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.app.UiAutomation;
2018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.app.UiAutomation.AccessibilityEventFilter;
2118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.graphics.Point;
2218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.Build;
2318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.Environment;
2418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.RemoteException;
2518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.SystemClock;
2618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.util.DisplayMetrics;
2718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.util.Log;
2818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.Display;
2918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.KeyEvent;
3018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.Surface;
3118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.accessibility.AccessibilityEvent;
3218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo;
3318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
3418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.io.File;
3518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.ArrayList;
3618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.HashMap;
3718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.List;
3818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.concurrent.TimeoutException;
3918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
4018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/**
4118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * UiDevice provides access to state information about the device.
4218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * You can also use this class to simulate user actions on the device,
4318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * such as pressing the d-pad or pressing the Home and Menu buttons.
4418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @since API Level 16
4518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */
4618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupublic class UiDevice {
4718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private static final String LOG_TAG = UiDevice.class.getSimpleName();
4818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
4918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // Sometimes HOME and BACK key presses will generate no events if already on
5018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // home page or there is nothing to go back to, Set low timeouts.
5118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private static final long KEY_PRESS_EVENT_TIMEOUT = 1 * 1000;
5218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
5318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // store for registered UiWatchers
5418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private final HashMap<String, UiWatcher> mWatchers = new HashMap<String, UiWatcher>();
5518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private final List<String> mWatchersTriggers = new ArrayList<String>();
5618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
5718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // remember if we're executing in the context of a UiWatcher
5818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private boolean mInWatcherContext = false;
5918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
6018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // provides access the {@link QueryController} and {@link InteractionController}
6118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private UiAutomatorBridge mUiAutomationBridge;
6218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
6318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    // reference to self
6418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private static UiDevice sDevice;
6518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
6618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private UiDevice() {
6718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        /* hide constructor */
6818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
6918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
7018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
7118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @hide
7218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
7318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void initialize(UiAutomatorBridge uiAutomatorBridge) {
7418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        mUiAutomationBridge = uiAutomatorBridge;
7518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
7618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
7718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    boolean isInWatcherContext() {
7818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return mInWatcherContext;
7918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
8018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
8118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
8218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Provides access the {@link QueryController} and {@link InteractionController}
8318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return {@link ShellUiAutomatorBridge}
8418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
8518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    UiAutomatorBridge getAutomatorBridge() {
8618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (mUiAutomationBridge == null) {
8718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new RuntimeException("UiDevice not initialized");
8818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
8918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return mUiAutomationBridge;
9018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
9118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
9218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
9318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Enables or disables layout hierarchy compression.
9418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
9518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If compression is enabled, the layout hierarchy derived from the Acessibility
9618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * framework will only contain nodes that are important for uiautomator
9718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * testing. Any unnecessary surrounding layout nodes that make viewing
9818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * and searching the hierarchy inefficient are removed.
9918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
10018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param compressed true to enable compression; else, false to disable
10118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
10218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
10318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void setCompressedLayoutHeirarchy(boolean compressed) {
10418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().setCompressedLayoutHierarchy(compressed);
10518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
10618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
10718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
10818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves a singleton instance of UiDevice
10918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
11018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return UiDevice instance
11118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
11218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
11318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public static UiDevice getInstance() {
11418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (sDevice == null) {
11518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            sDevice = new UiDevice();
11618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
11718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return sDevice;
11818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
11918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
12018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
12118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Returns the display size in dp (device-independent pixel)
12218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
12318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The returned display size is adjusted per screen rotation. Also this will return the actual
12418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * size of the screen, rather than adjusted per system decorations (like status bar).
12518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
12618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return a Point containing the display size in dp
12718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
12818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public Point getDisplaySizeDp() {
12918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
13018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Display display = getAutomatorBridge().getDefaultDisplay();
13118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point p = new Point();
13218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        display.getRealSize(p);
13318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        DisplayMetrics metrics = new DisplayMetrics();
13418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        display.getRealMetrics(metrics);
13518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        float dpx = p.x / metrics.density;
13618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        float dpy = p.y / metrics.density;
13718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p.x = Math.round(dpx);
13818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        p.y = Math.round(dpy);
13918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return p;
14018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
14118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
14218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
14318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the product name of the device.
14418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
14518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method provides information on what type of device the test is running on. This value is
14618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * the same as returned by invoking #adb shell getprop ro.product.name.
14718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
14818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return product name of the device
14918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
15018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
15118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getProductName() {
15218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
15318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return Build.PRODUCT;
15418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
15518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
15618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
15718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the text from the last UI traversal event received.
15818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
15918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * You can use this method to read the contents in a WebView container
16018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * because the accessibility framework fires events
16118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * as each text is highlighted. You can write a test to perform
16218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * directional arrow presses to focus on different elements inside a WebView,
16318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * and call this method to get the text from each traversed element.
16418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If you are testing a view container that can return a reference to a
16518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Document Object Model (DOM) object, your test should use the view's
16618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * DOM instead.
16718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
16818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return text of the last traversal event, else return an empty string
16918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
17018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
17118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getLastTraversedText() {
17218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
17318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getQueryController().getLastTraversedText();
17418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
17518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
17618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
17718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Clears the text from the last UI traversal event.
17818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #getLastTraversedText()}.
17918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
18018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
18118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void clearLastTraversedText() {
18218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
18318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getQueryController().clearLastTraversedText();
18418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
18518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
18618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
18718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the MENU button.
18818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
18918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
19018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
19118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressMenu() {
19218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
19318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
19418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent(
19518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                KeyEvent.KEYCODE_MENU, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
19618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                KEY_PRESS_EVENT_TIMEOUT);
19718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
19818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
19918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
20018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the BACK button.
20118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
20218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
20318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
20418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressBack() {
20518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
20618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
20718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent(
20818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                KeyEvent.KEYCODE_BACK, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
20918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                KEY_PRESS_EVENT_TIMEOUT);
21018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
21118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
21218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
21318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the HOME button.
21418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
21518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
21618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
21718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressHome() {
21818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
21918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
22018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent(
22118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                KeyEvent.KEYCODE_HOME, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
22218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                KEY_PRESS_EVENT_TIMEOUT);
22318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
22418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
22518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
22618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the SEARCH button.
22718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
22818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
22918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
23018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressSearch() {
23118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
23218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_SEARCH);
23318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
23418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
23518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
23618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the CENTER button.
23718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
23818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
23918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
24018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressDPadCenter() {
24118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
24218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_DPAD_CENTER);
24318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
24418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
24518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
24618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the DOWN button.
24718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
24818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
24918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
25018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressDPadDown() {
25118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
25218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_DPAD_DOWN);
25318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
25418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
25518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
25618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the UP button.
25718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
25818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
25918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
26018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressDPadUp() {
26118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
26218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_DPAD_UP);
26318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
26418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
26518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
26618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the LEFT button.
26718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
26818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
26918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
27018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressDPadLeft() {
27118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
27218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_DPAD_LEFT);
27318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
27418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
27518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
27618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the RIGHT button.
27718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
27818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
27918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
28018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressDPadRight() {
28118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
28218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_DPAD_RIGHT);
28318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
28418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
28518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
28618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the DELETE key.
28718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
28818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
28918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
29018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressDelete() {
29118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
29218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_DEL);
29318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
29418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
29518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
29618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the ENTER key.
29718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
29818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
29918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
30018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressEnter() {
30118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
30218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return pressKeyCode(KeyEvent.KEYCODE_ENTER);
30318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
30418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
30518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
30618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press using a key code.
30718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
30818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link KeyEvent}
30918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
31018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
31118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
31218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressKeyCode(int keyCode) {
31318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(keyCode);
31418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
31518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().sendKey(keyCode, 0);
31618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
31718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
31818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
31918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press using a key code.
32018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
32118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link KeyEvent}.
32218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param keyCode the key code of the event.
32318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param metaState an integer in which each bit set to 1 represents a pressed meta key
32418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
32518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
32618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
32718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressKeyCode(int keyCode, int metaState) {
32818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(keyCode, metaState);
32918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
33018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().sendKey(keyCode, metaState);
33118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
33218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
33318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
33418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates a short press on the Recent Apps button.
33518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
33618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
33718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
33818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
33918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
34018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean pressRecentApps() throws RemoteException {
34118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
34218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
34318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().toggleRecentApps();
34418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
34518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
34618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
34718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Opens the notification shade.
34818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
34918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
35018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
35118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
35218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean openNotification() {
35318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
35418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
35518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return  getAutomatorBridge().getInteractionController().openNotification();
35618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
35718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
35818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
35918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Opens the Quick Settings shade.
36018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
36118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if successful, else return false
36218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
36318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
36418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean openQuickSettings() {
36518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
36618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
36718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().openQuickSettings();
36818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
36918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
37018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
37118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Gets the width of the display, in pixels. The width and height details
37218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * are reported based on the current orientation of the display.
37318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return width in pixels or zero on failure
37418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
37518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
37618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public int getDisplayWidth() {
37718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
37818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Display display = getAutomatorBridge().getDefaultDisplay();
37918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point p = new Point();
38018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        display.getSize(p);
38118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return p.x;
38218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
38318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
38418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
38518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Gets the height of the display, in pixels. The size is adjusted based
38618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * on the current orientation of the display.
38718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return height in pixels or zero on failure
38818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
38918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
39018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public int getDisplayHeight() {
39118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
39218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Display display = getAutomatorBridge().getDefaultDisplay();
39318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Point p = new Point();
39418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        display.getSize(p);
39518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return p.y;
39618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
39718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
39818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
39918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Perform a click at arbitrary coordinates specified by the user
40018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
40118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param x coordinate
40218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param y coordinate
40318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the click succeeded else false
40418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
40518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
40618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean click(int x, int y) {
40718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(x, y);
40818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (x >= getDisplayWidth() || y >= getDisplayHeight()) {
40918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return (false);
41018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
41118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().clickNoSync(x, y);
41218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
41318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
41418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
41518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a swipe from one coordinate to another using the number of steps
41618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to determine smoothness and speed. Each step execution is throttled to 5ms
41718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * per step. So for a 100 steps, the swipe will take about 1/2 second to complete.
41818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
41918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param startX
42018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param startY
42118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param endX
42218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param endY
42318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps is the number of move steps sent to the system
42418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return false if the operation fails or the coordinates are invalid
42518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
42618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
42718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean swipe(int startX, int startY, int endX, int endY, int steps) {
42818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(startX, startY, endX, endY, steps);
42918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController()
43018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                .swipe(startX, startY, endX, endY, steps);
43118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
43218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
43318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
43418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a swipe from one coordinate to another coordinate. You can control
43518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * the smoothness and speed of the swipe by specifying the number of steps.
43618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Each step execution is throttled to 5 milliseconds per step, so for a 100
43718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * steps, the swipe will take around 0.5 seconds to complete.
43818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
43918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param startX X-axis value for the starting coordinate
44018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param startY Y-axis value for the starting coordinate
44118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param endX X-axis value for the ending coordinate
44218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param endY Y-axis value for the ending coordinate
44318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param steps is the number of steps for the swipe action
44418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if swipe is performed, false if the operation fails
44518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * or the coordinates are invalid
44618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 18
44718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
44818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean drag(int startX, int startY, int endX, int endY, int steps) {
44918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(startX, startY, endX, endY, steps);
45018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController()
45118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                .swipe(startX, startY, endX, endY, steps, true);
45218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
45318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
45418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
45518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Performs a swipe between points in the Point array. Each step execution is throttled
45618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to 5ms per step. So for a 100 steps, the swipe will take about 1/2 second to complete
45718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
45818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param segments is Point array containing at least one Point object
45918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param segmentSteps steps to inject between two Points
46018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true on success
46118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
46218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
46318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean swipe(Point[] segments, int segmentSteps) {
46418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(segments, segmentSteps);
46518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().swipe(segments, segmentSteps);
46618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
46718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
46818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
46918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Waits for the current application to idle.
47018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Default wait timeout is 10 seconds
47118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
47218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
47318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void waitForIdle() {
47418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
47518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle(Configurator.getInstance().getWaitForIdleTimeout());
47618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
47718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
47818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
47918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Waits for the current application to idle.
48018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param timeout in milliseconds
48118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
48218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
48318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void waitForIdle(long timeout) {
48418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(timeout);
48518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().waitForIdle(timeout);
48618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
48718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
48818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
48918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the last activity to report accessibility events.
49018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @deprecated The results returned should be considered unreliable
49118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return String name of activity
49218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
49318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
49418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    @Deprecated
49518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getCurrentActivityName() {
49618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
49718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getQueryController().getCurrentActivityName();
49818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
49918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
50018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
50118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Retrieves the name of the last package to report accessibility events.
50218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return String name of package
50318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
50418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
50518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public String getCurrentPackageName() {
50618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
50718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getQueryController().getCurrentPackageName();
50818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
50918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
51018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
51118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Registers a {@link UiWatcher} to run automatically when the testing framework is unable to
51218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * find a match using a {@link UiSelector}. See {@link #runWatchers()}
51318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
51418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param name to register the UiWatcher
51518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param watcher {@link UiWatcher}
51618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
51718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
51818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void registerWatcher(String name, UiWatcher watcher) {
51918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(name, watcher);
52018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (mInWatcherContext) {
52118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new IllegalStateException("Cannot register new watcher from within another");
52218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
52318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        mWatchers.put(name, watcher);
52418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
52518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
52618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
52718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Removes a previously registered {@link UiWatcher}.
52818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
52918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #registerWatcher(String, UiWatcher)}
53018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param name used to register the UiWatcher
53118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
53218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
53318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void removeWatcher(String name) {
53418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(name);
53518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (mInWatcherContext) {
53618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            throw new IllegalStateException("Cannot remove a watcher from within another");
53718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
53818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        mWatchers.remove(name);
53918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
54018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
54118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
54218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method forces all registered watchers to run.
54318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #registerWatcher(String, UiWatcher)}
54418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
54518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
54618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void runWatchers() {
54718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
54818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (mInWatcherContext) {
54918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return;
55018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
55118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
55218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        for (String watcherName : mWatchers.keySet()) {
55318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            UiWatcher watcher = mWatchers.get(watcherName);
55418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if (watcher != null) {
55518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                try {
55618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    mInWatcherContext = true;
55718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    if (watcher.checkForCondition()) {
55818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                        setWatcherTriggered(watcherName);
55918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    }
56018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                } catch (Exception e) {
56118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    Log.e(LOG_TAG, "Exceuting watcher: " + watcherName, e);
56218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                } finally {
56318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    mInWatcherContext = false;
56418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                }
56518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
56618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
56718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
56818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
56918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
57018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Resets a {@link UiWatcher} that has been triggered.
57118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If a UiWatcher runs and its {@link UiWatcher#checkForCondition()} call
57218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * returned <code>true</code>, then the UiWatcher is considered triggered.
57318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #registerWatcher(String, UiWatcher)}
57418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
57518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
57618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void resetWatcherTriggers() {
57718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
57818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        mWatchersTriggers.clear();
57918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
58018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
58118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
58218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks if a specific registered  {@link UiWatcher} has triggered.
58318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #registerWatcher(String, UiWatcher)}. If a UiWatcher runs and its
58418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * {@link UiWatcher#checkForCondition()} call returned <code>true</code>, then
58518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * the UiWatcher is considered triggered. This is helpful if a watcher is detecting errors
58618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * from ANR or crash dialogs and the test needs to know if a UiWatcher has been triggered.
58718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
58818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param watcherName
58918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if triggered else false
59018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
59118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
59218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean hasWatcherTriggered(String watcherName) {
59318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(watcherName);
59418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return mWatchersTriggers.contains(watcherName);
59518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
59618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
59718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
59818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks if any registered {@link UiWatcher} have triggered.
59918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
60018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #registerWatcher(String, UiWatcher)}
60118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * See {@link #hasWatcherTriggered(String)}
60218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
60318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
60418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean hasAnyWatcherTriggered() {
60518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
60618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return mWatchersTriggers.size() > 0;
60718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
60818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
60918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
61018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Used internally by this class to set a {@link UiWatcher} state as triggered.
61118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param watcherName
61218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
61318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    private void setWatcherTriggered(String watcherName) {
61418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(watcherName);
61518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (!hasWatcherTriggered(watcherName)) {
61618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            mWatchersTriggers.add(watcherName);
61718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
61818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
61918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
62018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
62118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Check if the device is in its natural orientation. This is determined by checking if the
62218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * orientation is at 0 or 180 degrees.
62318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if it is in natural orientation
62418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
62518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
62618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isNaturalOrientation() {
62718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
62818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
62918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        int ret = getAutomatorBridge().getRotation();
63018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return ret == UiAutomation.ROTATION_FREEZE_0 ||
63118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                ret == UiAutomation.ROTATION_FREEZE_180;
63218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
63318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
63418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
63518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Returns the current rotation of the display, as defined in {@link Surface}
63618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
63718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
63818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public int getDisplayRotation() {
63918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
64018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle();
64118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getRotation();
64218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
64318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
64418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
64518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Disables the sensors and freezes the device rotation at its
64618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * current rotation state.
64718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
64818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
64918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
65018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void freezeRotation() throws RemoteException {
65118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
65218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getInteractionController().freezeRotation();
65318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
65418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
65518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
65618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Re-enables the sensors and un-freezes the device rotation allowing its contents
65718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to rotate with the device physical rotation. During a test execution, it is best to
65818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * keep the device frozen in a specific orientation until the test case execution has completed.
65918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
66018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
66118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void unfreezeRotation() throws RemoteException {
66218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
66318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getInteractionController().unfreezeRotation();
66418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
66518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
66618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
66718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates orienting the device to the left and also freezes rotation
66818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * by disabling the sensors.
66918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
67018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If you want to un-freeze the rotation and re-enable the sensors
67118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * see {@link #unfreezeRotation()}.
67218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
67318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
67418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
67518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void setOrientationLeft() throws RemoteException {
67618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
67718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getInteractionController().setRotationLeft();
67818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle(); // we don't need to check for idle on entry for this. We'll sync on exit
67918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
68018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
68118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
68218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates orienting the device to the right and also freezes rotation
68318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * by disabling the sensors.
68418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
68518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If you want to un-freeze the rotation and re-enable the sensors
68618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * see {@link #unfreezeRotation()}.
68718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
68818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
68918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
69018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void setOrientationRight() throws RemoteException {
69118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
69218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getInteractionController().setRotationRight();
69318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle(); // we don't need to check for idle on entry for this. We'll sync on exit
69418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
69518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
69618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
69718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Simulates orienting the device into its natural orientation and also freezes rotation
69818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * by disabling the sensors.
69918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
70018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If you want to un-freeze the rotation and re-enable the sensors
70118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * see {@link #unfreezeRotation()}.
70218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
70318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
70418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
70518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void setOrientationNatural() throws RemoteException {
70618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
70718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getInteractionController().setRotationNatural();
70818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        waitForIdle(); // we don't need to check for idle on entry for this. We'll sync on exit
70918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
71018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
71118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
71218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method simulates pressing the power button if the screen is OFF else
71318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * it does nothing if the screen is already ON.
71418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
71518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If the screen was OFF and it just got turned ON, this method will insert a 500ms delay
71618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * to allow the device time to wake up and accept input.
71718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
71818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
71918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
72018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void wakeUp() throws RemoteException {
72118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
72218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(getAutomatorBridge().getInteractionController().wakeDevice()) {
72318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            // sync delay to allow the window manager to start accepting input
72418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            // after the device is awakened.
72518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            SystemClock.sleep(500);
72618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
72718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
72818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
72918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
73018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Checks the power manager if the screen is ON.
73118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
73218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if the screen is ON else false
73318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
73418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
73518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
73618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean isScreenOn() throws RemoteException {
73718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
73818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().getInteractionController().isScreenOn();
73918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
74018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
74118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
74218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * This method simply presses the power button if the screen is ON else
74318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * it does nothing if the screen is already OFF.
74418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
74518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @throws RemoteException
74618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
74718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
74818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void sleep() throws RemoteException {
74918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace();
75018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        getAutomatorBridge().getInteractionController().sleepDevice();
75118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
75218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
75318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
75418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Helper method used for debugging to dump the current window's layout hierarchy.
75518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The file root location is /data/local/tmp
75618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
75718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param fileName
75818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
75918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
76018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public void dumpWindowHierarchy(String fileName) {
76118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(fileName);
76218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityNodeInfo root =
76318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                getAutomatorBridge().getQueryController().getAccessibilityRootNode();
76418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if(root != null) {
76518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            Display display = getAutomatorBridge().getDefaultDisplay();
76618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            Point size = new Point();
76718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            display.getSize(size);
76818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            AccessibilityNodeInfoDumper.dumpWindowToFile(root,
76918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    new File(new File(Environment.getDataDirectory(), "local/tmp"), fileName),
77018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    display.getRotation(), size.x, size.y);
77118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
77218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
77318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
77418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
77518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Waits for a window content update event to occur.
77618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
77718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * If a package name for the window is specified, but the current window
77818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * does not have the same package name, the function returns immediately.
77918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
78018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param packageName the specified window package name (can be <code>null</code>).
78118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *        If <code>null</code>, a window update from any front-end window will end the wait
78218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param timeout the timeout for the wait
78318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
78418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if a window update occurred, false if timeout has elapsed or if the current
78518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *         window does not have the specified package name
78618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 16
78718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
78818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean waitForWindowUpdate(final String packageName, long timeout) {
78918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(packageName, timeout);
79018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        if (packageName != null) {
79118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            if (!packageName.equals(getCurrentPackageName())) {
79218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                return false;
79318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
79418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
79518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Runnable emptyRunnable = new Runnable() {
79618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            @Override
79718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            public void run() {
79818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
79918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        };
80018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        AccessibilityEventFilter checkWindowUpdate = new AccessibilityEventFilter() {
80118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            @Override
80218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            public boolean accept(AccessibilityEvent t) {
80318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                if (t.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
80418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    return packageName == null || packageName.equals(t.getPackageName());
80518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                }
80618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                return false;
80718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            }
80818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        };
80918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        try {
81018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            getAutomatorBridge().executeCommandAndWaitForAccessibilityEvent(
81118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu                    emptyRunnable, checkWindowUpdate, timeout);
81218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        } catch (TimeoutException e) {
81318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return false;
81418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        } catch (Exception e) {
81518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            Log.e(LOG_TAG, "waitForWindowUpdate: general exception from bridge", e);
81618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu            return false;
81718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        }
81818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return true;
81918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
82018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
82118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
82218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Take a screenshot of current window and store it as PNG
82318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
82418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Default scale of 1.0f (original size) and 90% quality is used
82518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The screenshot is adjusted per screen rotation
82618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
82718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param storePath where the PNG should be written to
82818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if screen shot is created successfully, false otherwise
82918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
83018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
83118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean takeScreenshot(File storePath) {
83218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(storePath);
83318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return takeScreenshot(storePath, 1.0f, 90);
83418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
83518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu
83618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    /**
83718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * Take a screenshot of current window and store it as PNG
83818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
83918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * The screenshot is adjusted per screen rotation
84018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     *
84118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param storePath where the PNG should be written to
84218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param scale scale the screenshot down if needed; 1.0f for original size
84318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @param quality quality of the PNG compression; range: 0-100
84418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @return true if screen shot is created successfully, false otherwise
84518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     * @since API Level 17
84618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu     */
84718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    public boolean takeScreenshot(File storePath, float scale, int quality) {
84818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        Tracer.trace(storePath, scale, quality);
84918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu        return getAutomatorBridge().takeScreenshot(storePath, quality);
85018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu    }
85118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu}
852