1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.test.uiautomator;
18 
19 import static android.view.Display.INVALID_DISPLAY;
20 
21 import android.view.MotionEvent;
22 
23 import org.jspecify.annotations.NonNull;
24 
25 /**
26  * Allows you to set key parameters for running UiAutomator tests. The new settings take effect
27  * immediately and can be changed at any time during a test run.
28  *
29  * <p>To modify parameters, first obtain an instance by calling {@link #getInstance()}. As a best
30  * practice, make sure you always save the original value of any parameter that you are modifying.
31  * After running your tests with the modified parameters, make sure to also restore the original
32  * parameter values, otherwise this will impact other tests cases.
33  */
34 public final class Configurator {
35 
36     private long mWaitForIdleTimeout = 10_000; // ms
37     private long mWaitForSelector = 10_000; // ms
38     private long mWaitForActionAcknowledgment = 3_000; // ms
39 
40     // Scroll timeout used only in InteractionController
41     private long mScrollEventWaitTimeout = 1_000; // ms
42 
43     // Default is inject as fast as we can
44     private long mKeyInjectionDelay = 0; // ms
45 
46     // Default tool type is a finger
47     private int mToolType = MotionEvent.TOOL_TYPE_FINGER;
48 
49     // Default flags to use when calling Instrumentation.getUiAutomation(int)
50     static final int DEFAULT_UIAUTOMATION_FLAGS = 0;
51     private int mUiAutomationFlags = DEFAULT_UIAUTOMATION_FLAGS;
52 
53     // Default display ID when obtaining a BySelector instance
54     private int mDefaultDisplayId = INVALID_DISPLAY;
55 
56     // Singleton instance.
57     private static Configurator sConfigurator;
58 
Configurator()59     private Configurator() {}
60 
61     /**
62      * Retrieves a singleton instance of Configurator.
63      *
64      * @return Configurator instance
65      */
getInstance()66     public static @NonNull Configurator getInstance() {
67         if (sConfigurator == null) {
68             sConfigurator = new Configurator();
69         }
70         return sConfigurator;
71     }
72 
73     /**
74      * Sets the timeout for waiting for the user interface to go into an idle state before
75      * starting a UiAutomator action.
76      *
77      * @param timeout Timeout value in milliseconds
78      * @return self
79      */
setWaitForIdleTimeout(long timeout)80     public @NonNull Configurator setWaitForIdleTimeout(long timeout) {
81         mWaitForIdleTimeout = timeout;
82         return this;
83     }
84 
85     /**
86      * Gets the current timeout used for waiting for the user interface to go into an idle state
87      * before starting a UiAutomator action.
88      *
89      * @return current timeout in milliseconds
90      */
getWaitForIdleTimeout()91     public long getWaitForIdleTimeout() {
92         return mWaitForIdleTimeout;
93     }
94 
95     /**
96      * Sets the timeout for waiting for a {@link UiObject} to become visible in the user
97      * interface so that it can be matched by a {@link UiSelector}.
98      *
99      * <p>For {@link UiObject}s, the underlying node is fetched with this timeout before every
100      * action.
101      *
102      * <p>Has no effect on {@link UiObject2}s, which cache the underlying node. Instead, use
103      * {@link UiDevice#wait} and {@link Until#findObject} to wait for the object to become visible.
104      *
105      * @param timeout Timeout value in milliseconds
106      * @return self
107      */
setWaitForSelectorTimeout(long timeout)108     public @NonNull Configurator setWaitForSelectorTimeout(long timeout) {
109         mWaitForSelector = timeout;
110         return this;
111     }
112 
113     /**
114      * Gets the current timeout for waiting for a {@link UiObject} to become visible in the user
115      * interface so that it can be matched by a {@link UiSelector}.
116      *
117      * @return current timeout in milliseconds
118      */
getWaitForSelectorTimeout()119     public long getWaitForSelectorTimeout() {
120         return mWaitForSelector;
121     }
122 
123     /**
124      * Sets the timeout for waiting for an acknowledgement of a {@link UiScrollable} scroll action.
125      *
126      * <p>The acknowledgment is an {@link android.view.accessibility.AccessibilityEvent}
127      * corresponding to the scroll action that lets the framework determine if it was successful.
128      * Generally, this timeout should not be modified.
129      *
130      * <p>Has no effect on {@link UiObject2} scrolls.
131      *
132      * @param timeout Timeout value in milliseconds
133      * @return self
134      */
setScrollAcknowledgmentTimeout(long timeout)135     public @NonNull Configurator setScrollAcknowledgmentTimeout(long timeout) {
136         mScrollEventWaitTimeout = timeout;
137         return this;
138     }
139 
140     /**
141      * Gets the current timeout for waiting for an acknowledgement of a {@link UiScrollable}
142      * scroll action.
143      *
144      * @return current timeout in milliseconds
145      */
getScrollAcknowledgmentTimeout()146     public long getScrollAcknowledgmentTimeout() {
147         return mScrollEventWaitTimeout;
148     }
149 
150     /**
151      * Sets the timeout for waiting for an acknowledgment of a {@link UiObject} click.
152      *
153      * <p>The acknowledgment is an {@link android.view.accessibility.AccessibilityEvent}
154      * corresponding to a content change that lets the framework determine if the action was
155      * successful. Generally, this timeout should not be modified.
156      *
157      * <p>Has no effect on {@link UiDevice} and {@link UiObject2} clicks.
158      *
159      * @param timeout Timeout value in milliseconds
160      * @return self
161      */
setActionAcknowledgmentTimeout(long timeout)162     public @NonNull Configurator setActionAcknowledgmentTimeout(long timeout) {
163         mWaitForActionAcknowledgment = timeout;
164         return this;
165     }
166 
167     /**
168      * Gets the current timeout for waiting for an acknowledgment of a {@link UiObject} click.
169      *
170      * @return current timeout in milliseconds
171      */
getActionAcknowledgmentTimeout()172     public long getActionAcknowledgmentTimeout() {
173         return mWaitForActionAcknowledgment;
174     }
175 
176     /**
177      * Sets a delay between key presses when injecting text input.
178      *
179      * @param delay Delay value in milliseconds
180      * @return self
181      * @deprecated This parameter is no longer used (text is set directly rather than by key).
182      */
183     @Deprecated
setKeyInjectionDelay(long delay)184     public @NonNull Configurator setKeyInjectionDelay(long delay) {
185         mKeyInjectionDelay = delay;
186         return this;
187     }
188 
189     /**
190      * Gets the current delay between key presses when injecting text input.
191      *
192      * @return current delay in milliseconds
193      * @deprecated This parameter is no longer used (text is set directly rather than by key).
194      */
195     @Deprecated
getKeyInjectionDelay()196     public long getKeyInjectionDelay() {
197         return mKeyInjectionDelay;
198     }
199 
200     /**
201      * Sets the tool type to use for motion events.
202      *
203      * @param toolType The tool type to use
204      * @return self
205      * @see MotionEvent#getToolType(int)
206      * @see MotionEvent#TOOL_TYPE_FINGER
207      * @see MotionEvent#TOOL_TYPE_STYLUS
208      * @see MotionEvent#TOOL_TYPE_MOUSE
209      * @see MotionEvent#TOOL_TYPE_ERASER
210      * @see MotionEvent#TOOL_TYPE_UNKNOWN
211      */
setToolType(final int toolType)212     public @NonNull Configurator setToolType(final int toolType) {
213         mToolType = toolType;
214         return this;
215     }
216 
217     /**
218      * Gets the current tool type to use for motion events.
219      *
220      * @return current tool type
221      * @see MotionEvent#getToolType(int)
222      */
getToolType()223     public int getToolType() {
224         return mToolType;
225     }
226 
227     /**
228      * Sets the flags to use when obtaining a {@link android.app.UiAutomation} instance.
229      *
230      * @param flags The UiAutomation flags to use
231      * @return self
232      * @see android.app.Instrumentation#getUiAutomation(int)
233      * @see android.app.UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES
234      */
setUiAutomationFlags(int flags)235     public @NonNull Configurator setUiAutomationFlags(int flags) {
236         mUiAutomationFlags = flags;
237         return this;
238     }
239 
240     /**
241      * Gets the current flags that are used to obtain a {@link android.app.UiAutomation} instance.
242      *
243      * @return UiAutomation flags
244      * @see android.app.Instrumentation#getUiAutomation(int)
245      * @see android.app.UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES
246      */
getUiAutomationFlags()247     public int getUiAutomationFlags() {
248         return mUiAutomationFlags;
249     }
250 
251     /**
252      * Sets the default display ID to use when obtaining a
253      * {@link androidx.test.uiautomator.BySelector} instance. To avoid interfering with other tests,
254      * the caller must call {@link #resetDefaultDisplayId} when the test is finished.
255      *
256      * @param defaultDisplayId the default display ID to use
257      * @return self
258      */
setDefaultDisplayId(int defaultDisplayId)259     public @NonNull Configurator setDefaultDisplayId(int defaultDisplayId) {
260         mDefaultDisplayId = defaultDisplayId;
261         return this;
262     }
263 
264     /**
265      * Resets the default display ID to use when obtaining a
266      * {@link androidx.test.uiautomator.BySelector} instance.
267      *
268      * @return self
269      */
resetDefaultDisplayId()270     public @NonNull Configurator resetDefaultDisplayId() {
271         mDefaultDisplayId = INVALID_DISPLAY;
272         return this;
273     }
274 
275     /**
276      * Gets the default display ID to use when obtaining a
277      * {@link androidx.test.uiautomator.BySelector} instance, or returns
278      * {@link android.view.Display#INVALID_DISPLAY} if the default display ID is not set yet.
279      *
280      * @return the default display ID
281      */
getDefaultDisplayId()282     public int getDefaultDisplayId() {
283         return mDefaultDisplayId;
284     }
285 }
286