| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.uiautomator.core; |
| |
| import android.app.UiAutomation; |
| import android.app.UiAutomation.AccessibilityEventFilter; |
| import android.graphics.Point; |
| import android.os.Build; |
| import android.os.Environment; |
| import android.os.RemoteException; |
| import android.os.SystemClock; |
| import android.util.DisplayMetrics; |
| import android.util.Log; |
| import android.view.Display; |
| import android.view.KeyEvent; |
| import android.view.Surface; |
| import android.view.accessibility.AccessibilityEvent; |
| import android.view.accessibility.AccessibilityNodeInfo; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.concurrent.TimeoutException; |
| |
| /** |
| * UiDevice provides access to state information about the device. |
| * You can also use this class to simulate user actions on the device, |
| * such as pressing the d-pad or pressing the Home and Menu buttons. |
| * @since API Level 16 |
| * @deprecated New tests should be written using UI Automator 2.0 which is available as part of the |
| * Android Testing Support Library. |
| */ |
| @Deprecated |
| public class UiDevice { |
| private static final String LOG_TAG = UiDevice.class.getSimpleName(); |
| |
| // Sometimes HOME and BACK key presses will generate no events if already on |
| // home page or there is nothing to go back to, Set low timeouts. |
| private static final long KEY_PRESS_EVENT_TIMEOUT = 1 * 1000; |
| |
| // store for registered UiWatchers |
| private final HashMap<String, UiWatcher> mWatchers = new HashMap<String, UiWatcher>(); |
| private final List<String> mWatchersTriggers = new ArrayList<String>(); |
| |
| // remember if we're executing in the context of a UiWatcher |
| private boolean mInWatcherContext = false; |
| |
| // provides access the {@link QueryController} and {@link InteractionController} |
| private UiAutomatorBridge mUiAutomationBridge; |
| |
| // reference to self |
| private static UiDevice sDevice; |
| |
| private UiDevice() { |
| /* hide constructor */ |
| } |
| |
| /** |
| * @hide |
| */ |
| public void initialize(UiAutomatorBridge uiAutomatorBridge) { |
| mUiAutomationBridge = uiAutomatorBridge; |
| } |
| |
| boolean isInWatcherContext() { |
| return mInWatcherContext; |
| } |
| |
| /** |
| * Provides access the {@link QueryController} and {@link InteractionController} |
| * @return {@link ShellUiAutomatorBridge} |
| */ |
| UiAutomatorBridge getAutomatorBridge() { |
| if (mUiAutomationBridge == null) { |
| throw new RuntimeException("UiDevice not initialized"); |
| } |
| return mUiAutomationBridge; |
| } |
| |
| /** |
| * Enables or disables layout hierarchy compression. |
| * |
| * If compression is enabled, the layout hierarchy derived from the Acessibility |
| * framework will only contain nodes that are important for uiautomator |
| * testing. Any unnecessary surrounding layout nodes that make viewing |
| * and searching the hierarchy inefficient are removed. |
| * |
| * @param compressed true to enable compression; else, false to disable |
| * @since API Level 18 |
| */ |
| public void setCompressedLayoutHeirarchy(boolean compressed) { |
| getAutomatorBridge().setCompressedLayoutHierarchy(compressed); |
| } |
| |
| /** |
| * Retrieves a singleton instance of UiDevice |
| * |
| * @return UiDevice instance |
| * @since API Level 16 |
| */ |
| public static UiDevice getInstance() { |
| if (sDevice == null) { |
| sDevice = new UiDevice(); |
| } |
| return sDevice; |
| } |
| |
| /** |
| * Returns the display size in dp (device-independent pixel) |
| * |
| * The returned display size is adjusted per screen rotation. Also this will return the actual |
| * size of the screen, rather than adjusted per system decorations (like status bar). |
| * |
| * @return a Point containing the display size in dp |
| */ |
| public Point getDisplaySizeDp() { |
| Tracer.trace(); |
| Display display = getAutomatorBridge().getDefaultDisplay(); |
| Point p = new Point(); |
| display.getRealSize(p); |
| DisplayMetrics metrics = new DisplayMetrics(); |
| display.getRealMetrics(metrics); |
| float dpx = p.x / metrics.density; |
| float dpy = p.y / metrics.density; |
| p.x = Math.round(dpx); |
| p.y = Math.round(dpy); |
| return p; |
| } |
| |
| /** |
| * Retrieves the product name of the device. |
| * |
| * This method provides information on what type of device the test is running on. This value is |
| * the same as returned by invoking #adb shell getprop ro.product.name. |
| * |
| * @return product name of the device |
| * @since API Level 17 |
| */ |
| public String getProductName() { |
| Tracer.trace(); |
| return Build.PRODUCT; |
| } |
| |
| /** |
| * Retrieves the text from the last UI traversal event received. |
| * |
| * You can use this method to read the contents in a WebView container |
| * because the accessibility framework fires events |
| * as each text is highlighted. You can write a test to perform |
| * directional arrow presses to focus on different elements inside a WebView, |
| * and call this method to get the text from each traversed element. |
| * If you are testing a view container that can return a reference to a |
| * Document Object Model (DOM) object, your test should use the view's |
| * DOM instead. |
| * |
| * @return text of the last traversal event, else return an empty string |
| * @since API Level 16 |
| */ |
| public String getLastTraversedText() { |
| Tracer.trace(); |
| return getAutomatorBridge().getQueryController().getLastTraversedText(); |
| } |
| |
| /** |
| * Clears the text from the last UI traversal event. |
| * See {@link #getLastTraversedText()}. |
| * @since API Level 16 |
| */ |
| public void clearLastTraversedText() { |
| Tracer.trace(); |
| getAutomatorBridge().getQueryController().clearLastTraversedText(); |
| } |
| |
| /** |
| * Simulates a short press on the MENU button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressMenu() { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent( |
| KeyEvent.KEYCODE_MENU, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, |
| KEY_PRESS_EVENT_TIMEOUT); |
| } |
| |
| /** |
| * Simulates a short press on the BACK button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressBack() { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent( |
| KeyEvent.KEYCODE_BACK, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, |
| KEY_PRESS_EVENT_TIMEOUT); |
| } |
| |
| /** |
| * Simulates a short press on the HOME button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressHome() { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent( |
| KeyEvent.KEYCODE_HOME, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, |
| KEY_PRESS_EVENT_TIMEOUT); |
| } |
| |
| /** |
| * Simulates a short press on the SEARCH button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressSearch() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_SEARCH); |
| } |
| |
| /** |
| * Simulates a short press on the CENTER button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressDPadCenter() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_DPAD_CENTER); |
| } |
| |
| /** |
| * Simulates a short press on the DOWN button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressDPadDown() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_DPAD_DOWN); |
| } |
| |
| /** |
| * Simulates a short press on the UP button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressDPadUp() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_DPAD_UP); |
| } |
| |
| /** |
| * Simulates a short press on the LEFT button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressDPadLeft() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_DPAD_LEFT); |
| } |
| |
| /** |
| * Simulates a short press on the RIGHT button. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressDPadRight() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_DPAD_RIGHT); |
| } |
| |
| /** |
| * Simulates a short press on the DELETE key. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressDelete() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_DEL); |
| } |
| |
| /** |
| * Simulates a short press on the ENTER key. |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressEnter() { |
| Tracer.trace(); |
| return pressKeyCode(KeyEvent.KEYCODE_ENTER); |
| } |
| |
| /** |
| * Simulates a short press using a key code. |
| * |
| * See {@link KeyEvent} |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressKeyCode(int keyCode) { |
| Tracer.trace(keyCode); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().sendKey(keyCode, 0); |
| } |
| |
| /** |
| * Simulates a short press using a key code. |
| * |
| * See {@link KeyEvent}. |
| * @param keyCode the key code of the event. |
| * @param metaState an integer in which each bit set to 1 represents a pressed meta key |
| * @return true if successful, else return false |
| * @since API Level 16 |
| */ |
| public boolean pressKeyCode(int keyCode, int metaState) { |
| Tracer.trace(keyCode, metaState); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().sendKey(keyCode, metaState); |
| } |
| |
| /** |
| * Simulates a short press on the Recent Apps button. |
| * |
| * @return true if successful, else return false |
| * @throws RemoteException |
| * @since API Level 16 |
| */ |
| public boolean pressRecentApps() throws RemoteException { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().toggleRecentApps(); |
| } |
| |
| /** |
| * Opens the notification shade. |
| * |
| * @return true if successful, else return false |
| * @since API Level 18 |
| */ |
| public boolean openNotification() { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().openNotification(); |
| } |
| |
| /** |
| * Opens the Quick Settings shade. |
| * |
| * @return true if successful, else return false |
| * @since API Level 18 |
| */ |
| public boolean openQuickSettings() { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getInteractionController().openQuickSettings(); |
| } |
| |
| /** |
| * Gets the width of the display, in pixels. The width and height details |
| * are reported based on the current orientation of the display. |
| * @return width in pixels or zero on failure |
| * @since API Level 16 |
| */ |
| public int getDisplayWidth() { |
| Tracer.trace(); |
| Display display = getAutomatorBridge().getDefaultDisplay(); |
| Point p = new Point(); |
| display.getSize(p); |
| return p.x; |
| } |
| |
| /** |
| * Gets the height of the display, in pixels. The size is adjusted based |
| * on the current orientation of the display. |
| * @return height in pixels or zero on failure |
| * @since API Level 16 |
| */ |
| public int getDisplayHeight() { |
| Tracer.trace(); |
| Display display = getAutomatorBridge().getDefaultDisplay(); |
| Point p = new Point(); |
| display.getSize(p); |
| return p.y; |
| } |
| |
| /** |
| * Perform a click at arbitrary coordinates specified by the user |
| * |
| * @param x coordinate |
| * @param y coordinate |
| * @return true if the click succeeded else false |
| * @since API Level 16 |
| */ |
| public boolean click(int x, int y) { |
| Tracer.trace(x, y); |
| if (x >= getDisplayWidth() || y >= getDisplayHeight()) { |
| return (false); |
| } |
| return getAutomatorBridge().getInteractionController().clickNoSync(x, y); |
| } |
| |
| /** |
| * Performs a swipe from one coordinate to another using the number of steps |
| * to determine smoothness and speed. Each step execution is throttled to 5ms |
| * per step. So for a 100 steps, the swipe will take about 1/2 second to complete. |
| * |
| * @param startX |
| * @param startY |
| * @param endX |
| * @param endY |
| * @param steps is the number of move steps sent to the system |
| * @return false if the operation fails or the coordinates are invalid |
| * @since API Level 16 |
| */ |
| public boolean swipe(int startX, int startY, int endX, int endY, int steps) { |
| Tracer.trace(startX, startY, endX, endY, steps); |
| return getAutomatorBridge().getInteractionController() |
| .swipe(startX, startY, endX, endY, steps); |
| } |
| |
| /** |
| * Performs a swipe from one coordinate to another coordinate. You can control |
| * the smoothness and speed of the swipe by specifying the number of steps. |
| * Each step execution is throttled to 5 milliseconds per step, so for a 100 |
| * steps, the swipe will take around 0.5 seconds to complete. |
| * |
| * @param startX X-axis value for the starting coordinate |
| * @param startY Y-axis value for the starting coordinate |
| * @param endX X-axis value for the ending coordinate |
| * @param endY Y-axis value for the ending coordinate |
| * @param steps is the number of steps for the swipe action |
| * @return true if swipe is performed, false if the operation fails |
| * or the coordinates are invalid |
| * @since API Level 18 |
| */ |
| public boolean drag(int startX, int startY, int endX, int endY, int steps) { |
| Tracer.trace(startX, startY, endX, endY, steps); |
| return getAutomatorBridge().getInteractionController() |
| .swipe(startX, startY, endX, endY, steps, true); |
| } |
| |
| /** |
| * Performs a swipe between points in the Point array. Each step execution is throttled |
| * to 5ms per step. So for a 100 steps, the swipe will take about 1/2 second to complete |
| * |
| * @param segments is Point array containing at least one Point object |
| * @param segmentSteps steps to inject between two Points |
| * @return true on success |
| * @since API Level 16 |
| */ |
| public boolean swipe(Point[] segments, int segmentSteps) { |
| Tracer.trace(segments, segmentSteps); |
| return getAutomatorBridge().getInteractionController().swipe(segments, segmentSteps); |
| } |
| |
| /** |
| * Waits for the current application to idle. |
| * Default wait timeout is 10 seconds |
| * @since API Level 16 |
| */ |
| public void waitForIdle() { |
| Tracer.trace(); |
| waitForIdle(Configurator.getInstance().getWaitForIdleTimeout()); |
| } |
| |
| /** |
| * Waits for the current application to idle. |
| * @param timeout in milliseconds |
| * @since API Level 16 |
| */ |
| public void waitForIdle(long timeout) { |
| Tracer.trace(timeout); |
| getAutomatorBridge().waitForIdle(timeout); |
| } |
| |
| /** |
| * Retrieves the last activity to report accessibility events. |
| * @deprecated The results returned should be considered unreliable |
| * @return String name of activity |
| * @since API Level 16 |
| */ |
| @Deprecated |
| public String getCurrentActivityName() { |
| Tracer.trace(); |
| return getAutomatorBridge().getQueryController().getCurrentActivityName(); |
| } |
| |
| /** |
| * Retrieves the name of the last package to report accessibility events. |
| * @return String name of package |
| * @since API Level 16 |
| */ |
| public String getCurrentPackageName() { |
| Tracer.trace(); |
| return getAutomatorBridge().getQueryController().getCurrentPackageName(); |
| } |
| |
| /** |
| * Registers a {@link UiWatcher} to run automatically when the testing framework is unable to |
| * find a match using a {@link UiSelector}. See {@link #runWatchers()} |
| * |
| * @param name to register the UiWatcher |
| * @param watcher {@link UiWatcher} |
| * @since API Level 16 |
| */ |
| public void registerWatcher(String name, UiWatcher watcher) { |
| Tracer.trace(name, watcher); |
| if (mInWatcherContext) { |
| throw new IllegalStateException("Cannot register new watcher from within another"); |
| } |
| mWatchers.put(name, watcher); |
| } |
| |
| /** |
| * Removes a previously registered {@link UiWatcher}. |
| * |
| * See {@link #registerWatcher(String, UiWatcher)} |
| * @param name used to register the UiWatcher |
| * @since API Level 16 |
| */ |
| public void removeWatcher(String name) { |
| Tracer.trace(name); |
| if (mInWatcherContext) { |
| throw new IllegalStateException("Cannot remove a watcher from within another"); |
| } |
| mWatchers.remove(name); |
| } |
| |
| /** |
| * This method forces all registered watchers to run. |
| * See {@link #registerWatcher(String, UiWatcher)} |
| * @since API Level 16 |
| */ |
| public void runWatchers() { |
| Tracer.trace(); |
| if (mInWatcherContext) { |
| return; |
| } |
| |
| for (String watcherName : mWatchers.keySet()) { |
| UiWatcher watcher = mWatchers.get(watcherName); |
| if (watcher != null) { |
| try { |
| mInWatcherContext = true; |
| if (watcher.checkForCondition()) { |
| setWatcherTriggered(watcherName); |
| } |
| } catch (Exception e) { |
| Log.e(LOG_TAG, "Exceuting watcher: " + watcherName, e); |
| } finally { |
| mInWatcherContext = false; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Resets a {@link UiWatcher} that has been triggered. |
| * If a UiWatcher runs and its {@link UiWatcher#checkForCondition()} call |
| * returned <code>true</code>, then the UiWatcher is considered triggered. |
| * See {@link #registerWatcher(String, UiWatcher)} |
| * @since API Level 16 |
| */ |
| public void resetWatcherTriggers() { |
| Tracer.trace(); |
| mWatchersTriggers.clear(); |
| } |
| |
| /** |
| * Checks if a specific registered {@link UiWatcher} has triggered. |
| * See {@link #registerWatcher(String, UiWatcher)}. If a UiWatcher runs and its |
| * {@link UiWatcher#checkForCondition()} call returned <code>true</code>, then |
| * the UiWatcher is considered triggered. This is helpful if a watcher is detecting errors |
| * from ANR or crash dialogs and the test needs to know if a UiWatcher has been triggered. |
| * |
| * @param watcherName |
| * @return true if triggered else false |
| * @since API Level 16 |
| */ |
| public boolean hasWatcherTriggered(String watcherName) { |
| Tracer.trace(watcherName); |
| return mWatchersTriggers.contains(watcherName); |
| } |
| |
| /** |
| * Checks if any registered {@link UiWatcher} have triggered. |
| * |
| * See {@link #registerWatcher(String, UiWatcher)} |
| * See {@link #hasWatcherTriggered(String)} |
| * @since API Level 16 |
| */ |
| public boolean hasAnyWatcherTriggered() { |
| Tracer.trace(); |
| return mWatchersTriggers.size() > 0; |
| } |
| |
| /** |
| * Used internally by this class to set a {@link UiWatcher} state as triggered. |
| * @param watcherName |
| */ |
| private void setWatcherTriggered(String watcherName) { |
| Tracer.trace(watcherName); |
| if (!hasWatcherTriggered(watcherName)) { |
| mWatchersTriggers.add(watcherName); |
| } |
| } |
| |
| /** |
| * Check if the device is in its natural orientation. This is determined by checking if the |
| * orientation is at 0 or 180 degrees. |
| * @return true if it is in natural orientation |
| * @since API Level 17 |
| */ |
| public boolean isNaturalOrientation() { |
| Tracer.trace(); |
| waitForIdle(); |
| int ret = getAutomatorBridge().getRotation(); |
| return ret == UiAutomation.ROTATION_FREEZE_0 || |
| ret == UiAutomation.ROTATION_FREEZE_180; |
| } |
| |
| /** |
| * Returns the current rotation of the display, as defined in {@link Surface} |
| * @since API Level 17 |
| */ |
| public int getDisplayRotation() { |
| Tracer.trace(); |
| waitForIdle(); |
| return getAutomatorBridge().getRotation(); |
| } |
| |
| /** |
| * Disables the sensors and freezes the device rotation at its |
| * current rotation state. |
| * @throws RemoteException |
| * @since API Level 16 |
| */ |
| public void freezeRotation() throws RemoteException { |
| Tracer.trace(); |
| getAutomatorBridge().getInteractionController().freezeRotation(); |
| } |
| |
| /** |
| * Re-enables the sensors and un-freezes the device rotation allowing its contents |
| * to rotate with the device physical rotation. During a test execution, it is best to |
| * keep the device frozen in a specific orientation until the test case execution has completed. |
| * @throws RemoteException |
| */ |
| public void unfreezeRotation() throws RemoteException { |
| Tracer.trace(); |
| getAutomatorBridge().getInteractionController().unfreezeRotation(); |
| } |
| |
| /** |
| * Simulates orienting the device to the left and also freezes rotation |
| * by disabling the sensors. |
| * |
| * If you want to un-freeze the rotation and re-enable the sensors |
| * see {@link #unfreezeRotation()}. |
| * @throws RemoteException |
| * @since API Level 17 |
| */ |
| public void setOrientationLeft() throws RemoteException { |
| Tracer.trace(); |
| getAutomatorBridge().getInteractionController().setRotationLeft(); |
| waitForIdle(); // we don't need to check for idle on entry for this. We'll sync on exit |
| } |
| |
| /** |
| * Simulates orienting the device to the right and also freezes rotation |
| * by disabling the sensors. |
| * |
| * If you want to un-freeze the rotation and re-enable the sensors |
| * see {@link #unfreezeRotation()}. |
| * @throws RemoteException |
| * @since API Level 17 |
| */ |
| public void setOrientationRight() throws RemoteException { |
| Tracer.trace(); |
| getAutomatorBridge().getInteractionController().setRotationRight(); |
| waitForIdle(); // we don't need to check for idle on entry for this. We'll sync on exit |
| } |
| |
| /** |
| * Simulates orienting the device into its natural orientation and also freezes rotation |
| * by disabling the sensors. |
| * |
| * If you want to un-freeze the rotation and re-enable the sensors |
| * see {@link #unfreezeRotation()}. |
| * @throws RemoteException |
| * @since API Level 17 |
| */ |
| public void setOrientationNatural() throws RemoteException { |
| Tracer.trace(); |
| getAutomatorBridge().getInteractionController().setRotationNatural(); |
| waitForIdle(); // we don't need to check for idle on entry for this. We'll sync on exit |
| } |
| |
| /** |
| * This method simulates pressing the power button if the screen is OFF else |
| * it does nothing if the screen is already ON. |
| * |
| * If the screen was OFF and it just got turned ON, this method will insert a 500ms delay |
| * to allow the device time to wake up and accept input. |
| * @throws RemoteException |
| * @since API Level 16 |
| */ |
| public void wakeUp() throws RemoteException { |
| Tracer.trace(); |
| if(getAutomatorBridge().getInteractionController().wakeDevice()) { |
| // sync delay to allow the window manager to start accepting input |
| // after the device is awakened. |
| SystemClock.sleep(500); |
| } |
| } |
| |
| /** |
| * Checks the power manager if the screen is ON. |
| * |
| * @return true if the screen is ON else false |
| * @throws RemoteException |
| * @since API Level 16 |
| */ |
| public boolean isScreenOn() throws RemoteException { |
| Tracer.trace(); |
| return getAutomatorBridge().getInteractionController().isScreenOn(); |
| } |
| |
| /** |
| * This method simply presses the power button if the screen is ON else |
| * it does nothing if the screen is already OFF. |
| * |
| * @throws RemoteException |
| * @since API Level 16 |
| */ |
| public void sleep() throws RemoteException { |
| Tracer.trace(); |
| getAutomatorBridge().getInteractionController().sleepDevice(); |
| } |
| |
| /** |
| * Helper method used for debugging to dump the current window's layout hierarchy. |
| * The file root location is /data/local/tmp |
| * |
| * @param fileName |
| * @since API Level 16 |
| */ |
| public void dumpWindowHierarchy(String fileName) { |
| Tracer.trace(fileName); |
| AccessibilityNodeInfo root = |
| getAutomatorBridge().getQueryController().getAccessibilityRootNode(); |
| if(root != null) { |
| Display display = getAutomatorBridge().getDefaultDisplay(); |
| Point size = new Point(); |
| display.getSize(size); |
| AccessibilityNodeInfoDumper.dumpWindowToFile(root, |
| new File(new File(Environment.getDataDirectory(), "local/tmp"), fileName), |
| display.getRotation(), size.x, size.y); |
| } |
| } |
| |
| /** |
| * Waits for a window content update event to occur. |
| * |
| * If a package name for the window is specified, but the current window |
| * does not have the same package name, the function returns immediately. |
| * |
| * @param packageName the specified window package name (can be <code>null</code>). |
| * If <code>null</code>, a window update from any front-end window will end the wait |
| * @param timeout the timeout for the wait |
| * |
| * @return true if a window update occurred, false if timeout has elapsed or if the current |
| * window does not have the specified package name |
| * @since API Level 16 |
| */ |
| public boolean waitForWindowUpdate(final String packageName, long timeout) { |
| Tracer.trace(packageName, timeout); |
| if (packageName != null) { |
| if (!packageName.equals(getCurrentPackageName())) { |
| return false; |
| } |
| } |
| Runnable emptyRunnable = new Runnable() { |
| @Override |
| public void run() { |
| } |
| }; |
| AccessibilityEventFilter checkWindowUpdate = new AccessibilityEventFilter() { |
| @Override |
| public boolean accept(AccessibilityEvent t) { |
| if (t.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) { |
| return packageName == null || packageName.equals(t.getPackageName()); |
| } |
| return false; |
| } |
| }; |
| try { |
| getAutomatorBridge().executeCommandAndWaitForAccessibilityEvent( |
| emptyRunnable, checkWindowUpdate, timeout); |
| } catch (TimeoutException e) { |
| return false; |
| } catch (Exception e) { |
| Log.e(LOG_TAG, "waitForWindowUpdate: general exception from bridge", e); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Take a screenshot of current window and store it as PNG |
| * |
| * Default scale of 1.0f (original size) and 90% quality is used |
| * The screenshot is adjusted per screen rotation |
| * |
| * @param storePath where the PNG should be written to |
| * @return true if screen shot is created successfully, false otherwise |
| * @since API Level 17 |
| */ |
| public boolean takeScreenshot(File storePath) { |
| Tracer.trace(storePath); |
| return takeScreenshot(storePath, 1.0f, 90); |
| } |
| |
| /** |
| * Take a screenshot of current window and store it as PNG |
| * |
| * The screenshot is adjusted per screen rotation |
| * |
| * @param storePath where the PNG should be written to |
| * @param scale scale the screenshot down if needed; 1.0f for original size |
| * @param quality quality of the PNG compression; range: 0-100 |
| * @return true if screen shot is created successfully, false otherwise |
| * @since API Level 17 |
| */ |
| public boolean takeScreenshot(File storePath, float scale, int quality) { |
| Tracer.trace(storePath, scale, quality); |
| return getAutomatorBridge().takeScreenshot(storePath, quality); |
| } |
| } |