1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package android.windowanimationjank;
15 
16 import android.app.Instrumentation;
17 import android.app.UiAutomation;
18 import android.content.ComponentName;
19 import android.content.Intent;
20 import android.os.SystemClock;
21 
22 import androidx.test.uiautomator.By;
23 import androidx.test.uiautomator.BySelector;
24 import androidx.test.uiautomator.UiDevice;
25 import androidx.test.uiautomator.UiObject2;
26 import androidx.test.uiautomator.Until;
27 
28 /**
29  * Set of helpers to manipulate test activities.
30  */
31 public class Utils {
32     protected final static String PACKAGE = "android.windowanimationjank";
33     protected final static String ELEMENT_LAYOUT_ACTIVITY = "ElementLayoutActivity";
34     protected final static String ELEMENT_LAYOUT_CLASS = PACKAGE + "." + ELEMENT_LAYOUT_ACTIVITY;
35     protected final static long WAIT_FOR_ACTIVITY_TIMEOUT = 10000;
36     private static final BySelector ROOT_ELEMENT_LAYOUT = By.res(PACKAGE, "root_flow_layout");
37 
38     private final static long ROTATION_ANIMATION_TIME_FULL_SCREEN_MS = 1000;
39 
40     protected final static int ROTATION_MODE_NATURAL = 0;
41     protected final static int ROTATION_MODE_LEFT = 1;
42     protected final static int ROTATION_MODE_RIGHT = 2;
43 
waitForActivity(Instrumentation instrumentation, BySelector selector)44     private static UiObject2 waitForActivity(Instrumentation instrumentation, BySelector selector) {
45         UiDevice device = UiDevice.getInstance(instrumentation);
46         UiObject2 window = device.wait(Until.findObject(selector), WAIT_FOR_ACTIVITY_TIMEOUT);
47         if (window == null) {
48             throw new RuntimeException(selector.toString() + " has not been started.");
49         }
50 
51         // Get root object.
52         while (window.getParent() != null) {
53             window = window.getParent();
54         }
55         return window;
56     }
57 
waitForElementLayout(Instrumentation instrumentation)58     public static UiObject2 waitForElementLayout(Instrumentation instrumentation) {
59         return waitForActivity(instrumentation, ROOT_ELEMENT_LAYOUT);
60     }
61 
62     /**
63      * Start and return activity with requested number of random elements.
64      */
startElementLayout(Instrumentation instrumentation, int numElements)65     public static UiObject2 startElementLayout(Instrumentation instrumentation, int numElements) {
66         Intent intent = new Intent(Intent.ACTION_MAIN);
67         intent.setComponent(new ComponentName(PACKAGE, ELEMENT_LAYOUT_CLASS));
68         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
69         intent.putExtra(ElementLayoutActivity.NUM_ELEMENTS_KEY, numElements);
70         instrumentation.getTargetContext().startActivity(intent);
71         return waitForElementLayout(instrumentation);
72     }
73 
getDeviceRotation(Instrumentation instrumentation)74     public static int getDeviceRotation(Instrumentation instrumentation) {
75         try {
76             UiDevice device = UiDevice.getInstance(instrumentation);
77             switch (device.getDisplayRotation()) {
78             case UiAutomation.ROTATION_FREEZE_90:
79                 return ROTATION_MODE_LEFT;
80             case UiAutomation.ROTATION_FREEZE_270:
81                 return ROTATION_MODE_RIGHT;
82             case UiAutomation.ROTATION_FREEZE_0:
83             case UiAutomation.ROTATION_FREEZE_180:
84                 return ROTATION_MODE_NATURAL;
85             }
86         } catch(Exception e) {
87             throw new RuntimeException();
88         }
89         throw new RuntimeException("Unsupported device rotation.");
90     }
91 
rotateDevice(Instrumentation instrumentation, int rotationMode)92     public static void rotateDevice(Instrumentation instrumentation, int rotationMode) {
93         try {
94             UiDevice device = UiDevice.getInstance(instrumentation);
95             long startTime = System.currentTimeMillis();
96             switch (rotationMode) {
97             case ROTATION_MODE_NATURAL:
98                 device.setOrientationNatural();
99                 break;
100             case ROTATION_MODE_LEFT:
101                 device.setOrientationLeft();
102                 break;
103             case ROTATION_MODE_RIGHT:
104                 device.setOrientationRight();
105                 break;
106             default:
107                 throw new RuntimeException("Unsupported rotation mode: " + rotationMode);
108             }
109 
110             long toSleep = ROTATION_ANIMATION_TIME_FULL_SCREEN_MS -
111                     (System.currentTimeMillis() - startTime);
112             if (toSleep > 0) {
113                 SystemClock.sleep(toSleep);
114             }
115         } catch(Exception e) {
116             throw new RuntimeException(e);
117         }
118     }
119 }
120