1ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu/* 2ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * Copyright (C) 2012 The Android Open Source Project 3ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * 4ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * you may not use this file except in compliance with the License. 6ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * You may obtain a copy of the License at 7ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * 8ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 9ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * 10ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * Unless required by applicable law or agreed to in writing, software 11ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * See the License for the specific language governing permissions and 14ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * limitations under the License. 15ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 16ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 17ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhupackage com.android.uiautomator.core; 18ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 1997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtazimport android.graphics.Point; 20ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhuimport android.graphics.Rect; 21ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhuimport android.os.SystemClock; 22ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhuimport android.util.Log; 23ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhuimport android.view.KeyEvent; 2497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtazimport android.view.MotionEvent.PointerCoords; 25ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo; 26ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 27ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu/** 28753092685410ea01dbb122162cd40cac48332ae1quddusc * A UiObject is a representation of a view. It is not in any way directly bound to a 29753092685410ea01dbb122162cd40cac48332ae1quddusc * view as an object reference. A UiObject contains information to help it 30753092685410ea01dbb122162cd40cac48332ae1quddusc * locate a matching view at runtime based on the {@link UiSelector} properties specified in 31753092685410ea01dbb122162cd40cac48332ae1quddusc * its constructor. Once you create an instance of a UiObject, it can 32753092685410ea01dbb122162cd40cac48332ae1quddusc * be reused for different views that match the selector criteria. 33d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 34ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 35ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhupublic class UiObject { 36ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu private static final String LOG_TAG = UiObject.class.getSimpleName(); 37d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu /** 38d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 39bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz * @deprecated use {@link Configurator#setWaitForSelectorTimeout(long)} 40d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu **/ 41bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz @Deprecated 42ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu protected static final long WAIT_FOR_SELECTOR_TIMEOUT = 10 * 1000; 43d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu /** 44d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 45d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu **/ 46ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu protected static final long WAIT_FOR_SELECTOR_POLL = 1000; 47ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // set a default timeout to 5.5s, since ANR threshold is 5s 48d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu /** 49d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 50d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu **/ 51ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500; 52d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu /** 5397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @since API Level 16 5497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz **/ 5597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz protected static final int SWIPE_MARGIN_LIMIT = 5; 5697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz /** 57d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 17 58bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz * @deprecated use {@link Configurator#setScrollAcknowledgmentTimeout(long)} 59d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu **/ 60bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz @Deprecated 61fa9a4a7575f0bf4a948ab169ff249f57258f35b6Adam Momtaz protected static final long WAIT_FOR_EVENT_TMEOUT = 3 * 1000; 62d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu /** 6397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @since API Level 18 64d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu **/ 6597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz protected static final int FINGER_TOUCH_HALF_WIDTH = 20; 66ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 6773da7f69437c911dc60cc3b9ad7ad876677c8f14Adam Momtaz private final UiSelector mSelector; 68ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 69bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz private final Configurator mConfig = Configurator.getInstance(); 70bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz 71ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 72753092685410ea01dbb122162cd40cac48332ae1quddusc * Constructs a UiObject to represent a view that matches the specified 73753092685410ea01dbb122162cd40cac48332ae1quddusc * selector criteria. 74ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @param selector 75d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 76ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 77dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz public UiObject(UiSelector selector) { 78ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu mSelector = selector; 79ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 80ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 81ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 82f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Debugging helper. A test can dump the properties of a selector as a string 83f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * to its logs if needed. <code>getSelector().toString();</code> 84f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 85dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz * @return {@link UiSelector} 86d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 87ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 88dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz public final UiSelector getSelector() { 89b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 90dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz return new UiSelector(mSelector); 91ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 92ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 93ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 94f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Retrieves the {@link QueryController} to translate a {@link UiSelector} selector 95f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * into an {@link AccessibilityNodeInfo}. 96f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 97ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return {@link QueryController} 98ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 995a5e8ca8a086bd87b7753cbd3c46ff1ca72292a2Guang Zhu QueryController getQueryController() { 10017fac436d78f6ac642386a245fb4fdb7243a91a4Guang Zhu return UiDevice.getInstance().getAutomatorBridge().getQueryController(); 101ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 102ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 103ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 104f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Retrieves the {@link InteractionController} to perform finger actions such as tapping, 105753092685410ea01dbb122162cd40cac48332ae1quddusc * swiping, or entering text. 106f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 107ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return {@link InteractionController} 108ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 1095a5e8ca8a086bd87b7753cbd3c46ff1ca72292a2Guang Zhu InteractionController getInteractionController() { 11017fac436d78f6ac642386a245fb4fdb7243a91a4Guang Zhu return UiDevice.getInstance().getAutomatorBridge().getInteractionController(); 111ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 112ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 113ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 114753092685410ea01dbb122162cd40cac48332ae1quddusc * Creates a new UiObject for a child view that is under the present UiObject. 115f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 116753092685410ea01dbb122162cd40cac48332ae1quddusc * @param selector for child view to match 117753092685410ea01dbb122162cd40cac48332ae1quddusc * @return a new UiObject representing the child view 118d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 119ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 120dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz public UiObject getChild(UiSelector selector) throws UiObjectNotFoundException { 121b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(selector); 122dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz return new UiObject(getSelector().childSelector(selector)); 123ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 124ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 125ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 126753092685410ea01dbb122162cd40cac48332ae1quddusc * Creates a new UiObject for a sibling view or a child of the sibling view, 127753092685410ea01dbb122162cd40cac48332ae1quddusc * relative to the present UiObject. 128f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 129753092685410ea01dbb122162cd40cac48332ae1quddusc * @param selector for a sibling view or children of the sibling view 130753092685410ea01dbb122162cd40cac48332ae1quddusc * @return a new UiObject representing the matched view 131ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 132d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 133ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 134dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz public UiObject getFromParent(UiSelector selector) throws UiObjectNotFoundException { 135b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(selector); 136dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz return new UiObject(getSelector().fromParent(selector)); 137ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 138ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 139ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 140753092685410ea01dbb122162cd40cac48332ae1quddusc * Counts the child views immediately under the present UiObject. 141f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 142753092685410ea01dbb122162cd40cac48332ae1quddusc * @return the count of child views. 143ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 144d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 145ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 146ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public int getChildCount() throws UiObjectNotFoundException { 147b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 148bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 149ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 150ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 151ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 152ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.getChildCount(); 153ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 154ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 155ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 156753092685410ea01dbb122162cd40cac48332ae1quddusc * Finds a matching UI element in the accessibility hierarchy, by 157753092685410ea01dbb122162cd40cac48332ae1quddusc * using the selector for this UiObject. 158f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 159ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @param timeout in milliseconds 160ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return AccessibilityNodeInfo if found else null 161d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 162ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 163ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu protected AccessibilityNodeInfo findAccessibilityNodeInfo(long timeout) { 164ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu AccessibilityNodeInfo node = null; 165f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz long startMills = SystemClock.uptimeMillis(); 166f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz long currentMills = 0; 167f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz while (currentMills <= timeout) { 168ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu node = getQueryController().findAccessibilityNodeInfo(getSelector()); 169f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz if (node != null) { 170f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz break; 171f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz } else { 172f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz // does nothing if we're reentering another runWatchers() 173f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz UiDevice.getInstance().runWatchers(); 174f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz } 175f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz currentMills = SystemClock.uptimeMillis() - startMills; 176f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz if(timeout > 0) { 177f510bdfd84fd93b9ecf3967d37df4f402b9f1806Adam Momtaz SystemClock.sleep(WAIT_FOR_SELECTOR_POLL); 178ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 179ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 180ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node; 181ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 182ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 183ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 184753092685410ea01dbb122162cd40cac48332ae1quddusc * Drags this object to a destination UiObject. 185753092685410ea01dbb122162cd40cac48332ae1quddusc * The number of steps specified in your input parameter can influence the 186753092685410ea01dbb122162cd40cac48332ae1quddusc * drag speed, and varying speeds may impact the results. Consider 187753092685410ea01dbb122162cd40cac48332ae1quddusc * evaluating different speeds when using this method in your tests. 188516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz * 189753092685410ea01dbb122162cd40cac48332ae1quddusc * @param destObj the destination UiObject. 190753092685410ea01dbb122162cd40cac48332ae1quddusc * @param steps usually 40 steps. You can increase or decrease the steps to change the speed. 191753092685410ea01dbb122162cd40cac48332ae1quddusc * @return true if successful 192516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz * @throws UiObjectNotFoundException 193516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz * @since API Level 18 194516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz */ 195516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz public boolean dragTo(UiObject destObj, int steps) throws UiObjectNotFoundException { 196516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz Rect srcRect = getVisibleBounds(); 197516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz Rect dstRect = destObj.getVisibleBounds(); 198516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz return getInteractionController().swipe(srcRect.centerX(), srcRect.centerY(), 199516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz dstRect.centerX(), dstRect.centerY(), steps, true); 200516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz } 201516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz 202516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz /** 203753092685410ea01dbb122162cd40cac48332ae1quddusc * Drags this object to arbitrary coordinates. 204753092685410ea01dbb122162cd40cac48332ae1quddusc * The number of steps specified in your input parameter can influence the 205753092685410ea01dbb122162cd40cac48332ae1quddusc * drag speed, and varying speeds may impact the results. Consider 206753092685410ea01dbb122162cd40cac48332ae1quddusc * evaluating different speeds when using this method in your tests. 207516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz * 208753092685410ea01dbb122162cd40cac48332ae1quddusc * @param destX the X-axis coordinate. 209753092685410ea01dbb122162cd40cac48332ae1quddusc * @param destY the Y-axis coordinate. 210753092685410ea01dbb122162cd40cac48332ae1quddusc * @param steps usually 40 steps. You can increase or decrease the steps to change the speed. 211753092685410ea01dbb122162cd40cac48332ae1quddusc * @return true if successful 212516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz * @throws UiObjectNotFoundException 213516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz * @since API Level 18 214516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz */ 215516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz public boolean dragTo(int destX, int destY, int steps) throws UiObjectNotFoundException { 216516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz Rect srcRect = getVisibleBounds(); 217516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz return getInteractionController().swipe(srcRect.centerX(), srcRect.centerY(), destX, destY, 218516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz steps, true); 219516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz } 220516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz 221516cd58fd9422502e2a1e6f4c4615a32bb05606cAdam Momtaz /** 222753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs the swipe up action on the UiObject. 223753092685410ea01dbb122162cd40cac48332ae1quddusc * See also: 224753092685410ea01dbb122162cd40cac48332ae1quddusc * <ul> 225753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToBeginning(int)}</li> 226753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToEnd(int)}</li> 227753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollBackward()}</li> 228753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollForward()}</li> 229753092685410ea01dbb122162cd40cac48332ae1quddusc * </ul> 230f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 231f2030d3dd3f4968b85a3177b9cd21db831a0edafAdam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 232f2030d3dd3f4968b85a3177b9cd21db831a0edafAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 233f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return true of successful 234ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 235d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 236ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 237ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean swipeUp(int steps) throws UiObjectNotFoundException { 238b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(steps); 239f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz Rect rect = getVisibleBounds(); 240ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(rect.height() <= SWIPE_MARGIN_LIMIT * 2) 241ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return false; // too small to swipe 242ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return getInteractionController().swipe(rect.centerX(), 243ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu rect.bottom - SWIPE_MARGIN_LIMIT, rect.centerX(), rect.top + SWIPE_MARGIN_LIMIT, 244ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu steps); 245ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 246ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 247ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 248753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs the swipe down action on the UiObject. 249753092685410ea01dbb122162cd40cac48332ae1quddusc * The swipe gesture can be performed over any surface. The targeted 250753092685410ea01dbb122162cd40cac48332ae1quddusc * UI element does not need to be scrollable. 251753092685410ea01dbb122162cd40cac48332ae1quddusc * See also: 252753092685410ea01dbb122162cd40cac48332ae1quddusc * <ul> 253753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToBeginning(int)}</li> 254753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToEnd(int)}</li> 255753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollBackward()}</li> 256753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollForward()}</li> 257753092685410ea01dbb122162cd40cac48332ae1quddusc * </ul> 258f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 259f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 260f2030d3dd3f4968b85a3177b9cd21db831a0edafAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 261f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return true if successful 262ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 263d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 264ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 265ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean swipeDown(int steps) throws UiObjectNotFoundException { 266b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(steps); 267f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz Rect rect = getVisibleBounds(); 268ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(rect.height() <= SWIPE_MARGIN_LIMIT * 2) 269ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return false; // too small to swipe 270ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return getInteractionController().swipe(rect.centerX(), 271ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu rect.top + SWIPE_MARGIN_LIMIT, rect.centerX(), 272ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu rect.bottom - SWIPE_MARGIN_LIMIT, steps); 273ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 274ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 275ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 276753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs the swipe left action on the UiObject. 277753092685410ea01dbb122162cd40cac48332ae1quddusc * The swipe gesture can be performed over any surface. The targeted 278753092685410ea01dbb122162cd40cac48332ae1quddusc * UI element does not need to be scrollable. 279753092685410ea01dbb122162cd40cac48332ae1quddusc * See also: 280753092685410ea01dbb122162cd40cac48332ae1quddusc * <ul> 281753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToBeginning(int)}</li> 282753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToEnd(int)}</li> 283753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollBackward()}</li> 284753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollForward()}</li> 285753092685410ea01dbb122162cd40cac48332ae1quddusc * </ul> 286f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 287f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 288f2030d3dd3f4968b85a3177b9cd21db831a0edafAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 289f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return true if successful 290ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 291d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 292ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 293ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean swipeLeft(int steps) throws UiObjectNotFoundException { 294b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(steps); 295f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz Rect rect = getVisibleBounds(); 296ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(rect.width() <= SWIPE_MARGIN_LIMIT * 2) 297ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return false; // too small to swipe 298ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return getInteractionController().swipe(rect.right - SWIPE_MARGIN_LIMIT, 299ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu rect.centerY(), rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(), steps); 300ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 301ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 302ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 303753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs the swipe right action on the UiObject. 304753092685410ea01dbb122162cd40cac48332ae1quddusc * The swipe gesture can be performed over any surface. The targeted 305753092685410ea01dbb122162cd40cac48332ae1quddusc * UI element does not need to be scrollable. 306753092685410ea01dbb122162cd40cac48332ae1quddusc * See also: 307753092685410ea01dbb122162cd40cac48332ae1quddusc * <ul> 308753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToBeginning(int)}</li> 309753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollToEnd(int)}</li> 310753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollBackward()}</li> 311753092685410ea01dbb122162cd40cac48332ae1quddusc * <li>{@link UiScrollable#scrollForward()}</li> 312753092685410ea01dbb122162cd40cac48332ae1quddusc * </ul> 313f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 314f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 315f2030d3dd3f4968b85a3177b9cd21db831a0edafAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 316f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return true if successful 317ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 318d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 319ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 320ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean swipeRight(int steps) throws UiObjectNotFoundException { 321b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(steps); 322f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz Rect rect = getVisibleBounds(); 323ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(rect.width() <= SWIPE_MARGIN_LIMIT * 2) 324ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return false; // too small to swipe 325ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return getInteractionController().swipe(rect.left + SWIPE_MARGIN_LIMIT, 326ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu rect.centerY(), rect.right - SWIPE_MARGIN_LIMIT, rect.centerY(), steps); 327ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 328ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 329ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 330f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Finds the visible bounds of a partially visible UI element 331f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 332ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @param node 33373da7f69437c911dc60cc3b9ad7ad876677c8f14Adam Momtaz * @return null if node is null, else a Rect containing visible bounds 334ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 335ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu private Rect getVisibleBounds(AccessibilityNodeInfo node) { 336ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if (node == null) { 337ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return null; 338ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 339ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 340ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // targeted node's bounds 34147d54d40309083809bf04ba07a5b7191fbca9351Guang Zhu int w = UiDevice.getInstance().getDisplayWidth(); 34247d54d40309083809bf04ba07a5b7191fbca9351Guang Zhu int h = UiDevice.getInstance().getDisplayHeight(); 34347d54d40309083809bf04ba07a5b7191fbca9351Guang Zhu Rect nodeRect = AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node, w, h); 344ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 345ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // is the targeted node within a scrollable container? 346ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu AccessibilityNodeInfo scrollableParentNode = getScrollableParent(node); 347ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(scrollableParentNode == null) { 348ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // nothing to adjust for so return the node's Rect as is 349ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return nodeRect; 350ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 351ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 352ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // Scrollable parent's visible bounds 35373da7f69437c911dc60cc3b9ad7ad876677c8f14Adam Momtaz Rect parentRect = AccessibilityNodeInfoHelper 35447d54d40309083809bf04ba07a5b7191fbca9351Guang Zhu .getVisibleBoundsInScreen(scrollableParentNode, w, h); 355ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // adjust for partial clipping of targeted by parent node if required 356ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu nodeRect.intersect(parentRect); 357ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return nodeRect; 358ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 359ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 360ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 361753092685410ea01dbb122162cd40cac48332ae1quddusc * Walks up the layout hierarchy to find a scrollable parent. A scrollable parent 362753092685410ea01dbb122162cd40cac48332ae1quddusc * indicates that this node might be in a container where it is partially 363753092685410ea01dbb122162cd40cac48332ae1quddusc * visible due to scrolling. In this case, its clickable center might not be visible and 364753092685410ea01dbb122162cd40cac48332ae1quddusc * the click coordinates should be adjusted. 365f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 366ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @param node 3675478840ad89ace2474b9b4d3ab14b92d9e06bf47Thanh Le * @return The accessibility node info. 368ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 369ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu private AccessibilityNodeInfo getScrollableParent(AccessibilityNodeInfo node) { 370ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu AccessibilityNodeInfo parent = node; 371ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu while(parent != null) { 372ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu parent = parent.getParent(); 373ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if (parent != null && parent.isScrollable()) { 374ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return parent; 375ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 376ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 377ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return null; 378ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 379ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 380ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 381f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Performs a click at the center of the visible bounds of the UI element represented 382fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * by this UiObject. 383f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 384ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true id successful else false 385ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 386d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 387ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 388ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean click() throws UiObjectNotFoundException { 389b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 390bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 391ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 392ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 393ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 394ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 395bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz return getInteractionController().clickAndSync(rect.centerX(), rect.centerY(), 396bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz mConfig.getActionAcknowledgmentTimeout()); 397ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 398ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 399ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 400753092685410ea01dbb122162cd40cac48332ae1quddusc * Waits for window transitions that would typically take longer than the 401753092685410ea01dbb122162cd40cac48332ae1quddusc * usual default timeouts. 402f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * See {@link #clickAndWaitForNewWindow(long)} 403f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 404f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return true if the event was triggered, else false 405f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @throws UiObjectNotFoundException 406d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 407f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz */ 408ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean clickAndWaitForNewWindow() throws UiObjectNotFoundException { 409b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 410ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return clickAndWaitForNewWindow(WAIT_FOR_WINDOW_TMEOUT); 411ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 412ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 413ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 414fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * Performs a click at the center of the visible bounds of the UI element represented 415fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * by this UiObject and waits for window transitions. 416fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 417f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * This method differ from {@link UiObject#click()} only in that this method waits for a 418fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * a new window transition as a result of the click. Some examples of a window transition: 419ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * <li>launching a new activity</li> 420ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * <li>bringing up a pop-up menu</li> 421ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * <li>bringing up a dialog</li> 422ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * 423f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @param timeout timeout before giving up on waiting for a new window 424ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if the event was triggered, else false 425ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 426d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 427ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 428ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean clickAndWaitForNewWindow(long timeout) throws UiObjectNotFoundException { 429b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(timeout); 430bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 431ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 432ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 433ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 434ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 435bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz return getInteractionController().clickAndWaitForNewWindow(rect.centerX(), rect.centerY(), 436bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz mConfig.getActionAcknowledgmentTimeout()); 437ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 438ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 439ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 440f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Clicks the top and left corner of the UI element 441f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 442ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true on success 4435478840ad89ace2474b9b4d3ab14b92d9e06bf47Thanh Le * @throws UiObjectNotFoundException 444d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 445ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 446ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean clickTopLeft() throws UiObjectNotFoundException { 447b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 448bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 449ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 450ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 451ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 452ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 4533949d2773cc87adf0554940f69d1529434949ca2Adam Momtaz return getInteractionController().clickNoSync(rect.left + 5, rect.top + 5); 454ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 455ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 456ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 457f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Long clicks bottom and right corner of the UI element 458f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 459ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if operation was successful 460ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 461d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 462ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 463ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean longClickBottomRight() throws UiObjectNotFoundException { 464b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 465bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 466ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 467ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 468ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 469ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 4703949d2773cc87adf0554940f69d1529434949ca2Adam Momtaz return getInteractionController().longTapNoSync(rect.right - 5, rect.bottom - 5); 471ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 472ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 473ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 474f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Clicks the bottom and right corner of the UI element 475f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 476ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true on success 4775478840ad89ace2474b9b4d3ab14b92d9e06bf47Thanh Le * @throws UiObjectNotFoundException 478d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 479ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 480ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean clickBottomRight() throws UiObjectNotFoundException { 481b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 482bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 483ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 484ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 485ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 486ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 4873949d2773cc87adf0554940f69d1529434949ca2Adam Momtaz return getInteractionController().clickNoSync(rect.right - 5, rect.bottom - 5); 488ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 489ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 490ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 491f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Long clicks the center of the visible bounds of the UI element 492f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 493ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if operation was successful 494ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 495d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 496ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 497ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean longClick() throws UiObjectNotFoundException { 498b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 499bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 500ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 501ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 502ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 503ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 5043949d2773cc87adf0554940f69d1529434949ca2Adam Momtaz return getInteractionController().longTapNoSync(rect.centerX(), rect.centerY()); 505ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 506ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 507ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 508f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Long clicks on the top and left corner of the UI element 509f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 510ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if operation was successful 511ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 512d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 513ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 514ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean longClickTopLeft() throws UiObjectNotFoundException { 515b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 516bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 517ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 518ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 519ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 520ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 5213949d2773cc87adf0554940f69d1529434949ca2Adam Momtaz return getInteractionController().longTapNoSync(rect.left + 5, rect.top + 5); 522ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 523ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 524ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 525f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Reads the <code>text</code> property of the UI element 526f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 527ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return text value of the current node represented by this UiObject 528ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException if no match could be found 529d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 530ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 531ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public String getText() throws UiObjectNotFoundException { 532b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 533bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 534ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 535ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 536ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 537ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu String retVal = safeStringReturn(node.getText()); 538ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Log.d(LOG_TAG, String.format("getText() = %s", retVal)); 539ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return retVal; 540ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 541ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 542ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 543753092685410ea01dbb122162cd40cac48332ae1quddusc * Retrieves the <code>className</code> property of the UI element. 54492aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz * 54592aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz * @return class name of the current node represented by this UiObject 546753092685410ea01dbb122162cd40cac48332ae1quddusc * @throws UiObjectNotFoundException if no match was found 54792aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz * @since API Level 18 54892aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz */ 54992aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz public String getClassName() throws UiObjectNotFoundException { 55092aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz Tracer.trace(); 551bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 55292aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz if(node == null) { 55392aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 55492aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz } 55592aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz String retVal = safeStringReturn(node.getClassName()); 55692aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz Log.d(LOG_TAG, String.format("getClassName() = %s", retVal)); 55792aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz return retVal; 55892aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz } 55992aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz 56092aa0ff3a891d5ca4b37d1ad091b0e207d6e3041Adam Momtaz /** 561f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Reads the <code>content_desc</code> property of the UI element 562f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 563ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return value of node attribute "content_desc" 564ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 565d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 566ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 567ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public String getContentDescription() throws UiObjectNotFoundException { 568b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 569bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 570ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 571ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 572ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 573ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return safeStringReturn(node.getContentDescription()); 574ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 575ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 576ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 577fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * Sets the text in an editable field, after clearing the field's content. 578fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 579fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * The {@link UiSelector} selector of this object must reference a UI element that is editable. 580fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 581fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * When you call this method, the method first simulates a {@link #click()} on 582fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * editable field to set focus. The method then clears the field's contents 583fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * and injects your specified text into the field. 584f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 585fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * If you want to capture the original contents of the field, call {@link #getText()} first. 586fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * You can then modify the text and use this method to update the field. 587fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 588fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * @param text string to set 589ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if operation is successful 590ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 591d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 592ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 593ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean setText(String text) throws UiObjectNotFoundException { 594b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(text); 595ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu clearTextField(); 596ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return getInteractionController().sendText(text); 597ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 598ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 599ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 600fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * Clears the existing text contents in an editable field. 601fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 602fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * The {@link UiSelector} of this object must reference a UI element that is editable. 603fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 604fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * When you call this method, the method first sets focus at the start edge of the field. 605fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * The method then simulates a long-press to select the existing text, and deletes the 606fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * selected text. 607fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 608fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * If a "Select-All" option is displayed, the method will automatically attempt to use it 609fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * to ensure full text selection. 610fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 611fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * Note that it is possible that not all the text in the field is selected; for example, 612fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * if the text contains separators such as spaces, slashes, at symbol etc. 613fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * Also, not all editable fields support the long-press functionality. 614fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 615ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 616d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 617ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 618ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public void clearTextField() throws UiObjectNotFoundException { 619b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 620ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // long click left + center 621bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 622ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 623ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 624ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 625ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu Rect rect = getVisibleBounds(node); 6263949d2773cc87adf0554940f69d1529434949ca2Adam Momtaz getInteractionController().longTapNoSync(rect.left + 20, rect.centerY()); 627ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // check if the edit menu is open 628dc45c6d0e77da06314f5454211d2e683a32b3b24Adam Momtaz UiObject selectAll = new UiObject(new UiSelector().descriptionContains("Select all")); 629ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(selectAll.waitForExists(50)) 630ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu selectAll.click(); 631ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // wait for the selection 632ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu SystemClock.sleep(250); 633ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu // delete it 634ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu getInteractionController().sendKey(KeyEvent.KEYCODE_DEL, 0); 635ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 636ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 637ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 638f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Check if the UI element's <code>checked</code> property is currently true 639f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 640ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 641d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 642ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 643ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isChecked() throws UiObjectNotFoundException { 644b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 645bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 646ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 647ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 648ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 649ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isChecked(); 650ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 651ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 652ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 653753092685410ea01dbb122162cd40cac48332ae1quddusc * Checks if the UI element's <code>selected</code> property is currently true. 654f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 655ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 656ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 657d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 658ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 659ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isSelected() throws UiObjectNotFoundException { 660b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 661bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 662ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 663ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 664ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 665ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isSelected(); 666ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 667ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 668ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 669753092685410ea01dbb122162cd40cac48332ae1quddusc * Checks if the UI element's <code>checkable</code> property is currently true. 670f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 671ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 672ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 673d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 674ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 675ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isCheckable() throws UiObjectNotFoundException { 676b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 677bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 678ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 679ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 680ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 681ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isCheckable(); 682ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 683ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 684ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 685753092685410ea01dbb122162cd40cac48332ae1quddusc * Checks if the UI element's <code>enabled</code> property is currently true. 686f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 687ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 688ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 689d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 690ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 691ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isEnabled() throws UiObjectNotFoundException { 692b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 693bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 694ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 695ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 696ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 697ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isEnabled(); 698ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 699ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 700ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 701753092685410ea01dbb122162cd40cac48332ae1quddusc * Checks if the UI element's <code>clickable</code> property is currently true. 702f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 703ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 704ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 705d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 706ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 707ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isClickable() throws UiObjectNotFoundException { 708b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 709bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 710ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 711ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 712ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 713ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isClickable(); 714ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 715ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 716ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 717f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * Check if the UI element's <code>focused</code> property is currently true 718f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 719ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 720ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 721d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 722ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 723ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isFocused() throws UiObjectNotFoundException { 724b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 725bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 726ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 727ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 728ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 729ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isFocused(); 730ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 731ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 732ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 733753092685410ea01dbb122162cd40cac48332ae1quddusc * Check if the UI element's <code>focusable</code> property is currently true. 734f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 735ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 736ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 737d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 738ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 739ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isFocusable() throws UiObjectNotFoundException { 740b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 741bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 742ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 743ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 744ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 745ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isFocusable(); 746ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 747ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 748ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 749753092685410ea01dbb122162cd40cac48332ae1quddusc * Check if the view's <code>scrollable</code> property is currently true 750f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 751ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 752ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 753d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 754ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 755ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isScrollable() throws UiObjectNotFoundException { 756b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 757bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 758ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 759ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 760ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 761ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isScrollable(); 762ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 763ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 764ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 765753092685410ea01dbb122162cd40cac48332ae1quddusc * Check if the view's <code>long-clickable</code> property is currently true 766f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 767ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return true if it is else false 768ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 769d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 770ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 771ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean isLongClickable() throws UiObjectNotFoundException { 772b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 773bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 774ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 775ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 776ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 777ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return node.isLongClickable(); 778ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 779ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 780ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 781753092685410ea01dbb122162cd40cac48332ae1quddusc * Reads the view's <code>package</code> property 782f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 783f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return true if it is else false 784ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 785d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 786ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 787ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public String getPackageName() throws UiObjectNotFoundException { 788b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 789bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 790ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 791ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 792ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 793ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return safeStringReturn(node.getPackageName()); 794ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 795ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 796ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 797753092685410ea01dbb122162cd40cac48332ae1quddusc * Returns the visible bounds of the view. 798fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 799753092685410ea01dbb122162cd40cac48332ae1quddusc * If a portion of the view is visible, only the bounds of the visible portion are 800fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * reported. 801f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 802ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @return Rect 803ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * @throws UiObjectNotFoundException 8045478840ad89ace2474b9b4d3ab14b92d9e06bf47Thanh Le * @see {@link #getBounds()} 8058dab12c1039f9dc99f330ddc638626b4fbb11b19Guang Zhu * @since API Level 17 806ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 807f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz public Rect getVisibleBounds() throws UiObjectNotFoundException { 808b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 809bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 810ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(node == null) { 811ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 812ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 813ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return getVisibleBounds(node); 814ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 815ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 816ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 817753092685410ea01dbb122162cd40cac48332ae1quddusc * Returns the view's <code>bounds</code> property. See {@link #getVisibleBounds()} 818f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 819f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @return Rect 820f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * @throws UiObjectNotFoundException 821d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 822f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz */ 823f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz public Rect getBounds() throws UiObjectNotFoundException { 824b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 825bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 826f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz if(node == null) { 827f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 828f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz } 829f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz Rect nodeRect = new Rect(); 830f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz node.getBoundsInScreen(nodeRect); 831f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz 832f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz return nodeRect; 833f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz } 834f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz 835f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz /** 836753092685410ea01dbb122162cd40cac48332ae1quddusc * Waits a specified length of time for a view to become visible. 837fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 838753092685410ea01dbb122162cd40cac48332ae1quddusc * This method waits until the view becomes visible on the display, or 839fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * until the timeout has elapsed. You can use this method in situations where 840fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * the content that you want to select is not immediately displayed. 841f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 842fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * @param timeout the amount of time to wait (in milliseconds) 843753092685410ea01dbb122162cd40cac48332ae1quddusc * @return true if the view is displayed, else false if timeout elapsed while waiting 844d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 845ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 846ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean waitForExists(long timeout) { 847b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(timeout); 848ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(findAccessibilityNodeInfo(timeout) != null) { 849ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return true; 850ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 851ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return false; 852ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 853ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 854ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 855753092685410ea01dbb122162cd40cac48332ae1quddusc * Waits a specified length of time for a view to become undetectable. 856f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 857753092685410ea01dbb122162cd40cac48332ae1quddusc * This method waits until a view is no longer matchable, or until the 858fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * timeout has elapsed. 859fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 860753092685410ea01dbb122162cd40cac48332ae1quddusc * A view becomes undetectable when the {@link UiSelector} of the object is 861fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * unable to find a match because the element has either changed its state or is no 862fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * longer displayed. 863fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 864fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * You can use this method when attempting to wait for some long operation 865fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * to compete, such as downloading a large file or connecting to a remote server. 866fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 867fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * @param timeout time to wait (in milliseconds) 868fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * @return true if the element is gone before timeout elapsed, else false if timeout elapsed 869fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * but a matching element is still found. 870d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 871ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 872ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean waitUntilGone(long timeout) { 873b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(timeout); 874ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu long startMills = SystemClock.uptimeMillis(); 875ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu long currentMills = 0; 876ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu while (currentMills <= timeout) { 877ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(findAccessibilityNodeInfo(0) == null) 878ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return true; 879ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu currentMills = SystemClock.uptimeMillis() - startMills; 880ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(timeout > 0) 881ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu SystemClock.sleep(WAIT_FOR_SELECTOR_POLL); 882ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 883ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return false; 884ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 885ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 886ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu /** 887753092685410ea01dbb122162cd40cac48332ae1quddusc * Check if view exists. 888fbcc9c7c6df14a11e92f5c2553069e3333710896Adam Momtaz * 889ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * This methods performs a {@link #waitForExists(long)} with zero timeout. This 890753092685410ea01dbb122162cd40cac48332ae1quddusc * basically returns immediately whether the view represented by this UiObject 891753092685410ea01dbb122162cd40cac48332ae1quddusc * exists or not. If you need to wait longer for this view, then see 892ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu * {@link #waitForExists(long)}. 893f38e3f7321e4999bf92ddd6db5d5009f2e9801a2Adam Momtaz * 894753092685410ea01dbb122162cd40cac48332ae1quddusc * @return true if the view represented by this UiObject does exist 895d6b7eab5d1cf65a31aeebacc4a842e836ba5817cGuang Zhu * @since API Level 16 896ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu */ 897ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu public boolean exists() { 898b04f3c526835516b098227342e741b7ce944c2f3Maxim Siniavine Tracer.trace(); 899ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return waitForExists(0); 900ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 901ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu 902ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu private String safeStringReturn(CharSequence cs) { 903ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu if(cs == null) 904ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return ""; 905ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu return cs.toString(); 906ff763316cdb1986d8668ca3011cbb892b43aab93Guang Zhu } 90797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 90897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz /** 909753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs a two-pointer gesture, where each pointer moves diagonally 910753092685410ea01dbb122162cd40cac48332ae1quddusc * opposite across the other, from the center out towards the edges of the 91197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * this UiObject. 912753092685410ea01dbb122162cd40cac48332ae1quddusc * @param percent percentage of the object's diagonal length for the pinch gesture 913753092685410ea01dbb122162cd40cac48332ae1quddusc * @param steps the number of steps for the gesture. Steps are injected 914753092685410ea01dbb122162cd40cac48332ae1quddusc * about 5 milliseconds apart, so 100 steps may take around 0.5 seconds to complete. 9151ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 916753092685410ea01dbb122162cd40cac48332ae1quddusc * <code>false</code> otherwise 91797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @throws UiObjectNotFoundException 91897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @since API Level 18 91997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz */ 9201ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu public boolean pinchOut(int percent, int steps) throws UiObjectNotFoundException { 92197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // make value between 1 and 100 92297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz percent = (percent < 0) ? 1 : (percent > 100) ? 100 : percent; 92397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz float percentage = percent / 100f; 92497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 925bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 92697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz if (node == null) { 92797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 92897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 92997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 93097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Rect rect = getVisibleBounds(node); 93197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2) 93297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz throw new IllegalStateException("Object width is too small for operation"); 93397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 93497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // start from the same point at the center of the control 93597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point startPoint1 = new Point(rect.centerX() - FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 93697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point startPoint2 = new Point(rect.centerX() + FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 93797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 93897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // End at the top-left and bottom-right corners of the control 93997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point endPoint1 = new Point(rect.centerX() - (int)((rect.width()/2) * percentage), 94097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz rect.centerY()); 94197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point endPoint2 = new Point(rect.centerX() + (int)((rect.width()/2) * percentage), 94297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz rect.centerY()); 94397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 9441ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu return performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps); 94597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 94697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 94797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz /** 948753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs a two-pointer gesture, where each pointer moves diagonally 949753092685410ea01dbb122162cd40cac48332ae1quddusc * toward the other, from the edges to the center of this UiObject . 950753092685410ea01dbb122162cd40cac48332ae1quddusc * @param percent percentage of the object's diagonal length for the pinch gesture 951753092685410ea01dbb122162cd40cac48332ae1quddusc * @param steps the number of steps for the gesture. Steps are injected 952753092685410ea01dbb122162cd40cac48332ae1quddusc * about 5 milliseconds apart, so 100 steps may take around 0.5 seconds to complete. 9531ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 954753092685410ea01dbb122162cd40cac48332ae1quddusc * <code>false</code> otherwise 95597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @throws UiObjectNotFoundException 95697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @since API Level 18 95797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz */ 9581ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu public boolean pinchIn(int percent, int steps) throws UiObjectNotFoundException { 95997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // make value between 1 and 100 96097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz percent = (percent < 0) ? 0 : (percent > 100) ? 100 : percent; 96197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz float percentage = percent / 100f; 96297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 963bf43bba97b8009df1dc6c25d135fcfcbb9729540Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout()); 96497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz if (node == null) { 96597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 96697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 96797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 96897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Rect rect = getVisibleBounds(node); 96997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2) 97097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz throw new IllegalStateException("Object width is too small for operation"); 97197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 97297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point startPoint1 = new Point(rect.centerX() - (int)((rect.width()/2) * percentage), 97397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz rect.centerY()); 97497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point startPoint2 = new Point(rect.centerX() + (int)((rect.width()/2) * percentage), 97597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz rect.centerY()); 97697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 97797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point endPoint1 = new Point(rect.centerX() - FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 97897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point endPoint2 = new Point(rect.centerX() + FINGER_TOUCH_HALF_WIDTH, rect.centerY()); 97997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 9801ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu return performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps); 98197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 98297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 98397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz /** 984753092685410ea01dbb122162cd40cac48332ae1quddusc * Generates a two-pointer gesture with arbitrary starting and ending points. 98597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * 98697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @param startPoint1 start point of pointer 1 98797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @param startPoint2 start point of pointer 2 98897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @param endPoint1 end point of pointer 1 98997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @param endPoint2 end point of pointer 2 990753092685410ea01dbb122162cd40cac48332ae1quddusc * @param steps the number of steps for the gesture. Steps are injected 991753092685410ea01dbb122162cd40cac48332ae1quddusc * about 5 milliseconds apart, so 100 steps may take around 0.5 seconds to complete. 9921ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 993753092685410ea01dbb122162cd40cac48332ae1quddusc * <code>false</code> otherwise 99497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @since API Level 18 99597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz */ 9961ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu public boolean performTwoPointerGesture(Point startPoint1, Point startPoint2, Point endPoint1, 99797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz Point endPoint2, int steps) { 99897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 99997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // avoid a divide by zero 100097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz if(steps == 0) 100197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz steps = 1; 100297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 100397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz final float stepX1 = (endPoint1.x - startPoint1.x) / steps; 100497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz final float stepY1 = (endPoint1.y - startPoint1.y) / steps; 100597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz final float stepX2 = (endPoint2.x - startPoint2.x) / steps; 100697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz final float stepY2 = (endPoint2.y - startPoint2.y) / steps; 100797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 100897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz int eventX1, eventY1, eventX2, eventY2; 100997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventX1 = startPoint1.x; 101097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventY1 = startPoint1.y; 101197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventX2 = startPoint2.x; 101297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventY2 = startPoint2.y; 101397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 101497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // allocate for steps plus first down and last up 101597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz PointerCoords[] points1 = new PointerCoords[steps + 2]; 101697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz PointerCoords[] points2 = new PointerCoords[steps + 2]; 101797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 101897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // Include the first and last touch downs in the arrays of steps 101997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz for (int i = 0; i < steps + 1; i++) { 102097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz PointerCoords p1 = new PointerCoords(); 102197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.x = eventX1; 102297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.y = eventY1; 102397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.pressure = 1; 102497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.size = 1; 102597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz points1[i] = p1; 102697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 102797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz PointerCoords p2 = new PointerCoords(); 102897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.x = eventX2; 102997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.y = eventY2; 103097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.pressure = 1; 103197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.size = 1; 103297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz points2[i] = p2; 103397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 103497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventX1 += stepX1; 103597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventY1 += stepY1; 103697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventX2 += stepX2; 103797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz eventY2 += stepY2; 103897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 103997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 104097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz // ending pointers coordinates 104197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz PointerCoords p1 = new PointerCoords(); 104297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.x = endPoint1.x; 104397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.y = endPoint1.y; 104497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.pressure = 1; 104597e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p1.size = 1; 104697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz points1[steps + 1] = p1; 104797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 104897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz PointerCoords p2 = new PointerCoords(); 104997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.x = endPoint2.x; 105097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.y = endPoint2.y; 105197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.pressure = 1; 105297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz p2.size = 1; 105397e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz points2[steps + 1] = p2; 105497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 10551ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu return performMultiPointerGesture(points1, points2); 105697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 105797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz 105897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz /** 1059753092685410ea01dbb122162cd40cac48332ae1quddusc * Performs a multi-touch gesture. You must specify touch coordinates for 1060753092685410ea01dbb122162cd40cac48332ae1quddusc * at least 2 pointers. Each pointer must have all of its touch steps 1061753092685410ea01dbb122162cd40cac48332ae1quddusc * defined in an array of {@link PointerCoords}. You can use this method to 1062753092685410ea01dbb122162cd40cac48332ae1quddusc * specify complex gestures, like circles and irregular shapes, where each 1063753092685410ea01dbb122162cd40cac48332ae1quddusc * pointer may take a different path. 106497e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * 1065753092685410ea01dbb122162cd40cac48332ae1quddusc * To create a single point on a pointer's touch path: 106697e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * <code> 106797e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * PointerCoords p = new PointerCoords(); 106897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * p.x = stepX; 106997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * p.y = stepY; 107097e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * p.pressure = 1; 107197e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * p.size = 1; 107297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * </code> 10737093e225477d309c278c45cfe545f2c070aadad0Guang Zhu * @param touches represents the pointers' paths. Each {@link PointerCoords} 10747093e225477d309c278c45cfe545f2c070aadad0Guang Zhu * array represents a different pointer. Each {@link PointerCoords} in an 1075753092685410ea01dbb122162cd40cac48332ae1quddusc * array element represents a touch point on a pointer's path. 10761ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu * @return <code>true</code> if all touch events for this gesture are injected successfully, 1077753092685410ea01dbb122162cd40cac48332ae1quddusc * <code>false</code> otherwise 107897e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz * @since API Level 18 107997e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz */ 10801ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu public boolean performMultiPointerGesture(PointerCoords[] ...touches) { 10811ac23e97d43bc4acc3101c3ad3f3529fd118906cGuang Zhu return getInteractionController().performMultiPointerGesture(touches); 108297e4adbf51055559e5a5fa18fbb5147ea276c6c0Adam Momtaz } 10837093e225477d309c278c45cfe545f2c070aadad0Guang Zhu} 1084