diff --git a/api/current.txt b/api/current.txt index c8f999fd2403d..d1155c4d191d7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4155,9 +4155,12 @@ package android.app { public final class UiAutomation { method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, com.android.internal.util.Predicate, long) throws java.util.concurrent.TimeoutException; method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow(); + method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); method public boolean injectInputEvent(android.view.InputEvent, boolean); + method public final boolean performGlobalAction(int); method public void setOnAccessibilityEventListener(android.app.UiAutomation.OnAccessibilityEventListener); method public boolean setRotation(int); + method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo); method public android.graphics.Bitmap takeScreenshot(); method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException; field public static final int ROTATION_FREEZE_0 = 0; // 0x0 diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 8dddbc10242a5..811b92a5e102c 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -457,7 +457,7 @@ public abstract class AccessibilityService extends Service { * * @return The accessibility service info. * - * @see AccessibilityNodeInfo + * @see AccessibilityServiceInfo */ public final AccessibilityServiceInfo getServiceInfo() { IAccessibilityServiceConnection connection = diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index e611f6da95df2..8d865da02f078 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -18,7 +18,9 @@ package android.app; import android.accessibilityservice.AccessibilityService.Callbacks; import android.accessibilityservice.AccessibilityService.IAccessibilityServiceClientWrapper; +import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; +import android.accessibilityservice.IAccessibilityServiceConnection; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; @@ -45,7 +47,10 @@ import java.util.concurrent.TimeoutException; * introspection of the screen content. It relies on the platform accessibility * APIs to introspect the screen and to perform some actions on the remote view * tree. It also allows injecting of arbitrary raw input events simulating user - * interaction with keyboards and touch devices. + * interaction with keyboards and touch devices. One can think of a UiAutomation + * as a special type of {@link android.accessibilityservice.AccessibilityService} + * which does not provide hooks for the service life cycle and exposes other + * APIs that are useful for UI test automation. *

* The APIs exposed by this class are low-level to maximize flexibility when * developing UI test automation tools and libraries. Generally, a UiAutomation @@ -242,6 +247,90 @@ public final class UiAutomation { } } + /** + * Performs a global action. Such an action can be performed at any moment + * regardless of the current application or user location in that application. + * For example going back, going home, opening recents, etc. + * + * @param action The action to perform. + * @return Whether the action was successfully performed. + * + * @see AccessibilityService#GLOBAL_ACTION_BACK + * @see AccessibilityService#GLOBAL_ACTION_HOME + * @see AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS + * @see AccessibilityService#GLOBAL_ACTION_RECENTS + */ + public final boolean performGlobalAction(int action) { + final IAccessibilityServiceConnection connection; + synchronized (mLock) { + throwIfNotConnectedLocked(); + connection = AccessibilityInteractionClient.getInstance() + .getConnection(mConnectionId); + } + // Calling out without a lock held. + if (connection != null) { + try { + return connection.performGlobalAction(action); + } catch (RemoteException re) { + Log.w(LOG_TAG, "Error while calling performGlobalAction", re); + } + } + return false; + } + + /** + * Gets the an {@link AccessibilityServiceInfo} describing this UiAutomation. + * This method is useful if one wants to change some of the dynamically + * configurable properties at runtime. + * + * @return The accessibility service info. + * + * @see AccessibilityServiceInfo + */ + public final AccessibilityServiceInfo getServiceInfo() { + final IAccessibilityServiceConnection connection; + synchronized (mLock) { + throwIfNotConnectedLocked(); + connection = AccessibilityInteractionClient.getInstance() + .getConnection(mConnectionId); + } + // Calling out without a lock held. + if (connection != null) { + try { + return connection.getServiceInfo(); + } catch (RemoteException re) { + Log.w(LOG_TAG, "Error while getting AccessibilityServiceInfo", re); + } + } + return null; + } + + /** + * Sets the {@link AccessibilityServiceInfo} that describes how this + * UiAutomation will be handled by the platform accessibility layer. + * + * @param info The info. + * + * @see AccessibilityServiceInfo + */ + public final void setServiceInfo(AccessibilityServiceInfo info) { + final IAccessibilityServiceConnection connection; + synchronized (mLock) { + throwIfNotConnectedLocked(); + AccessibilityInteractionClient.getInstance().clearCache(); + connection = AccessibilityInteractionClient.getInstance() + .getConnection(mConnectionId); + } + // Calling out without a lock held. + if (connection != null) { + try { + connection.setServiceInfo(info); + } catch (RemoteException re) { + Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re); + } + } + } + /** * Gets the root {@link AccessibilityNodeInfo} in the active window. *