118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/*
218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Copyright (C) 2012 The Android Open Source Project
318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu *
418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * you may not use this file except in compliance with the License.
618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * You may obtain a copy of the License at
718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu *
818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu *
1018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Unless required by applicable law or agreed to in writing, software
1118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
1218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * See the License for the specific language governing permissions and
1418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * limitations under the License.
1518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */
1618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
1718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupackage com.android.uiautomator.core;
1818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
1918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.graphics.Point;
2018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.graphics.Rect;
2118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.SystemClock;
2218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.util.Log;
2318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.KeyEvent;
2418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.MotionEvent.PointerCoords;
2518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo;
2618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
2718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/**
2818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * A UiObject is a representation of a view. It is not in any way directly bound to a
2918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * view as an object reference. A UiObject contains information to help it
3018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * locate a matching view at runtime based on the {@link UiSelector} properties specified in
3118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * its constructor. Once you create an instance of a UiObject, it can
3218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * be reused for different views that match the selector criteria.
3318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @since API Level 16
343fb03313e9d0e41f7c14b648c0f4dcfdab78bff3Allen Hair * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the
353fb03313e9d0e41f7c14b648c0f4dcfdab78bff3Allen Hair * Android Testing Support Library.
3618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */
373fb03313e9d0e41f7c14b648c0f4dcfdab78bff3Allen Hair@Deprecated
3818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupublic class UiObject {
3918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private static final String LOG_TAG = UiObject.class.getSimpleName();
4018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
4118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
4218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @deprecated use {@link Configurator#setWaitForSelectorTimeout(long)}
4318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     **/
4418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    @Deprecated
4518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected static final long WAIT_FOR_SELECTOR_TIMEOUT = 10 * 1000;
4618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
4718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
4818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     **/
4918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected static final long WAIT_FOR_SELECTOR_POLL = 1000;
5018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // set a default timeout to 5.5s, since ANR threshold is 5s
5118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
5218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
5318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     **/
5418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500;
5518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
5618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
5718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     **/
5818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected static final int SWIPE_MARGIN_LIMIT = 5;
5918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
6018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
6118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @deprecated use {@link Configurator#setScrollAcknowledgmentTimeout(long)}
6218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     **/
6318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    @Deprecated
6418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected static final long WAIT_FOR_EVENT_TMEOUT = 3 * 1000;
6518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
6618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
6718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     **/
6818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected static final int FINGER_TOUCH_HALF_WIDTH = 20;
6918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
7018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private final UiSelector mSelector;
7118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
7218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private final Configurator mConfig = Configurator.getInstance();
7318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
7418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
7518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Constructs a UiObject to represent a view that matches the specified
7618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * selector criteria.
7718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param selector
7818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
7918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
8018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public UiObject(UiSelector selector) {
8118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        mSelector = selector;
8218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
8318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
8418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
8518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Debugging helper. A test can dump the properties of a selector as a string
8618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to its logs if needed. <code>getSelector().toString();</code>
8718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
8818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return {@link UiSelector}
8918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
9018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
9118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public final UiSelector getSelector() {
9218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
9318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return new UiSelector(mSelector);
9418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
9518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
9618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
9718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the {@link QueryController} to translate a {@link UiSelector} selector
9818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * into an {@link AccessibilityNodeInfo}.
9918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
10018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return {@link QueryController}
10118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
10218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    QueryController getQueryController() {
10318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return UiDevice.getInstance().getAutomatorBridge().getQueryController();
10418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
10518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
10618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
10718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the {@link InteractionController} to perform finger actions such as tapping,
10818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * swiping, or entering text.
10918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
11018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return {@link InteractionController}
11118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
11218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    InteractionController getInteractionController() {
11318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return UiDevice.getInstance().getAutomatorBridge().getInteractionController();
11418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
11518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
11618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
11718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Creates a new UiObject for a child view that is under the present UiObject.
11818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
11918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param selector for child view to match
12018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return a new UiObject representing the child view
12118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
12218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
12318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public UiObject getChild(UiSelector selector) throws UiObjectNotFoundException {
12418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(selector);
12518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return new UiObject(getSelector().childSelector(selector));
12618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
12718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
12818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
12918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Creates a new UiObject for a sibling view or a child of the sibling view,
13018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * relative to the present UiObject.
13118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
13218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param selector for a sibling view or children of the sibling view
13318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return a new UiObject representing the matched view
13418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
13518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
13618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
13718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public UiObject getFromParent(UiSelector selector) throws UiObjectNotFoundException {
13818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(selector);
13918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return new UiObject(getSelector().fromParent(selector));
14018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
14118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
14218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
14318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Counts the child views immediately under the present UiObject.
14418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
14518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return the count of child views.
14618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
14718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
14818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
14918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public int getChildCount() throws UiObjectNotFoundException {
15018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
15118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
15218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
15318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
15418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
15518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.getChildCount();
15618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
15718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
15818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
15918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Finds a matching UI element in the accessibility hierarchy, by
16018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * using the selector for this UiObject.
16118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
16218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param timeout in milliseconds
16318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return AccessibilityNodeInfo if found else null
16418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
16518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
16618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    protected AccessibilityNodeInfo findAccessibilityNodeInfo(long timeout) {
16718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = null;
16818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        long startMills = SystemClock.uptimeMillis();
16918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        long currentMills = 0;
17018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        while (currentMills <= timeout) {
17118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            node = getQueryController().findAccessibilityNodeInfo(getSelector());
17218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if (node != null) {
17318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                break;
17418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            } else {
17518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                // does nothing if we're reentering another runWatchers()
17618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                UiDevice.getInstance().runWatchers();
17718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
17818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            currentMills = SystemClock.uptimeMillis() - startMills;
17918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if(timeout > 0) {
18018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                SystemClock.sleep(WAIT_FOR_SELECTOR_POLL);
18118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
18218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
18318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node;
18418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
18518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
18618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
18718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Drags this object to a destination UiObject.
18818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The number of steps specified in your input parameter can influence the
18918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * drag speed, and varying speeds may impact the results. Consider
19018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * evaluating different speeds when using this method in your tests.
19118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
19218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param destObj the destination UiObject.
19318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps usually 40 steps. You can increase or decrease the steps to change the speed.
19418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful
19518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
19618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
19718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
19818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean dragTo(UiObject destObj, int steps) throws UiObjectNotFoundException {
19918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect srcRect = getVisibleBounds();
20018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect dstRect = destObj.getVisibleBounds();
20118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().swipe(srcRect.centerX(), srcRect.centerY(),
20218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                dstRect.centerX(), dstRect.centerY(), steps, true);
20318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
20418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
20518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
20618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Drags this object to arbitrary coordinates.
20718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The number of steps specified in your input parameter can influence the
20818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * drag speed, and varying speeds may impact the results. Consider
20918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * evaluating different speeds when using this method in your tests.
21018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
21118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param destX the X-axis coordinate.
21218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param destY the Y-axis coordinate.
21318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps usually 40 steps. You can increase or decrease the steps to change the speed.
21418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful
21518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
21618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
21718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
21818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean dragTo(int destX, int destY, int steps) throws UiObjectNotFoundException {
21918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect srcRect = getVisibleBounds();
22018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().swipe(srcRect.centerX(), srcRect.centerY(), destX, destY,
22118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                steps, true);
22218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
22318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
22418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
22518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs the swipe up action on the UiObject.
22618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See also:
22718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <ul>
22818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToBeginning(int)}</li>
22918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToEnd(int)}</li>
23018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollBackward()}</li>
23118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollForward()}</li>
23218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * </ul>
23318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
23418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps indicates the number of injected move steps into the system. Steps are
23518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
23618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true of successful
23718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
23818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
23918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
24018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean swipeUp(int steps) throws UiObjectNotFoundException {
24118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(steps);
24218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds();
24318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(rect.height() <= SWIPE_MARGIN_LIMIT * 2)
24418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return false; // too small to swipe
24518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().swipe(rect.centerX(),
24618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.bottom - SWIPE_MARGIN_LIMIT, rect.centerX(), rect.top + SWIPE_MARGIN_LIMIT,
24718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                steps);
24818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
24918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
25018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
25118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs the swipe down action on the UiObject.
25218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The swipe gesture can be performed over any surface. The targeted
25318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * UI element does not need to be scrollable.
25418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See also:
25518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <ul>
25618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToBeginning(int)}</li>
25718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToEnd(int)}</li>
25818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollBackward()}</li>
25918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollForward()}</li>
26018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * </ul>
26118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
26218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps indicates the number of injected move steps into the system. Steps are
26318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
26418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful
26518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
26618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
26718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
26818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean swipeDown(int steps) throws UiObjectNotFoundException {
26918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(steps);
27018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds();
27118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(rect.height() <= SWIPE_MARGIN_LIMIT * 2)
27218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return false; // too small to swipe
27318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().swipe(rect.centerX(),
27418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.top + SWIPE_MARGIN_LIMIT, rect.centerX(),
27518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.bottom - SWIPE_MARGIN_LIMIT, steps);
27618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
27718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
27818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
27918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs the swipe left action on the UiObject.
28018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The swipe gesture can be performed over any surface. The targeted
28118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * UI element does not need to be scrollable.
28218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See also:
28318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <ul>
28418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToBeginning(int)}</li>
28518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToEnd(int)}</li>
28618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollBackward()}</li>
28718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollForward()}</li>
28818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * </ul>
28918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
29018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps indicates the number of injected move steps into the system. Steps are
29118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
29218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful
29318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
29418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
29518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
29618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean swipeLeft(int steps) throws UiObjectNotFoundException {
29718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(steps);
29818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds();
29918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(rect.width() <= SWIPE_MARGIN_LIMIT * 2)
30018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return false; // too small to swipe
30118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().swipe(rect.right - SWIPE_MARGIN_LIMIT,
30218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.centerY(), rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(), steps);
30318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
30418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
30518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
30618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs the swipe right action on the UiObject.
30718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The swipe gesture can be performed over any surface. The targeted
30818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * UI element does not need to be scrollable.
30918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See also:
31018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <ul>
31118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToBeginning(int)}</li>
31218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollToEnd(int)}</li>
31318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollBackward()}</li>
31418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>{@link UiScrollable#scrollForward()}</li>
31518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * </ul>
31618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
31718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps indicates the number of injected move steps into the system. Steps are
31818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
31918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful
32018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
32118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
32218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
32318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean swipeRight(int steps) throws UiObjectNotFoundException {
32418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(steps);
32518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds();
32618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(rect.width() <= SWIPE_MARGIN_LIMIT * 2)
32718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return false; // too small to swipe
32818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().swipe(rect.left + SWIPE_MARGIN_LIMIT,
32918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.centerY(), rect.right - SWIPE_MARGIN_LIMIT, rect.centerY(), steps);
33018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
33118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
33218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
33318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Finds the visible bounds of a partially visible UI element
33418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
33518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param node
33618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return null if node is null, else a Rect containing visible bounds
33718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
33818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private Rect getVisibleBounds(AccessibilityNodeInfo node) {
33918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (node == null) {
34018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return null;
34118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
34218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
34318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // targeted node's bounds
34418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        int w = UiDevice.getInstance().getDisplayWidth();
34518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        int h = UiDevice.getInstance().getDisplayHeight();
34618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect nodeRect = AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node, w, h);
34718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
34818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // is the targeted node within a scrollable container?
34918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo scrollableParentNode = getScrollableParent(node);
35018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(scrollableParentNode == null) {
35118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            // nothing to adjust for so return the node's Rect as is
35218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return nodeRect;
35318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
35418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
35518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // Scrollable parent's visible bounds
35618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect parentRect = AccessibilityNodeInfoHelper
35718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                .getVisibleBoundsInScreen(scrollableParentNode, w, h);
35818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // adjust for partial clipping of targeted by parent node if required
359adb89214532a2eda2b5396886ae1ada16d890b24Doris Liu        if (nodeRect.intersect(parentRect)) {
360adb89214532a2eda2b5396886ae1ada16d890b24Doris Liu            return nodeRect;
361adb89214532a2eda2b5396886ae1ada16d890b24Doris Liu        } else {
362adb89214532a2eda2b5396886ae1ada16d890b24Doris Liu            // Node rect has no intersection with parent Rect
363adb89214532a2eda2b5396886ae1ada16d890b24Doris Liu            return new Rect();
364adb89214532a2eda2b5396886ae1ada16d890b24Doris Liu        }
36518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
36618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
36718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
36818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Walks up the layout hierarchy to find a scrollable parent. A scrollable parent
36918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * indicates that this node might be in a container where it is partially
37018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * visible due to scrolling. In this case, its clickable center might not be visible and
37118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * the click coordinates should be adjusted.
37218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
37318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param node
37418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return The accessibility node info.
37518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
37618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private AccessibilityNodeInfo getScrollableParent(AccessibilityNodeInfo node) {
37718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo parent = node;
37818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        while(parent != null) {
37918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            parent = parent.getParent();
38018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if (parent != null && parent.isScrollable()) {
38118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                return parent;
38218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
38318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
38418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return null;
38518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
38618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
38718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
38818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a click at the center of the visible bounds of the UI element represented
38918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * by this UiObject.
39018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
39118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true id successful else false
39218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
39318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
39418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
39518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean click() throws UiObjectNotFoundException {
39618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
39718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
39818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
39918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
40018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
40118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
40218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().clickAndSync(rect.centerX(), rect.centerY(),
40318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                mConfig.getActionAcknowledgmentTimeout());
40418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
40518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
40618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
40718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Waits for window transitions that would typically take longer than the
40818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * usual default timeouts.
40918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #clickAndWaitForNewWindow(long)}
41018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
41118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the event was triggered, else false
41218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
41318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
41418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
41518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean clickAndWaitForNewWindow() throws UiObjectNotFoundException {
41618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
41718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return clickAndWaitForNewWindow(WAIT_FOR_WINDOW_TMEOUT);
41818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
41918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
42018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
42118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a click at the center of the visible bounds of the UI element represented
42218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * by this UiObject and waits for window transitions.
42318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
42418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method differ from {@link UiObject#click()} only in that this method waits for a
42518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * a new window transition as a result of the click. Some examples of a window transition:
42618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>launching a new activity</li>
42718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>bringing up a pop-up menu</li>
42818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <li>bringing up a dialog</li>
42918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
43018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param timeout timeout before giving up on waiting for a new window
43118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the event was triggered, else false
43218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
43318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
43418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
43518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean clickAndWaitForNewWindow(long timeout) throws UiObjectNotFoundException {
43618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(timeout);
43718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
43818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
43918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
44018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
44118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
44218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().clickAndWaitForNewWindow(rect.centerX(), rect.centerY(),
44318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                mConfig.getActionAcknowledgmentTimeout());
44418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
44518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
44618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
44718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Clicks the top and left corner of the UI element
44818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
44918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true on success
45018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
45118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
45218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
45318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean clickTopLeft() throws UiObjectNotFoundException {
45418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
45518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
45618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
45718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
45818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
45918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
46018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().clickNoSync(rect.left + 5, rect.top + 5);
46118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
46218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
46318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
46418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Long clicks bottom and right corner of the UI element
46518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
46618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if operation was successful
46718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
46818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
46918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
47018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean longClickBottomRight() throws UiObjectNotFoundException  {
47118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
47218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
47318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
47418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
47518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
47618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
47718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().longTapNoSync(rect.right - 5, rect.bottom - 5);
47818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
47918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
48018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
48118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Clicks the bottom and right corner of the UI element
48218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
48318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true on success
48418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
48518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
48618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
48718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean clickBottomRight() throws UiObjectNotFoundException {
48818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
48918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
49018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
49118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
49218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
49318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
49418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().clickNoSync(rect.right - 5, rect.bottom - 5);
49518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
49618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
49718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
49818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Long clicks the center of the visible bounds of the UI element
49918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
50018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if operation was successful
50118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
50218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
50318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
50418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean longClick() throws UiObjectNotFoundException  {
50518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
50618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
50718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
50818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
50918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
51018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
51118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().longTapNoSync(rect.centerX(), rect.centerY());
51218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
51318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
51418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
51518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Long clicks on the top and left corner of the UI element
51618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
51718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if operation was successful
51818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
51918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
52018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
52118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean longClickTopLeft() throws UiObjectNotFoundException {
52218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
52318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
52418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
52518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
52618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
52718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
52818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().longTapNoSync(rect.left + 5, rect.top + 5);
52918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
53018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
53118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
53218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Reads the <code>text</code> property of the UI element
53318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
53418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return text value of the current node represented by this UiObject
53518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException if no match could be found
53618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
53718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
53818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getText() throws UiObjectNotFoundException {
53918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
54018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
54118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
54218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
54318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
54418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        String retVal = safeStringReturn(node.getText());
54518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Log.d(LOG_TAG, String.format("getText() = %s", retVal));
54618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return retVal;
54718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
54818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
54918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
55018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the <code>className</code> property of the UI element.
55118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
55218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return class name of the current node represented by this UiObject
55318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException if no match was found
55418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
55518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
55618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getClassName() throws UiObjectNotFoundException {
55718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
55818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
55918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
56018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
56118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
56218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        String retVal = safeStringReturn(node.getClassName());
56318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Log.d(LOG_TAG, String.format("getClassName() = %s", retVal));
56418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return retVal;
56518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
56618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
56718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
56818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Reads the <code>content_desc</code> property of the UI element
56918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
57018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return value of node attribute "content_desc"
57118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
57218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
57318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
57418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getContentDescription() throws UiObjectNotFoundException {
57518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
57618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
57718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
57818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
57918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
58018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return safeStringReturn(node.getContentDescription());
58118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
58218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
58318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
58418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Sets the text in an editable field, after clearing the field's content.
58518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
58618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The {@link UiSelector} selector of this object must reference a UI element that is editable.
58718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
58818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * When you call this method, the method first simulates a {@link #click()} on
58918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * editable field to set focus. The method then clears the field's contents
59018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * and injects your specified text into the field.
59118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
59218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If you want to capture the original contents of the field, call {@link #getText()} first.
59318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * You can then modify the text and use this method to update the field.
59418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
59518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param text string to set
59618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if operation is successful
59718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
59818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
59918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
60018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean setText(String text) throws UiObjectNotFoundException {
60118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(text);
60218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        clearTextField();
60318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().sendText(text);
60418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
60518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
60618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
60718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Clears the existing text contents in an editable field.
60818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
60918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The {@link UiSelector} of this object must reference a UI element that is editable.
61018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
61118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * When you call this method, the method first sets focus at the start edge of the field.
61218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The method then simulates a long-press to select the existing text, and deletes the
61318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * selected text.
61418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
61518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If a "Select-All" option is displayed, the method will automatically attempt to use it
61618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to ensure full text selection.
61718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
61818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Note that it is possible that not all the text in the field is selected; for example,
61918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * if the text contains separators such as spaces, slashes, at symbol etc.
62018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Also, not all editable fields support the long-press functionality.
62118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
62218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
62318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
62418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
62518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void clearTextField() throws UiObjectNotFoundException {
62618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
62718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // long click left + center
62818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
62918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
63018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
63118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
63218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
63318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getInteractionController().longTapNoSync(rect.left + 20, rect.centerY());
63418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // check if the edit menu is open
63518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        UiObject selectAll = new UiObject(new UiSelector().descriptionContains("Select all"));
63618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(selectAll.waitForExists(50))
63718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            selectAll.click();
63818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // wait for the selection
63918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        SystemClock.sleep(250);
64018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // delete it
64118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getInteractionController().sendKey(KeyEvent.KEYCODE_DEL, 0);
64218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
64318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
64418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
64518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if the UI element's <code>checked</code> property is currently true
64618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
64718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
64818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
64918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
65018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isChecked() throws UiObjectNotFoundException {
65118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
65218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
65318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
65418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
65518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
65618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isChecked();
65718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
65818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
65918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
66018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks if the UI element's <code>selected</code> property is currently true.
66118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
66218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
66318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
66418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
66518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
66618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isSelected() throws UiObjectNotFoundException {
66718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
66818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
66918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
67018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
67118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
67218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isSelected();
67318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
67418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
67518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
67618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks if the UI element's <code>checkable</code> property is currently true.
67718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
67818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
67918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
68018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
68118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
68218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isCheckable() throws UiObjectNotFoundException {
68318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
68418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
68518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
68618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
68718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
68818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isCheckable();
68918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
69018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
69118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
69218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks if the UI element's <code>enabled</code> property is currently true.
69318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
69418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
69518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
69618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
69718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
69818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isEnabled() throws UiObjectNotFoundException {
69918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
70018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
70118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
70218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
70318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
70418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isEnabled();
70518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
70618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
70718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
70818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks if the UI element's <code>clickable</code> property is currently true.
70918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
71018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
71118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
71218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
71318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
71418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isClickable() throws UiObjectNotFoundException {
71518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
71618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
71718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
71818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
71918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
72018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isClickable();
72118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
72218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
72318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
72418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if the UI element's <code>focused</code> property is currently true
72518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
72618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
72718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
72818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
72918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
73018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isFocused() throws UiObjectNotFoundException {
73118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
73218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
73318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
73418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
73518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
73618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isFocused();
73718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
73818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
73918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
74018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if the UI element's <code>focusable</code> property is currently true.
74118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
74218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
74318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
74418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
74518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
74618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isFocusable() throws UiObjectNotFoundException {
74718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
74818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
74918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
75018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
75118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
75218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isFocusable();
75318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
75418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
75518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
75618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if the view's <code>scrollable</code> property is currently true
75718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
75818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
75918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
76018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
76118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
76218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isScrollable() throws UiObjectNotFoundException {
76318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
76418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
76518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
76618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
76718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
76818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isScrollable();
76918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
77018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
77118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
77218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if the view's <code>long-clickable</code> property is currently true
77318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
77418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
77518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
77618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
77718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
77818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isLongClickable() throws UiObjectNotFoundException {
77918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
78018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
78118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
78218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
78318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
78418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return node.isLongClickable();
78518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
78618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
78718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
78818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Reads the view's <code>package</code> property
78918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
79018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is else false
79118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
79218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
79318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
79418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getPackageName() throws UiObjectNotFoundException {
79518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
79618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
79718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
79818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
79918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
80018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return safeStringReturn(node.getPackageName());
80118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
80218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
80318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
80418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Returns the visible bounds of the view.
80518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
80618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If a portion of the view is visible, only the bounds of the visible portion are
80718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * reported.
80818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
80918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return Rect
81018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
81154de77470de4f605eef7f4b4e01718b301fe275eElliot Waite     * @see #getBounds()
81218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
81318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
81418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public Rect getVisibleBounds() throws UiObjectNotFoundException {
81518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
81618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
81718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
81818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
81918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
82018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getVisibleBounds(node);
82118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
82218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
82318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
82418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Returns the view's <code>bounds</code> property. See {@link #getVisibleBounds()}
82518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
82618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return Rect
82718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
82818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
82918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
83018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public Rect getBounds() throws UiObjectNotFoundException {
83118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
83218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
83318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(node == null) {
83418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
83518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
83618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect nodeRect = new Rect();
83718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        node.getBoundsInScreen(nodeRect);
83818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
83918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return nodeRect;
84018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
84118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
84218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
84318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Waits a specified length of time for a view to become visible.
84418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
84518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method waits until the view becomes visible on the display, or
84618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * until the timeout has elapsed. You can use this method in situations where
84718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * the content that you want to select is not immediately displayed.
84818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
84918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param timeout the amount of time to wait (in milliseconds)
85018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the view is displayed, else false if timeout elapsed while waiting
85118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
85218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
85318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean waitForExists(long timeout) {
85418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(timeout);
85518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(findAccessibilityNodeInfo(timeout) != null) {
85618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return true;
85718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
85818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return false;
85918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
86018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
86118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
86218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Waits a specified length of time for a view to become undetectable.
86318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
86418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method waits until a view is no longer matchable, or until the
86518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * timeout has elapsed.
86618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
86718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * A view becomes undetectable when the {@link UiSelector} of the object is
86818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * unable to find a match because the element has either changed its state or is no
86918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * longer displayed.
87018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
87118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * You can use this method when attempting to wait for some long operation
87218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to compete, such as downloading a large file or connecting to a remote server.
87318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
87418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param timeout time to wait (in milliseconds)
87518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the element is gone before timeout elapsed, else false if timeout elapsed
87618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * but a matching element is still found.
87718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
87818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
87918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean waitUntilGone(long timeout) {
88018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(timeout);
88118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        long startMills = SystemClock.uptimeMillis();
88218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        long currentMills = 0;
88318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        while (currentMills <= timeout) {
88418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if(findAccessibilityNodeInfo(0) == null)
88518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                return true;
88618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            currentMills = SystemClock.uptimeMillis() - startMills;
88718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if(timeout > 0)
88818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                SystemClock.sleep(WAIT_FOR_SELECTOR_POLL);
88918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
89018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return false;
89118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
89218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
89318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
89418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if view exists.
89518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
89618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This methods performs a {@link #waitForExists(long)} with zero timeout. This
89718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * basically returns immediately whether the view represented by this UiObject
89818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * exists or not. If you need to wait longer for this view, then see
89918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * {@link #waitForExists(long)}.
90018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
90118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the view represented by this UiObject does exist
90218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
90318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
90418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean exists() {
90518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
90618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return waitForExists(0);
90718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
90818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
90918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private String safeStringReturn(CharSequence cs) {
91018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(cs == null)
91118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return "";
91218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return cs.toString();
91318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
91418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
91518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
91618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a two-pointer gesture, where each pointer moves diagonally
91718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * opposite across the other, from the center out towards the edges of the
91818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * this UiObject.
91918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param percent percentage of the object's diagonal length for the pinch gesture
92018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps the number of steps for the gesture. Steps are injected
92118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * about 5 milliseconds apart, so 100 steps may take around 0.5 seconds to complete.
92218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return <code>true</code> if all touch events for this gesture are injected successfully,
92318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *         <code>false</code> otherwise
92418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
92518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
92618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
92718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pinchOut(int percent, int steps) throws UiObjectNotFoundException {
92818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // make value between 1 and 100
92918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        percent = (percent < 0) ? 1 : (percent > 100) ? 100 : percent;
93018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        float percentage = percent / 100f;
93118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
93218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
93318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (node == null) {
93418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
93518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
93618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
93718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
93818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2)
93918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new IllegalStateException("Object width is too small for operation");
94018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
94118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // start from the same point at the center of the control
94218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point startPoint1 = new Point(rect.centerX() - FINGER_TOUCH_HALF_WIDTH, rect.centerY());
94318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point startPoint2 = new Point(rect.centerX() + FINGER_TOUCH_HALF_WIDTH, rect.centerY());
94418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
94518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // End at the top-left and bottom-right corners of the control
94618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point endPoint1 = new Point(rect.centerX() - (int)((rect.width()/2) * percentage),
94718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.centerY());
94818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point endPoint2 = new Point(rect.centerX() + (int)((rect.width()/2) * percentage),
94918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.centerY());
95018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
95118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps);
95218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
95318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
95418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
95518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a two-pointer gesture, where each pointer moves diagonally
95618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * toward the other, from the edges to the center of this UiObject .
95718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param percent percentage of the object's diagonal length for the pinch gesture
95818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps the number of steps for the gesture. Steps are injected
95918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * about 5 milliseconds apart, so 100 steps may take around 0.5 seconds to complete.
96018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return <code>true</code> if all touch events for this gesture are injected successfully,
96118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *         <code>false</code> otherwise
96218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws UiObjectNotFoundException
96318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
96418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
96518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pinchIn(int percent, int steps) throws UiObjectNotFoundException {
96618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // make value between 1 and 100
96718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        percent = (percent < 0) ? 0 : (percent > 100) ? 100 : percent;
96818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        float percentage = percent / 100f;
96918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
97018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
97118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (node == null) {
97218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new UiObjectNotFoundException(getSelector().toString());
97318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
97418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
97518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Rect rect = getVisibleBounds(node);
97618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2)
97718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new IllegalStateException("Object width is too small for operation");
97818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
97918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point startPoint1 = new Point(rect.centerX() - (int)((rect.width()/2) * percentage),
98018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.centerY());
98118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point startPoint2 = new Point(rect.centerX() + (int)((rect.width()/2) * percentage),
98218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                rect.centerY());
98318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
98418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point endPoint1 = new Point(rect.centerX() - FINGER_TOUCH_HALF_WIDTH, rect.centerY());
98518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point endPoint2 = new Point(rect.centerX() + FINGER_TOUCH_HALF_WIDTH, rect.centerY());
98618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
98718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps);
98818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
98918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
99018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
99118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Generates a two-pointer gesture with arbitrary starting and ending points.
99218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
99318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param startPoint1 start point of pointer 1
99418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param startPoint2 start point of pointer 2
99518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param endPoint1 end point of pointer 1
99618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param endPoint2 end point of pointer 2
99718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps the number of steps for the gesture. Steps are injected
99818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * about 5 milliseconds apart, so 100 steps may take around 0.5 seconds to complete.
99918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return <code>true</code> if all touch events for this gesture are injected successfully,
100018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *         <code>false</code> otherwise
100118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
100218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
100318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean performTwoPointerGesture(Point startPoint1, Point startPoint2, Point endPoint1,
100418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            Point endPoint2, int steps) {
100518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
100618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // avoid a divide by zero
100718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(steps == 0)
100818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            steps = 1;
100918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
101018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        final float stepX1 = (endPoint1.x - startPoint1.x) / steps;
101118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        final float stepY1 = (endPoint1.y - startPoint1.y) / steps;
101218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        final float stepX2 = (endPoint2.x - startPoint2.x) / steps;
101318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        final float stepY2 = (endPoint2.y - startPoint2.y) / steps;
101418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
101518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        int eventX1, eventY1, eventX2, eventY2;
101618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        eventX1 = startPoint1.x;
101718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        eventY1 = startPoint1.y;
101818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        eventX2 = startPoint2.x;
101918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        eventY2 = startPoint2.y;
102018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
102118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // allocate for steps plus first down and last up
102218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        PointerCoords[] points1 = new PointerCoords[steps + 2];
102318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        PointerCoords[] points2 = new PointerCoords[steps + 2];
102418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
102518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // Include the first and last touch downs in the arrays of steps
102618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        for (int i = 0; i < steps + 1; i++) {
102718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            PointerCoords p1 = new PointerCoords();
102818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p1.x = eventX1;
102918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p1.y = eventY1;
103018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p1.pressure = 1;
103118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p1.size = 1;
103218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            points1[i] = p1;
103318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
103418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            PointerCoords p2 = new PointerCoords();
103518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p2.x = eventX2;
103618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p2.y = eventY2;
103718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p2.pressure = 1;
103818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            p2.size = 1;
103918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            points2[i] = p2;
104018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
104118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            eventX1 += stepX1;
104218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            eventY1 += stepY1;
104318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            eventX2 += stepX2;
104418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            eventY2 += stepY2;
104518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
104618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
104718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        // ending pointers coordinates
104818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        PointerCoords p1 = new PointerCoords();
104918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p1.x = endPoint1.x;
105018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p1.y = endPoint1.y;
105118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p1.pressure = 1;
105218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p1.size = 1;
105318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        points1[steps + 1] = p1;
105418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
105518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        PointerCoords p2 = new PointerCoords();
105618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p2.x = endPoint2.x;
105718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p2.y = endPoint2.y;
105818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p2.pressure = 1;
105918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p2.size = 1;
106018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        points2[steps + 1] = p2;
106118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
106218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return performMultiPointerGesture(points1, points2);
106318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
106418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
106518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
106618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a multi-touch gesture. You must specify touch coordinates for
106718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * at least 2 pointers. Each pointer must have all of its touch steps
106818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * defined in an array of {@link PointerCoords}. You can use this method to
106918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * specify complex gestures, like circles and irregular shapes, where each
107018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * pointer may take a different path.
107118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
107218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * To create a single point on a pointer's touch path:
107318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * <code>
107418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *       PointerCoords p = new PointerCoords();
107518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *       p.x = stepX;
107618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *       p.y = stepY;
107718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *       p.pressure = 1;
107818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *       p.size = 1;
107918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * </code>
108018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param touches represents the pointers' paths. Each {@link PointerCoords}
108118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * array represents a different pointer. Each {@link PointerCoords} in an
108218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * array element represents a touch point on a pointer's path.
108318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return <code>true</code> if all touch events for this gesture are injected successfully,
108418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *         <code>false</code> otherwise
108518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
108618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
108718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean performMultiPointerGesture(PointerCoords[] ...touches) {
108818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getInteractionController().performMultiPointerGesture(touches);
108918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
109018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu}
1091