UiObject.java revision 1078ab1070411af45d5e8ec3b56abec6789e7722
1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/* 2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project 3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License. 6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at 7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software 11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and 14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License. 15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.core; 18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 19c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtazimport android.graphics.Point; 20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.graphics.Rect; 21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.SystemClock; 22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.Log; 23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.KeyEvent; 24c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtazimport android.view.MotionEvent.PointerCoords; 25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo; 26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/** 2846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * A UiObject is a representation of a UI element. It is not in any way directly bound to a 2946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * UI element as an object reference. A UiObject holds information to help it 3046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * locate a matching UI element at runtime based on the {@link UiSelector} properties specified in 3146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * its constructor. Since a UiObject is a representative for a UI element, it can 3246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * be reused for different views with matching UI elements. 33dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class UiObject { 36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String LOG_TAG = UiObject.class.getSimpleName(); 37dbba713661688a285e701a006ce2d199296ac328Guang Zhu /** 38dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 390d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz * @deprecated use {@link Configurator#setWaitForSelectorTimeout(long)} 40dbba713661688a285e701a006ce2d199296ac328Guang Zhu **/ 410d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz @Deprecated 42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final long WAIT_FOR_SELECTOR_TIMEOUT = 10 * 1000; 43dbba713661688a285e701a006ce2d199296ac328Guang Zhu /** 44dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 45dbba713661688a285e701a006ce2d199296ac328Guang Zhu **/ 46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final long WAIT_FOR_SELECTOR_POLL = 1000; 47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // set a default timeout to 5.5s, since ANR threshold is 5s 48dbba713661688a285e701a006ce2d199296ac328Guang Zhu /** 49dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 50dbba713661688a285e701a006ce2d199296ac328Guang Zhu **/ 51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500; 52dbba713661688a285e701a006ce2d199296ac328Guang Zhu /** 53c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @since API Level 16 54c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz **/ 55c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz protected static final int SWIPE_MARGIN_LIMIT = 5; 56c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz /** 57dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 17 580d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz * @deprecated use {@link Configurator#setScrollAcknowledgmentTimeout(long)} 59dbba713661688a285e701a006ce2d199296ac328Guang Zhu **/ 600d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz @Deprecated 616088c8f9e34e34a4958b1601ed7c1bb34c95da21Adam Momtaz protected static final long WAIT_FOR_EVENT_TMEOUT = 3 * 1000; 62dbba713661688a285e701a006ce2d199296ac328Guang Zhu /** 63c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @since API Level 18 64dbba713661688a285e701a006ce2d199296ac328Guang Zhu **/ 65c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz protected static final int FINGER_TOUCH_HALF_WIDTH = 20; 66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 677f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz private final UiSelector mSelector; 68ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu private final UiAutomatorBridge mUiAutomationBridge; 69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 700d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz private final Configurator mConfig = Configurator.getInstance(); 710d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz 72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 733d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Constructs a UiObject to represent a specific UI element matched by the specified 743d50587be8ff021369c90554d814839335b445b0Adam Momtaz * {@link UiSelector} selector properties. 75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param selector 76dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 77e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 784ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject(UiSelector selector) { 79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mUiAutomationBridge = UiDevice.getInstance().getAutomatorBridge(); 80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mSelector = selector; 81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 843d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Debugging helper. A test can dump the properties of a selector as a string 853d50587be8ff021369c90554d814839335b445b0Adam Momtaz * to its logs if needed. <code>getSelector().toString();</code> 863d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 874ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @return {@link UiSelector} 88dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 904ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public final UiSelector getSelector() { 91f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 924ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return new UiSelector(mSelector); 93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 963d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Retrieves the {@link QueryController} to translate a {@link UiSelector} selector 973d50587be8ff021369c90554d814839335b445b0Adam Momtaz * into an {@link AccessibilityNodeInfo}. 983d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 99e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link QueryController} 100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 101ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu QueryController getQueryController() { 102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mUiAutomationBridge.getQueryController(); 103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1063d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Retrieves the {@link InteractionController} to perform finger actions such as tapping, 1073d50587be8ff021369c90554d814839335b445b0Adam Momtaz * swiping or entering text. 1083d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link InteractionController} 110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 111ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu InteractionController getInteractionController() { 112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mUiAutomationBridge.getInteractionController(); 113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 114e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 115e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1163d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Creates a new UiObject representing a child UI element of the element currently represented 1173d50587be8ff021369c90554d814839335b445b0Adam Momtaz * by this UiObject. 1183d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1193d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param selector for UI element to match 1203d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return a new UiObject representing the matched UI element 121dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 122e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 1234ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChild(UiSelector selector) throws UiObjectNotFoundException { 124f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(selector); 1254ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return new UiObject(getSelector().childSelector(selector)); 126e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 127e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 128e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1293d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Creates a new UiObject representing a child UI element from the parent element currently 1303d50587be8ff021369c90554d814839335b445b0Adam Momtaz * represented by this object. Essentially this is starting the search from the parent 1313d50587be8ff021369c90554d814839335b445b0Adam Momtaz * element and can also be used to find sibling UI elements to the one currently represented 1323d50587be8ff021369c90554d814839335b445b0Adam Momtaz * by this UiObject. 1333d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1343d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param selector for the UI element to match 1353d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return a new UiObject representing the matched UI element 136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 137dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 1394ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getFromParent(UiSelector selector) throws UiObjectNotFoundException { 140f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(selector); 1414ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return new UiObject(getSelector().fromParent(selector)); 142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 144e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1453d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Counts the child UI elements immediately under the UI element currently represented by 146e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * this UiObject. 1473d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 148e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return the count of child UI elements. 149e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 150dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 152e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public int getChildCount() throws UiObjectNotFoundException { 153f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 1540d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 155e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 156e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 157e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 158e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.getChildCount(); 159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 160e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1623d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Uses the member UiSelector properties to find a matching UI element reported in 1633d50587be8ff021369c90554d814839335b445b0Adam Momtaz * the accessibility hierarchy. 1643d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 165e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param timeout in milliseconds 166e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return AccessibilityNodeInfo if found else null 167dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 168e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 169e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected AccessibilityNodeInfo findAccessibilityNodeInfo(long timeout) { 170e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = null; 171bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz long startMills = SystemClock.uptimeMillis(); 172bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz long currentMills = 0; 173bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz while (currentMills <= timeout) { 174e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node = getQueryController().findAccessibilityNodeInfo(getSelector()); 175bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz if (node != null) { 176bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz break; 177bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz } else { 178bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz // does nothing if we're reentering another runWatchers() 179bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz UiDevice.getInstance().runWatchers(); 180bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz } 181bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz currentMills = SystemClock.uptimeMillis() - startMills; 182bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz if(timeout > 0) { 183bb36257f15f090966e2aeb9fd4f092e1a54722b1Adam Momtaz SystemClock.sleep(WAIT_FOR_SELECTOR_POLL); 184e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 185e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 186e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node; 187e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 188e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 189e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1908d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * Performs a drag of this object to a destination UiObject. Note that the number of steps 1918d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * used can influence the drag speed and varying speeds may impact the results. Consider 1928d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * evaluating different speeds when testing this method. 1938d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * 1948d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @param destObj 1958d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @param steps usually 40 steps. More or less to change the speed. 1968d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @return true of successful 1978d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @throws UiObjectNotFoundException 1988d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @since API Level 18 1998d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz */ 2008d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz public boolean dragTo(UiObject destObj, int steps) throws UiObjectNotFoundException { 2018d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz Rect srcRect = getVisibleBounds(); 2028d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz Rect dstRect = destObj.getVisibleBounds(); 2038d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz return getInteractionController().swipe(srcRect.centerX(), srcRect.centerY(), 2048d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz dstRect.centerX(), dstRect.centerY(), steps, true); 2058d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz } 2068d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz 2078d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz /** 2088d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * Performs a drag of this object to arbitrary coordinates. Note that the number of steps 2098d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * used will influence the drag speed and varying speeds may impact the results. Consider 2108d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * evaluating different speeds when testing this method. 2118d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * 2128d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @param destX 2138d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @param destY 2148d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @param steps 2158d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @return true of successful 2168d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @throws UiObjectNotFoundException 2178d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz * @since API Level 18 2188d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz */ 2198d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz public boolean dragTo(int destX, int destY, int steps) throws UiObjectNotFoundException { 2208d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz Rect srcRect = getVisibleBounds(); 2218d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz return getInteractionController().swipe(srcRect.centerX(), srcRect.centerY(), destX, destY, 2228d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz steps, true); 2238d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz } 2248d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz 2258d7e1dc0248bf9d3c7b133eaac79b7fb31321564Adam Momtaz /** 2263d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Perform the action on the UI element that is represented by this UiObject. Also see 2271893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)}, 2281893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. 2293d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 230467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 231467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 2323d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true of successful 233e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 234dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 235e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 236e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeUp(int steps) throws UiObjectNotFoundException { 237f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(steps); 2383d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 239e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.height() <= SWIPE_MARGIN_LIMIT * 2) 240e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 241e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.centerX(), 242e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.bottom - SWIPE_MARGIN_LIMIT, rect.centerX(), rect.top + SWIPE_MARGIN_LIMIT, 243e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu steps); 244e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 246e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 247e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform the action on the UI element that is represented by this object, Also see 2481893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)}, 2491893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. This method will 2501893caed0ad4e73b0676f206282d490c2d345316Thanh Le * perform the swipe gesture over any surface. The targeted UI element does not need to have 2511893caed0ad4e73b0676f206282d490c2d345316Thanh Le * the attribute <code>scrollable</code> set to <code>true</code> for this operation to be 2521893caed0ad4e73b0676f206282d490c2d345316Thanh Le * performed. 2533d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 2543d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 255467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 2563d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if successful 257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 258dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 259e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 260e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeDown(int steps) throws UiObjectNotFoundException { 261f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(steps); 2623d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.height() <= SWIPE_MARGIN_LIMIT * 2) 264e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 265e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.centerX(), 266e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.top + SWIPE_MARGIN_LIMIT, rect.centerX(), 267e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.bottom - SWIPE_MARGIN_LIMIT, steps); 268e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 269e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 270e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 271e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform the action on the UI element that is represented by this object. Also see 2721893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)}, 2731893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. This method will 2741893caed0ad4e73b0676f206282d490c2d345316Thanh Le * perform the swipe gesture over any surface. The targeted UI element does not need to have the 2751893caed0ad4e73b0676f206282d490c2d345316Thanh Le * attribute <code>scrollable</code> set to <code>true</code> for this operation to be 2761893caed0ad4e73b0676f206282d490c2d345316Thanh Le * performed. 2773d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 2783d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 279467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 2803d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if successful 281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 282dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 283e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 284e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeLeft(int steps) throws UiObjectNotFoundException { 285f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(steps); 2863d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 287e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.width() <= SWIPE_MARGIN_LIMIT * 2) 288e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 289e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.right - SWIPE_MARGIN_LIMIT, 290e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.centerY(), rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(), steps); 291e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 292e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 293e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 294e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform the action on the UI element that is represented by this object. Also see 2951893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)}, 2961893caed0ad4e73b0676f206282d490c2d345316Thanh Le * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. This method will 2971893caed0ad4e73b0676f206282d490c2d345316Thanh Le * perform the swipe gesture over any surface. The targeted UI element does not need to have the 2981893caed0ad4e73b0676f206282d490c2d345316Thanh Le * attribute <code>scrollable</code> set to <code>true</code> for this operation to be 2991893caed0ad4e73b0676f206282d490c2d345316Thanh Le * performed. 3003d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 3013d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 302467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 3033d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if successful 304e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 305dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 306e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 307e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeRight(int steps) throws UiObjectNotFoundException { 308f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(steps); 3093d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 310e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.width() <= SWIPE_MARGIN_LIMIT * 2) 311e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 312e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.left + SWIPE_MARGIN_LIMIT, 313e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.centerY(), rect.right - SWIPE_MARGIN_LIMIT, rect.centerY(), steps); 314e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3173d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Finds the visible bounds of a partially visible UI element 3183d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 319e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param node 3207f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * @return null if node is null, else a Rect containing visible bounds 321e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 322e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private Rect getVisibleBounds(AccessibilityNodeInfo node) { 323e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (node == null) { 324e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return null; 325e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 326e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 327e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // targeted node's bounds 32823296fc6448cd265fbb45c1fd9041976ae0da274Guang Zhu int w = UiDevice.getInstance().getDisplayWidth(); 32923296fc6448cd265fbb45c1fd9041976ae0da274Guang Zhu int h = UiDevice.getInstance().getDisplayHeight(); 33023296fc6448cd265fbb45c1fd9041976ae0da274Guang Zhu Rect nodeRect = AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node, w, h); 331e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 332e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // is the targeted node within a scrollable container? 333e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo scrollableParentNode = getScrollableParent(node); 334e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(scrollableParentNode == null) { 335e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // nothing to adjust for so return the node's Rect as is 336e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return nodeRect; 337e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 338e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 339e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Scrollable parent's visible bounds 3407f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz Rect parentRect = AccessibilityNodeInfoHelper 34123296fc6448cd265fbb45c1fd9041976ae0da274Guang Zhu .getVisibleBoundsInScreen(scrollableParentNode, w, h); 342e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // adjust for partial clipping of targeted by parent node if required 343e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu nodeRect.intersect(parentRect); 344e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return nodeRect; 345e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 346e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 347e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3487f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * Walk the hierarchy up to find a scrollable parent. A scrollable parent 3497f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * indicates that this node may be in a content where it is partially 3507f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * visible due to scrolling. its clickable center maybe invisible and 3517f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * adjustments should be made to the click coordinates. 3523d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 353e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param node 3541893caed0ad4e73b0676f206282d490c2d345316Thanh Le * @return The accessibility node info. 355e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 356e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private AccessibilityNodeInfo getScrollableParent(AccessibilityNodeInfo node) { 357e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo parent = node; 358e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu while(parent != null) { 359e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu parent = parent.getParent(); 360e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (parent != null && parent.isScrollable()) { 361e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return parent; 362e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 363e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 364e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return null; 365e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 366e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 367e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3683d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Performs a click at the center of the visible bounds of the UI element represented 36946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * by this UiObject. 3703d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 371e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true id successful else false 372e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 373dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 374e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 375e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean click() throws UiObjectNotFoundException { 376f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 3770d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 378e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 379e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 380e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 381e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 3820d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz return getInteractionController().clickAndSync(rect.centerX(), rect.centerY(), 3830d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz mConfig.getActionAcknowledgmentTimeout()); 384e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 385e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 386e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3873d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link #clickAndWaitForNewWindow(long)} 388a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz * This method is intended to reliably wait for window transitions that would typically take 389a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz * longer than the usual default timeouts. 3903d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 3913d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if the event was triggered, else false 3923d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @throws UiObjectNotFoundException 393dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 3943d50587be8ff021369c90554d814839335b445b0Adam Momtaz */ 395e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickAndWaitForNewWindow() throws UiObjectNotFoundException { 396f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 397e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return clickAndWaitForNewWindow(WAIT_FOR_WINDOW_TMEOUT); 398e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 399e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 400e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 40146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Performs a click at the center of the visible bounds of the UI element represented 40246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * by this UiObject and waits for window transitions. 40346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 4043d50587be8ff021369c90554d814839335b445b0Adam Momtaz * This method differ from {@link UiObject#click()} only in that this method waits for a 40546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * a new window transition as a result of the click. Some examples of a window transition: 406e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <li>launching a new activity</li> 407e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <li>bringing up a pop-up menu</li> 408e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <li>bringing up a dialog</li> 409e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 4103d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param timeout timeout before giving up on waiting for a new window 411e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if the event was triggered, else false 412e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 413dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 414e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 415e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickAndWaitForNewWindow(long timeout) throws UiObjectNotFoundException { 416f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(timeout); 4170d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 418e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 419e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 420e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 421e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 4220d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz return getInteractionController().clickAndWaitForNewWindow(rect.centerX(), rect.centerY(), 4230d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz mConfig.getActionAcknowledgmentTimeout()); 424e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 425e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 426e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4273d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Clicks the top and left corner of the UI element 4283d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 429e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on success 4301893caed0ad4e73b0676f206282d490c2d345316Thanh Le * @throws UiObjectNotFoundException 431dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 432e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 433e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickTopLeft() throws UiObjectNotFoundException { 434f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 4350d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 436e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 437e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 438e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 439e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 4401dc7d12406947faaee8454c6efb2a0631f5da573Adam Momtaz return getInteractionController().clickNoSync(rect.left + 5, rect.top + 5); 441e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 442e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 443e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4443d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Long clicks bottom and right corner of the UI element 4453d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 446e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation was successful 447e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 448dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 449e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 450e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean longClickBottomRight() throws UiObjectNotFoundException { 451f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 4520d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 453e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 454e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 455e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 456e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 4571dc7d12406947faaee8454c6efb2a0631f5da573Adam Momtaz return getInteractionController().longTapNoSync(rect.right - 5, rect.bottom - 5); 458e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 459e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 460e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4613d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Clicks the bottom and right corner of the UI element 4623d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 463e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on success 4641893caed0ad4e73b0676f206282d490c2d345316Thanh Le * @throws UiObjectNotFoundException 465dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 466e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 467e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickBottomRight() throws UiObjectNotFoundException { 468f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 4690d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 470e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 471e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 472e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 473e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 4741dc7d12406947faaee8454c6efb2a0631f5da573Adam Momtaz return getInteractionController().clickNoSync(rect.right - 5, rect.bottom - 5); 475e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 476e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 477e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4783d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Long clicks the center of the visible bounds of the UI element 4793d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 480e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation was successful 481e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 482dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 483e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 484e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean longClick() throws UiObjectNotFoundException { 485f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 4860d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 487e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 488e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 489e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 490e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 4911dc7d12406947faaee8454c6efb2a0631f5da573Adam Momtaz return getInteractionController().longTapNoSync(rect.centerX(), rect.centerY()); 492e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 493e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 494e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4953d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Long clicks on the top and left corner of the UI element 4963d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 497e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation was successful 498e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 499dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 500e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 501e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean longClickTopLeft() throws UiObjectNotFoundException { 502f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 5030d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 504e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 505e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 506e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 507e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 5081dc7d12406947faaee8454c6efb2a0631f5da573Adam Momtaz return getInteractionController().longTapNoSync(rect.left + 5, rect.top + 5); 509e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 510e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 511e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5123d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Reads the <code>text</code> property of the UI element 5133d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 514e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return text value of the current node represented by this UiObject 515e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException if no match could be found 516dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 517e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 518e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public String getText() throws UiObjectNotFoundException { 519f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 5200d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 521e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 522e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 523e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 524e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String retVal = safeStringReturn(node.getText()); 525e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, String.format("getText() = %s", retVal)); 526e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return retVal; 527e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 528e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 529e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 53097835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz * Reads the <code>className</code> property of the UI element 53197835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz * 53297835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz * @return class name of the current node represented by this UiObject 53397835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz * @throws UiObjectNotFoundException if no match could be found 53497835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz * @since API Level 18 53597835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz */ 53697835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz public String getClassName() throws UiObjectNotFoundException { 53797835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz Tracer.trace(); 5380d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 53997835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz if(node == null) { 54097835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 54197835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz } 54297835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz String retVal = safeStringReturn(node.getClassName()); 54397835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz Log.d(LOG_TAG, String.format("getClassName() = %s", retVal)); 54497835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz return retVal; 54597835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz } 54697835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz 54797835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz /** 5483d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Reads the <code>content_desc</code> property of the UI element 5493d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 550e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return value of node attribute "content_desc" 551e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 552dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 553e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 554e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public String getContentDescription() throws UiObjectNotFoundException { 555f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 5560d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 557e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 558e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 559e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 560e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return safeStringReturn(node.getContentDescription()); 561e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 562e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 563e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 56446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Sets the text in an editable field, after clearing the field's content. 56546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 56646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * The {@link UiSelector} selector of this object must reference a UI element that is editable. 56746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 56846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * When you call this method, the method first simulates a {@link #click()} on 56946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * editable field to set focus. The method then clears the field's contents 57046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * and injects your specified text into the field. 5713d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 57246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * If you want to capture the original contents of the field, call {@link #getText()} first. 57346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * You can then modify the text and use this method to update the field. 57446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 57546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @param text string to set 576e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation is successful 577e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 578dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 579e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 580e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean setText(String text) throws UiObjectNotFoundException { 581f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(text); 582e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu clearTextField(); 583e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().sendText(text); 584e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 585e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 586e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 58746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Clears the existing text contents in an editable field. 58846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 58946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * The {@link UiSelector} of this object must reference a UI element that is editable. 59046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 59146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * When you call this method, the method first sets focus at the start edge of the field. 59246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * The method then simulates a long-press to select the existing text, and deletes the 59346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * selected text. 59446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 59546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * If a "Select-All" option is displayed, the method will automatically attempt to use it 59646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * to ensure full text selection. 59746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 59846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Note that it is possible that not all the text in the field is selected; for example, 59946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * if the text contains separators such as spaces, slashes, at symbol etc. 60046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Also, not all editable fields support the long-press functionality. 60146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 602e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 603dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 604e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 605e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void clearTextField() throws UiObjectNotFoundException { 606f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 607e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // long click left + center 6080d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 609e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 610e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 611e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 612e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 6131dc7d12406947faaee8454c6efb2a0631f5da573Adam Momtaz getInteractionController().longTapNoSync(rect.left + 20, rect.centerY()); 614e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // check if the edit menu is open 6154ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz UiObject selectAll = new UiObject(new UiSelector().descriptionContains("Select all")); 616e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(selectAll.waitForExists(50)) 617e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu selectAll.click(); 618e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // wait for the selection 619e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu SystemClock.sleep(250); 620e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // delete it 621e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu getInteractionController().sendKey(KeyEvent.KEYCODE_DEL, 0); 622e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 623e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 624e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6253d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>checked</code> property is currently true 6263d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 627e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 628dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 629e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 630e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isChecked() throws UiObjectNotFoundException { 631f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 6320d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 633e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 634e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 635e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 636e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isChecked(); 637e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 638e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 639e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6403d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>selected</code> property is currently true 6413d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 642e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 643e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 644dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 645e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 646e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isSelected() throws UiObjectNotFoundException { 647f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 6480d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 649e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 650e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 651e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 652e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isSelected(); 653e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 654e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 655e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6563d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>checkable</code> property is currently true 6573d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 658e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 659e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 660dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 661e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 662e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isCheckable() throws UiObjectNotFoundException { 663f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 6640d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 665e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 666e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 667e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 668e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isCheckable(); 669e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 670e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 671e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6723d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>enabled</code> property is currently true 6733d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 674e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 675e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 676dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 677e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 678e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isEnabled() throws UiObjectNotFoundException { 679f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 6800d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 681e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 682e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 683e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 684e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isEnabled(); 685e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 686e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 687e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6883d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>clickable</code> property is currently true 6893d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 690e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 691e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 692dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 693e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 694e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isClickable() throws UiObjectNotFoundException { 695f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 6960d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 697e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 698e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 699e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 700e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isClickable(); 701e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 702e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 703e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 7043d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>focused</code> property is currently true 7053d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 706e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 707e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 708dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 709e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 710e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isFocused() throws UiObjectNotFoundException { 711f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 7120d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 713e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 714e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 715e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 716e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isFocused(); 717e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 718e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 719e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 7203d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>focusable</code> property is currently true 7213d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 722e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 723e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 724dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 725e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 726e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isFocusable() throws UiObjectNotFoundException { 727f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 7280d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 729e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 730e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 731e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 732e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isFocusable(); 733e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 734e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 735e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 7363d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>scrollable</code> property is currently true 7373d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 738e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 739e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 740dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 741e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 742e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isScrollable() throws UiObjectNotFoundException { 743f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 7440d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 745e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 746e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 747e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 748e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isScrollable(); 749e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 750e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 751e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 7523d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>long-clickable</code> property is currently true 7533d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 754e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 755e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 756dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 757e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 758e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isLongClickable() throws UiObjectNotFoundException { 759f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 7600d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 761e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 762e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 763e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 764e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isLongClickable(); 765e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 766e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 767e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 7683d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Reads the UI element's <code>package</code> property 7693d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 7703d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if it is else false 771e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 772dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 773e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 774e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public String getPackageName() throws UiObjectNotFoundException { 775f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 7760d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 777e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 778e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 779e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 780e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return safeStringReturn(node.getPackageName()); 781e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 782e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 783e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 78446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Returns the visible bounds of the UI element. 78546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 78646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * If a portion of the UI element is visible, only the bounds of the visible portion are 78746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * reported. 7883d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 789e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return Rect 790e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 7911893caed0ad4e73b0676f206282d490c2d345316Thanh Le * @see {@link #getBounds()} 79279693ede92636fe6f3a6ec4dc049a438fd9504ffGuang Zhu * @since API Level 17 793e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 7943d50587be8ff021369c90554d814839335b445b0Adam Momtaz public Rect getVisibleBounds() throws UiObjectNotFoundException { 795f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 7960d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 797e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 798e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 799e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 800e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getVisibleBounds(node); 801e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 802e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 803e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 80446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Returns the UI element's <code>bounds</code> property. See {@link #getVisibleBounds()} 8053d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 8063d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return Rect 8073d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @throws UiObjectNotFoundException 808dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 8093d50587be8ff021369c90554d814839335b445b0Adam Momtaz */ 8103d50587be8ff021369c90554d814839335b445b0Adam Momtaz public Rect getBounds() throws UiObjectNotFoundException { 811f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 8120d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 8133d50587be8ff021369c90554d814839335b445b0Adam Momtaz if(node == null) { 8143d50587be8ff021369c90554d814839335b445b0Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 8153d50587be8ff021369c90554d814839335b445b0Adam Momtaz } 8163d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect nodeRect = new Rect(); 8173d50587be8ff021369c90554d814839335b445b0Adam Momtaz node.getBoundsInScreen(nodeRect); 8183d50587be8ff021369c90554d814839335b445b0Adam Momtaz 8193d50587be8ff021369c90554d814839335b445b0Adam Momtaz return nodeRect; 8203d50587be8ff021369c90554d814839335b445b0Adam Momtaz } 8213d50587be8ff021369c90554d814839335b445b0Adam Momtaz 8223d50587be8ff021369c90554d814839335b445b0Adam Momtaz /** 82346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Waits a specified length of time for a UI element to become visible. 82446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 82546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * This method waits until the UI element becomes visible on the display, or 82646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * until the timeout has elapsed. You can use this method in situations where 82746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * the content that you want to select is not immediately displayed. 8283d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 82946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @param timeout the amount of time to wait (in milliseconds) 83046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @return true if the UI element is displayed, else false if timeout elapsed while waiting 831dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 832e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 833e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean waitForExists(long timeout) { 834f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(timeout); 835e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(findAccessibilityNodeInfo(timeout) != null) { 836e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 837e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 838e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 839e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 840e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 841e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 84246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Waits a specified length of time for a UI element to become undetectable. 8433d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 84446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * This method waits until a UI element is no longer matchable, or until the 84546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * timeout has elapsed. 84646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 84746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * A UI element becomes undetectable when the {@link UiSelector} of the object is 84846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * unable to find a match because the element has either changed its state or is no 84946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * longer displayed. 85046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 85146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * You can use this method when attempting to wait for some long operation 85246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * to compete, such as downloading a large file or connecting to a remote server. 85346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 85446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @param timeout time to wait (in milliseconds) 85546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @return true if the element is gone before timeout elapsed, else false if timeout elapsed 85646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * but a matching element is still found. 857dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 858e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 859e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean waitUntilGone(long timeout) { 860f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(timeout); 861e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu long startMills = SystemClock.uptimeMillis(); 862e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu long currentMills = 0; 863e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu while (currentMills <= timeout) { 864e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(findAccessibilityNodeInfo(0) == null) 865e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 866e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu currentMills = SystemClock.uptimeMillis() - startMills; 867e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(timeout > 0) 868e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu SystemClock.sleep(WAIT_FOR_SELECTOR_POLL); 869e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 870e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 871e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 872e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 873e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 87446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Check if UI element exists. 87546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 876e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * This methods performs a {@link #waitForExists(long)} with zero timeout. This 877e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * basically returns immediately whether the UI element represented by this UiObject 878e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * exists or not. If you need to wait longer for this UI element, then see 879e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #waitForExists(long)}. 8803d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 881e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if the UI element represented by this UiObject does exist 882dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16 883e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 884e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean exists() { 885f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine Tracer.trace(); 886e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return waitForExists(0); 887e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 888e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 889e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private String safeStringReturn(CharSequence cs) { 890e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(cs == null) 891e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return ""; 892e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return cs.toString(); 893e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 894c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 895c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz /** 896c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * PinchOut generates a 2 pointer gesture where each pointer is moving from the center out 897c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * away from each other diagonally towards the edges of the current UI element represented by 898c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * this UiObject. 899c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param percent of the object's diagonal length to use for the pinch 900c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 901c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 9021078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 9031078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * <code>false</code> otherwise 904c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @throws UiObjectNotFoundException 905c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @since API Level 18 906c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz */ 9071078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu public boolean pinchOut(int percent, int steps) throws UiObjectNotFoundException { 908c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // make value between 1 and 100 909c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz percent = (percent < 0) ? 1 : (percent > 100) ? 100 : percent; 910c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz float percentage = percent / 100f; 911c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 9120d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 913c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz if (node == null) { 914c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 915c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 916c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 917c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Rect rect = getVisibleBounds(node); 918c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2) 919c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz throw new IllegalStateException("Object width is too small for operation"); 920c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 921c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // start from the same point at the center of the control 922c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point startPoint1 = new Point(rect.centerX() - FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 923c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point startPoint2 = new Point(rect.centerX() + FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 924c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 925c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // End at the top-left and bottom-right corners of the control 926c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point endPoint1 = new Point(rect.centerX() - (int)((rect.width()/2) * percentage), 927c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz rect.centerY()); 928c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point endPoint2 = new Point(rect.centerX() + (int)((rect.width()/2) * percentage), 929c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz rect.centerY()); 930c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 9311078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu return performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps); 932c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 933c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 934c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz /** 935c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * PinchIn generates a 2 pointer gesture where each pointer is moving towards the other 936c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * diagonally from the edges of the current UI element represented by this UiObject, until the 937c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * center. 938c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param percent of the object's diagonal length to use for the pinch 939c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 940c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 9411078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 9421078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * <code>false</code> otherwise 943c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @throws UiObjectNotFoundException 944c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @since API Level 18 945c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz */ 9461078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu public boolean pinchIn(int percent, int steps) throws UiObjectNotFoundException { 947c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // make value between 1 and 100 948c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz percent = (percent < 0) ? 0 : (percent > 100) ? 100 : percent; 949c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz float percentage = percent / 100f; 950c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 9510d3e425526a214d355e87b0c90f1b85c8aefe35aAdam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 952c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz if (node == null) { 953c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 954c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 955c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 956c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Rect rect = getVisibleBounds(node); 957c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2) 958c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz throw new IllegalStateException("Object width is too small for operation"); 959c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 960c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point startPoint1 = new Point(rect.centerX() - (int)((rect.width()/2) * percentage), 961c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz rect.centerY()); 962c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point startPoint2 = new Point(rect.centerX() + (int)((rect.width()/2) * percentage), 963c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz rect.centerY()); 964c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 965c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point endPoint1 = new Point(rect.centerX() - FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 966c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point endPoint2 = new Point(rect.centerX() + FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 967c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 9681078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu return performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps); 969c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 970c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 971c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz /** 972c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * Generates a 2 pointer gesture from an arbitrary starting and ending points. 973c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * 974c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param startPoint1 start point of pointer 1 975c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param startPoint2 start point of pointer 2 976c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param endPoint1 end point of pointer 1 977c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param endPoint2 end point of pointer 2 978c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 979c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 9801078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 9811078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * <code>false</code> otherwise 982c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @since API Level 18 983c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz */ 9841078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu public boolean performTwoPointerGesture(Point startPoint1, Point startPoint2, Point endPoint1, 985c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz Point endPoint2, int steps) { 986c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 987c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // avoid a divide by zero 988c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz if(steps == 0) 989c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz steps = 1; 990c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 991c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz final float stepX1 = (endPoint1.x - startPoint1.x) / steps; 992c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz final float stepY1 = (endPoint1.y - startPoint1.y) / steps; 993c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz final float stepX2 = (endPoint2.x - startPoint2.x) / steps; 994c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz final float stepY2 = (endPoint2.y - startPoint2.y) / steps; 995c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 996c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz int eventX1, eventY1, eventX2, eventY2; 997c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventX1 = startPoint1.x; 998c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventY1 = startPoint1.y; 999c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventX2 = startPoint2.x; 1000c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventY2 = startPoint2.y; 1001c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1002c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // allocate for steps plus first down and last up 1003c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz PointerCoords[] points1 = new PointerCoords[steps + 2]; 1004c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz PointerCoords[] points2 = new PointerCoords[steps + 2]; 1005c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1006c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // Include the first and last touch downs in the arrays of steps 1007c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz for (int i = 0; i < steps + 1; i++) { 1008c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz PointerCoords p1 = new PointerCoords(); 1009c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.x = eventX1; 1010c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.y = eventY1; 1011c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.pressure = 1; 1012c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.size = 1; 1013c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz points1[i] = p1; 1014c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1015c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz PointerCoords p2 = new PointerCoords(); 1016c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.x = eventX2; 1017c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.y = eventY2; 1018c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.pressure = 1; 1019c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.size = 1; 1020c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz points2[i] = p2; 1021c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1022c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventX1 += stepX1; 1023c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventY1 += stepY1; 1024c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventX2 += stepX2; 1025c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz eventY2 += stepY2; 1026c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 1027c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1028c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz // ending pointers coordinates 1029c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz PointerCoords p1 = new PointerCoords(); 1030c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.x = endPoint1.x; 1031c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.y = endPoint1.y; 1032c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.pressure = 1; 1033c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p1.size = 1; 1034c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz points1[steps + 1] = p1; 1035c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1036c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz PointerCoords p2 = new PointerCoords(); 1037c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.x = endPoint2.x; 1038c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.y = endPoint2.y; 1039c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.pressure = 1; 1040c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz p2.size = 1; 1041c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz points2[steps + 1] = p2; 1042c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 10431078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu return performMultiPointerGesture(points1, points2); 1044c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 1045c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz 1046c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz /** 1047c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * Performs a multi-touch gesture 1048c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * 1049c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * Takes a series of touch coordinates for at least 2 pointers. Each pointer must have 1050c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * all of its touch steps defined in an array of {@link PointerCoords}. By having the ability 1051c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * to specify the touch points along the path of a pointer, the caller is able to specify 1052c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * complex gestures like circles, irregular shapes etc, where each pointer may take a 1053c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * different path. 1054c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * 1055c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * To create a single point on a pointer's touch path 1056c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * <code> 1057c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * PointerCoords p = new PointerCoords(); 1058c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * p.x = stepX; 1059c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * p.y = stepY; 1060c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * p.pressure = 1; 1061c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * p.size = 1; 1062c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * </code> 1063c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @param touches each array of {@link PointerCoords} constitute a single pointer's touch path. 1064c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * Multiple {@link PointerCoords} arrays constitute multiple pointers, each with its own 1065c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * path. Each {@link PointerCoords} in an array constitute a point on a pointer's path. 10661078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 10671078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu * <code>false</code> otherwise 1068c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz * @since API Level 18 1069c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz */ 10701078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu public boolean performMultiPointerGesture(PointerCoords[] ...touches) { 10711078ab1070411af45d5e8ec3b56abec6789e7722Guang Zhu return getInteractionController().performMultiPointerGesture(touches); 1072c344be11dbfd56e95d076f46b870108fdaa662f0Adam Momtaz } 1073b4671570eb1caa88c7b6042f81f1ca3a2cb6a916Guang Zhu} 1074