Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -6532,6 +6532,7 @@ package android.app { method public android.graphics.Bitmap takeScreenshot(); method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException; field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1 field public static final int FLAG_DONT_USE_ACCESSIBILITY = 2; // 0x2 field public static final int ROTATION_FREEZE_0 = 0; // 0x0 field public static final int ROTATION_FREEZE_180 = 2; // 0x2 field public static final int ROTATION_FREEZE_270 = 3; // 0x3 core/java/android/app/Instrumentation.java +4 −2 Original line number Diff line number Diff line Loading @@ -97,7 +97,8 @@ public class Instrumentation { * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}) @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES, UiAutomation.FLAG_DONT_USE_ACCESSIBILITY}) public @interface UiAutomationFlags {}; Loading Loading @@ -2170,7 +2171,8 @@ public class Instrumentation { * </p> * * @param flags The flags to be passed to the UiAutomation, for example * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}. * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}, * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY}. * * @return The UI automation instance. * Loading core/java/android/app/UiAutomation.java +77 −52 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.IAccessibilityInteractionConnection; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.pooled.PooledLambda; import libcore.io.IoUtils; Loading Loading @@ -142,13 +143,22 @@ public final class UiAutomation { } /** * UiAutomation supresses accessibility services by default. This flag specifies that * UiAutomation suppresses accessibility services by default. This flag specifies that * existing accessibility services should continue to run, and that new ones may start. * This flag is set when obtaining the UiAutomation from * {@link Instrumentation#getUiAutomation(int)}. */ public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 0x00000001; /** * UiAutomation uses the accessibility subsystem by default. This flag provides an option to * eliminate the overhead of engaging the accessibility subsystem for tests that do not need to * interact with the user interface. Setting this flag disables methods that rely on * accessibility. This flag is set when obtaining the UiAutomation from * {@link Instrumentation#getUiAutomation(int)}. */ public static final int FLAG_DONT_USE_ACCESSIBILITY = 0x00000002; private final Object mLock = new Object(); private final ArrayList<AccessibilityEvent> mEventQueue = new ArrayList<AccessibilityEvent>(); Loading Loading @@ -267,11 +277,14 @@ public final class UiAutomation { /** * Connects this UiAutomation to the accessibility introspection APIs. * * @param flags Any flags to apply to the automation as it gets connected * @param flags Any flags to apply to the automation as it gets connected while * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY} would keep the * connection disconnected and not to register UiAutomation service. * @param timeoutMillis The wait timeout in milliseconds * * @throws IllegalStateException If the connection to the accessibility subsystem is already * established. * @throws TimeoutException If not connected within the timeout * * @hide */ public void connectWithTimeout(int flags, long timeoutMillis) throws TimeoutException { Loading @@ -292,6 +305,12 @@ public final class UiAutomation { // Calling out without a lock held. mUiAutomationConnection.connect(mClient, flags); mFlags = flags; // If UiAutomation is not allowed to use the accessibility subsystem, the // connection state should keep disconnected and not to start the client connection. if (!useAccessibility()) { mConnectionState = ConnectionState.DISCONNECTED; return; } } catch (RemoteException re) { throw new RuntimeException("Error while connecting " + this, re); } Loading Loading @@ -340,7 +359,7 @@ public final class UiAutomation { throw new IllegalStateException( "Cannot call disconnect() while connecting " + this); } if (mConnectionState == ConnectionState.DISCONNECTED) { if (useAccessibility() && mConnectionState == ConnectionState.DISCONNECTED) { return; } mConnectionState = ConnectionState.DISCONNECTED; Loading @@ -354,10 +373,12 @@ public final class UiAutomation { } catch (RemoteException re) { throw new RuntimeException("Error while disconnecting " + this, re); } finally { if (mRemoteCallbackThread != null) { mRemoteCallbackThread.quit(); mRemoteCallbackThread = null; } } } /** * The id of the {@link IAccessibilityInteractionConnection} for querying Loading Loading @@ -389,9 +410,13 @@ public final class UiAutomation { * The callbacks are delivered on the main application thread. * * @param listener The callback. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public void setOnAccessibilityEventListener(OnAccessibilityEventListener listener) { synchronized (mLock) { throwIfNotConnectedLocked(); mOnAccessibilityEventListener = listener; } } Loading Loading @@ -423,9 +448,6 @@ public final class UiAutomation { * @see #dropShellPermissionIdentity() */ public void adoptShellPermissionIdentity() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), null); Loading @@ -451,9 +473,6 @@ public final class UiAutomation { * @see #dropShellPermissionIdentity() */ public void adoptShellPermissionIdentity(@Nullable String... permissions) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), permissions); Loading @@ -470,9 +489,6 @@ public final class UiAutomation { * @see #adoptShellPermissionIdentity() */ public void dropShellPermissionIdentity() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.dropShellPermissionIdentity(); Loading @@ -489,6 +505,8 @@ public final class UiAutomation { * @param action The action to perform. * @return Whether the action was successfully performed. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_HOME * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS Loading Loading @@ -526,10 +544,15 @@ public final class UiAutomation { * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. * @return The node info of the focused view or null. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see AccessibilityNodeInfo#FOCUS_INPUT * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY */ public AccessibilityNodeInfo findFocus(int focus) { synchronized (mLock) { throwIfNotConnectedLocked(); } return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus); } Loading @@ -541,6 +564,8 @@ public final class UiAutomation { * * @return The accessibility service info. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see AccessibilityServiceInfo */ public final AccessibilityServiceInfo getServiceInfo() { Loading @@ -567,6 +592,8 @@ public final class UiAutomation { * * @param info The info. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see AccessibilityServiceInfo */ public final void setServiceInfo(AccessibilityServiceInfo info) { Loading Loading @@ -602,6 +629,8 @@ public final class UiAutomation { * </p> * * @return The windows if there are windows such, otherwise an empty list. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public List<AccessibilityWindowInfo> getWindows() { final int connectionId; Loading Loading @@ -630,6 +659,8 @@ public final class UiAutomation { * * @return The windows of all displays if there are windows and the service is can retrieve * them, otherwise an empty list. The key of SparseArray is display ID. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ @NonNull public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() { Loading @@ -647,6 +678,8 @@ public final class UiAutomation { * Gets the root {@link AccessibilityNodeInfo} in the active window. * * @return The root info. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public AccessibilityNodeInfo getRootInActiveWindow() { final int connectionId; Loading @@ -664,14 +697,12 @@ public final class UiAutomation { * <p> * <strong>Note:</strong> It is caller's responsibility to recycle the event. * </p> * * @param event The event to inject. * @param sync Whether to inject the event synchronously. * @return Whether event injection succeeded. */ public boolean injectInputEvent(InputEvent event, boolean sync) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Injecting: " + event + " sync: " + sync); Loading @@ -692,9 +723,6 @@ public final class UiAutomation { */ @TestApi public void syncInputTransactions() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.syncInputTransactions(); Loading @@ -720,9 +748,6 @@ public final class UiAutomation { * @see #ROTATION_UNFREEZE */ public boolean setRotation(int rotation) { synchronized (mLock) { throwIfNotConnectedLocked(); } switch (rotation) { case ROTATION_FREEZE_0: case ROTATION_FREEZE_90: Loading Loading @@ -752,11 +777,14 @@ public final class UiAutomation { * <p> * <strong>Note:</strong> It is caller's responsibility to recycle the returned event. * </p> * * @param command The command to execute. * @param filter Filter that recognizes the expected event. * @param timeoutMillis The wait timeout in milliseconds. * * @throws TimeoutException If the expected event is not received within the timeout. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public AccessibilityEvent executeAndWaitForEvent(Runnable command, AccessibilityEventFilter filter, long timeoutMillis) throws TimeoutException { Loading Loading @@ -845,6 +873,8 @@ public final class UiAutomation { * * @throws TimeoutException If no idle state was detected within * <code>globalTimeoutMillis.</code> * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public void waitForIdle(long idleTimeoutMillis, long globalTimeoutMillis) throws TimeoutException { Loading Loading @@ -888,9 +918,6 @@ public final class UiAutomation { * @return The screenshot bitmap on success, null otherwise. */ public Bitmap takeScreenshot() { synchronized (mLock) { throwIfNotConnectedLocked(); } Display display = DisplayManagerGlobal.getInstance() .getRealDisplay(Display.DEFAULT_DISPLAY); Point displaySize = new Point(); Loading Loading @@ -927,9 +954,6 @@ public final class UiAutomation { * @see ActivityManager#isUserAMonkey() */ public void setRunAsMonkey(boolean enable) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { ActivityManager.getService().setUserIsMonkey(enable); } catch (RemoteException re) { Loading @@ -946,6 +970,8 @@ public final class UiAutomation { * @return Whether the window is present and its frame statistics * were cleared. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see android.view.WindowContentFrameStats * @see #getWindowContentFrameStats(int) * @see #getWindows() Loading Loading @@ -991,6 +1017,8 @@ public final class UiAutomation { * @param windowId The window id. * @return The window frame statistics, or null if the window is not present. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see android.view.WindowContentFrameStats * @see #clearWindowContentFrameStats(int) * @see #getWindows() Loading Loading @@ -1022,9 +1050,6 @@ public final class UiAutomation { * @see android.R.styleable#WindowAnimation */ public void clearWindowAnimationFrameStats() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Clearing window animation frame stats"); Loading Loading @@ -1064,9 +1089,6 @@ public final class UiAutomation { * @see android.R.styleable#WindowAnimation */ public WindowAnimationFrameStats getWindowAnimationFrameStats() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Getting window animation frame stats"); Loading @@ -1081,6 +1103,7 @@ public final class UiAutomation { /** * Grants a runtime permission to a package. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to grant the permission. Loading @@ -1104,15 +1127,13 @@ public final class UiAutomation { /** * Grants a runtime permission to a package for a user. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to grant the permission. */ public void grantRuntimePermissionAsUser(String packageName, String permission, UserHandle userHandle) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Granting runtime permission"); Loading @@ -1127,6 +1148,7 @@ public final class UiAutomation { /** * Revokes a runtime permission from a package. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to revoke the permission. Loading @@ -1150,15 +1172,13 @@ public final class UiAutomation { /** * Revokes a runtime permission from a package. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to revoke the permission. */ public void revokeRuntimePermissionAsUser(String packageName, String permission, UserHandle userHandle) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Revoking runtime permission"); Loading Loading @@ -1186,9 +1206,6 @@ public final class UiAutomation { * @see #adoptShellPermissionIdentity() */ public ParcelFileDescriptor executeShellCommand(String command) { synchronized (mLock) { throwIfNotConnectedLocked(); } warnIfBetterCommand(command); ParcelFileDescriptor source = null; Loading Loading @@ -1229,9 +1246,6 @@ public final class UiAutomation { */ @TestApi public ParcelFileDescriptor[] executeShellCommandRw(String command) { synchronized (mLock) { throwIfNotConnectedLocked(); } warnIfBetterCommand(command); ParcelFileDescriptor source_read = null; Loading Loading @@ -1276,15 +1290,21 @@ public final class UiAutomation { return stringBuilder.toString(); } @GuardedBy("mLock") private void throwIfConnectedLocked() { if (mConnectionState == ConnectionState.CONNECTED) { throw new IllegalStateException("UiAutomation connected, " + this); } } @GuardedBy("mLock") private void throwIfNotConnectedLocked() { if (mConnectionState != ConnectionState.CONNECTED) { throw new IllegalStateException("UiAutomation not connected, " + this); final String msg = useAccessibility() ? "UiAutomation not connected, " : "UiAutomation not connected: Accessibility-dependent method called with " + "FLAG_DONT_USE_ACCESSIBILITY set, "; throw new IllegalStateException(msg + this); } } Loading @@ -1298,11 +1318,16 @@ public final class UiAutomation { } } private boolean useAccessibility() { return (mFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0; } private class IAccessibilityServiceClientImpl extends IAccessibilityServiceClientWrapper { public IAccessibilityServiceClientImpl(Looper looper, int generationId) { super(null, looper, new Callbacks() { private final int mGenerationId = generationId; /** * True if UiAutomation doesn't interact with this client anymore. * Used by methods below to stop sending notifications or changing members Loading non-updatable-api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -6532,6 +6532,7 @@ package android.app { method public android.graphics.Bitmap takeScreenshot(); method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException; field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1 field public static final int FLAG_DONT_USE_ACCESSIBILITY = 2; // 0x2 field public static final int ROTATION_FREEZE_0 = 0; // 0x0 field public static final int ROTATION_FREEZE_180 = 2; // 0x2 field public static final int ROTATION_FREEZE_270 = 3; // 0x3 services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java +28 −15 Original line number Diff line number Diff line Loading @@ -72,7 +72,8 @@ class UiAutomationManager { }; /** * Register a UiAutomation. Only one may be registered at a time. * Register a UiAutomation if it uses the accessibility subsystem. Only one may be registered * at a time. * * @param owner A binder object owned by the process that owns the UiAutomation to be * registered. Loading @@ -80,6 +81,7 @@ class UiAutomationManager { * @param accessibilityServiceInfo The UiAutomation's service info * @param flags The UiAutomation's flags * @param id The id for the service connection * @see UiAutomation#FLAG_DONT_USE_ACCESSIBILITY */ void registerUiTestAutomationServiceLocked(IBinder owner, IAccessibilityServiceClient serviceClient, Loading @@ -88,13 +90,14 @@ class UiAutomationManager { AccessibilitySecurityPolicy securityPolicy, AbstractAccessibilityServiceConnection.SystemSupport systemSupport, WindowManagerInternal windowManagerInternal, SystemActionPerformer systemActionPerfomer, SystemActionPerformer systemActionPerformer, AccessibilityWindowManager awm, int flags) { synchronized (mLock) { accessibilityServiceInfo.setComponentName(COMPONENT_NAME); if (mUiAutomationService != null) { throw new IllegalStateException("UiAutomationService " + serviceClient throw new IllegalStateException( "UiAutomationService " + mUiAutomationService.mServiceInterface + "already registered!"); } Loading @@ -106,12 +109,17 @@ class UiAutomationManager { return; } mUiAutomationFlags = flags; mSystemSupport = systemSupport; // Ignore registering UiAutomation if it is not allowed to use the accessibility // subsystem. if (!useAccessibility()) { return; } mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id, mainHandler, mLock, securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer, awm); systemActionPerformer, awm); mUiAutomationServiceOwner = owner; mUiAutomationFlags = flags; mUiAutomationServiceInfo = accessibilityServiceInfo; mUiAutomationService.mServiceInterface = serviceClient; mUiAutomationService.onAdded(); Loading @@ -130,15 +138,15 @@ class UiAutomationManager { void unregisterUiTestAutomationServiceLocked(IAccessibilityServiceClient serviceClient) { synchronized (mLock) { if ((mUiAutomationService == null) if (useAccessibility() && ((mUiAutomationService == null) || (serviceClient == null) || (mUiAutomationService.mServiceInterface == null) || (serviceClient.asBinder() != mUiAutomationService.mServiceInterface.asBinder())) { != mUiAutomationService.mServiceInterface.asBinder()))) { throw new IllegalStateException("UiAutomationService " + serviceClient + " not registered!"); } destroyUiAutomationService(); } } Loading @@ -150,14 +158,19 @@ class UiAutomationManager { } boolean isUiAutomationRunningLocked() { return (mUiAutomationService != null); return (mUiAutomationService != null || !useAccessibility()); } boolean suppressingAccessibilityServicesLocked() { return (mUiAutomationService != null) && ((mUiAutomationFlags return (mUiAutomationService != null || !useAccessibility()) && ((mUiAutomationFlags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0); } boolean useAccessibility() { return ((mUiAutomationFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0); } boolean isTouchExplorationEnabledLocked() { return (mUiAutomationService != null) && mUiAutomationService.mRequestTouchExplorationMode; Loading Loading @@ -209,14 +222,14 @@ class UiAutomationManager { mUiAutomationService.onRemoved(); mUiAutomationService.resetLocked(); mUiAutomationService = null; mUiAutomationFlags = 0; if (mUiAutomationServiceOwner != null) { mUiAutomationServiceOwner.unlinkToDeath( mUiAutomationServiceOwnerDeathRecipient, 0); mUiAutomationServiceOwner = null; } mSystemSupport.onClientChangeLocked(false); } mUiAutomationFlags = 0; mSystemSupport.onClientChangeLocked(false); } } Loading @@ -227,9 +240,9 @@ class UiAutomationManager { int id, Handler mainHandler, Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, WindowManagerInternal windowManagerInternal, SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager awm) { SystemActionPerformer systemActionPerformer, AccessibilityWindowManager awm) { super(context, COMPONENT_NAME, accessibilityServiceInfo, id, mainHandler, lock, securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer, securityPolicy, systemSupport, windowManagerInternal, systemActionPerformer, awm); mMainHandler = mainHandler; } Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -6532,6 +6532,7 @@ package android.app { method public android.graphics.Bitmap takeScreenshot(); method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException; field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1 field public static final int FLAG_DONT_USE_ACCESSIBILITY = 2; // 0x2 field public static final int ROTATION_FREEZE_0 = 0; // 0x0 field public static final int ROTATION_FREEZE_180 = 2; // 0x2 field public static final int ROTATION_FREEZE_270 = 3; // 0x3
core/java/android/app/Instrumentation.java +4 −2 Original line number Diff line number Diff line Loading @@ -97,7 +97,8 @@ public class Instrumentation { * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}) @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES, UiAutomation.FLAG_DONT_USE_ACCESSIBILITY}) public @interface UiAutomationFlags {}; Loading Loading @@ -2170,7 +2171,8 @@ public class Instrumentation { * </p> * * @param flags The flags to be passed to the UiAutomation, for example * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}. * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}, * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY}. * * @return The UI automation instance. * Loading
core/java/android/app/UiAutomation.java +77 −52 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.IAccessibilityInteractionConnection; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.pooled.PooledLambda; import libcore.io.IoUtils; Loading Loading @@ -142,13 +143,22 @@ public final class UiAutomation { } /** * UiAutomation supresses accessibility services by default. This flag specifies that * UiAutomation suppresses accessibility services by default. This flag specifies that * existing accessibility services should continue to run, and that new ones may start. * This flag is set when obtaining the UiAutomation from * {@link Instrumentation#getUiAutomation(int)}. */ public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 0x00000001; /** * UiAutomation uses the accessibility subsystem by default. This flag provides an option to * eliminate the overhead of engaging the accessibility subsystem for tests that do not need to * interact with the user interface. Setting this flag disables methods that rely on * accessibility. This flag is set when obtaining the UiAutomation from * {@link Instrumentation#getUiAutomation(int)}. */ public static final int FLAG_DONT_USE_ACCESSIBILITY = 0x00000002; private final Object mLock = new Object(); private final ArrayList<AccessibilityEvent> mEventQueue = new ArrayList<AccessibilityEvent>(); Loading Loading @@ -267,11 +277,14 @@ public final class UiAutomation { /** * Connects this UiAutomation to the accessibility introspection APIs. * * @param flags Any flags to apply to the automation as it gets connected * @param flags Any flags to apply to the automation as it gets connected while * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY} would keep the * connection disconnected and not to register UiAutomation service. * @param timeoutMillis The wait timeout in milliseconds * * @throws IllegalStateException If the connection to the accessibility subsystem is already * established. * @throws TimeoutException If not connected within the timeout * * @hide */ public void connectWithTimeout(int flags, long timeoutMillis) throws TimeoutException { Loading @@ -292,6 +305,12 @@ public final class UiAutomation { // Calling out without a lock held. mUiAutomationConnection.connect(mClient, flags); mFlags = flags; // If UiAutomation is not allowed to use the accessibility subsystem, the // connection state should keep disconnected and not to start the client connection. if (!useAccessibility()) { mConnectionState = ConnectionState.DISCONNECTED; return; } } catch (RemoteException re) { throw new RuntimeException("Error while connecting " + this, re); } Loading Loading @@ -340,7 +359,7 @@ public final class UiAutomation { throw new IllegalStateException( "Cannot call disconnect() while connecting " + this); } if (mConnectionState == ConnectionState.DISCONNECTED) { if (useAccessibility() && mConnectionState == ConnectionState.DISCONNECTED) { return; } mConnectionState = ConnectionState.DISCONNECTED; Loading @@ -354,10 +373,12 @@ public final class UiAutomation { } catch (RemoteException re) { throw new RuntimeException("Error while disconnecting " + this, re); } finally { if (mRemoteCallbackThread != null) { mRemoteCallbackThread.quit(); mRemoteCallbackThread = null; } } } /** * The id of the {@link IAccessibilityInteractionConnection} for querying Loading Loading @@ -389,9 +410,13 @@ public final class UiAutomation { * The callbacks are delivered on the main application thread. * * @param listener The callback. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public void setOnAccessibilityEventListener(OnAccessibilityEventListener listener) { synchronized (mLock) { throwIfNotConnectedLocked(); mOnAccessibilityEventListener = listener; } } Loading Loading @@ -423,9 +448,6 @@ public final class UiAutomation { * @see #dropShellPermissionIdentity() */ public void adoptShellPermissionIdentity() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), null); Loading @@ -451,9 +473,6 @@ public final class UiAutomation { * @see #dropShellPermissionIdentity() */ public void adoptShellPermissionIdentity(@Nullable String... permissions) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), permissions); Loading @@ -470,9 +489,6 @@ public final class UiAutomation { * @see #adoptShellPermissionIdentity() */ public void dropShellPermissionIdentity() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.dropShellPermissionIdentity(); Loading @@ -489,6 +505,8 @@ public final class UiAutomation { * @param action The action to perform. * @return Whether the action was successfully performed. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_HOME * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS Loading Loading @@ -526,10 +544,15 @@ public final class UiAutomation { * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. * @return The node info of the focused view or null. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see AccessibilityNodeInfo#FOCUS_INPUT * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY */ public AccessibilityNodeInfo findFocus(int focus) { synchronized (mLock) { throwIfNotConnectedLocked(); } return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus); } Loading @@ -541,6 +564,8 @@ public final class UiAutomation { * * @return The accessibility service info. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see AccessibilityServiceInfo */ public final AccessibilityServiceInfo getServiceInfo() { Loading @@ -567,6 +592,8 @@ public final class UiAutomation { * * @param info The info. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see AccessibilityServiceInfo */ public final void setServiceInfo(AccessibilityServiceInfo info) { Loading Loading @@ -602,6 +629,8 @@ public final class UiAutomation { * </p> * * @return The windows if there are windows such, otherwise an empty list. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public List<AccessibilityWindowInfo> getWindows() { final int connectionId; Loading Loading @@ -630,6 +659,8 @@ public final class UiAutomation { * * @return The windows of all displays if there are windows and the service is can retrieve * them, otherwise an empty list. The key of SparseArray is display ID. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ @NonNull public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() { Loading @@ -647,6 +678,8 @@ public final class UiAutomation { * Gets the root {@link AccessibilityNodeInfo} in the active window. * * @return The root info. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public AccessibilityNodeInfo getRootInActiveWindow() { final int connectionId; Loading @@ -664,14 +697,12 @@ public final class UiAutomation { * <p> * <strong>Note:</strong> It is caller's responsibility to recycle the event. * </p> * * @param event The event to inject. * @param sync Whether to inject the event synchronously. * @return Whether event injection succeeded. */ public boolean injectInputEvent(InputEvent event, boolean sync) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Injecting: " + event + " sync: " + sync); Loading @@ -692,9 +723,6 @@ public final class UiAutomation { */ @TestApi public void syncInputTransactions() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { // Calling out without a lock held. mUiAutomationConnection.syncInputTransactions(); Loading @@ -720,9 +748,6 @@ public final class UiAutomation { * @see #ROTATION_UNFREEZE */ public boolean setRotation(int rotation) { synchronized (mLock) { throwIfNotConnectedLocked(); } switch (rotation) { case ROTATION_FREEZE_0: case ROTATION_FREEZE_90: Loading Loading @@ -752,11 +777,14 @@ public final class UiAutomation { * <p> * <strong>Note:</strong> It is caller's responsibility to recycle the returned event. * </p> * * @param command The command to execute. * @param filter Filter that recognizes the expected event. * @param timeoutMillis The wait timeout in milliseconds. * * @throws TimeoutException If the expected event is not received within the timeout. * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public AccessibilityEvent executeAndWaitForEvent(Runnable command, AccessibilityEventFilter filter, long timeoutMillis) throws TimeoutException { Loading Loading @@ -845,6 +873,8 @@ public final class UiAutomation { * * @throws TimeoutException If no idle state was detected within * <code>globalTimeoutMillis.</code> * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. */ public void waitForIdle(long idleTimeoutMillis, long globalTimeoutMillis) throws TimeoutException { Loading Loading @@ -888,9 +918,6 @@ public final class UiAutomation { * @return The screenshot bitmap on success, null otherwise. */ public Bitmap takeScreenshot() { synchronized (mLock) { throwIfNotConnectedLocked(); } Display display = DisplayManagerGlobal.getInstance() .getRealDisplay(Display.DEFAULT_DISPLAY); Point displaySize = new Point(); Loading Loading @@ -927,9 +954,6 @@ public final class UiAutomation { * @see ActivityManager#isUserAMonkey() */ public void setRunAsMonkey(boolean enable) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { ActivityManager.getService().setUserIsMonkey(enable); } catch (RemoteException re) { Loading @@ -946,6 +970,8 @@ public final class UiAutomation { * @return Whether the window is present and its frame statistics * were cleared. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see android.view.WindowContentFrameStats * @see #getWindowContentFrameStats(int) * @see #getWindows() Loading Loading @@ -991,6 +1017,8 @@ public final class UiAutomation { * @param windowId The window id. * @return The window frame statistics, or null if the window is not present. * * @throws IllegalStateException If the connection to the accessibility subsystem is not * established. * @see android.view.WindowContentFrameStats * @see #clearWindowContentFrameStats(int) * @see #getWindows() Loading Loading @@ -1022,9 +1050,6 @@ public final class UiAutomation { * @see android.R.styleable#WindowAnimation */ public void clearWindowAnimationFrameStats() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Clearing window animation frame stats"); Loading Loading @@ -1064,9 +1089,6 @@ public final class UiAutomation { * @see android.R.styleable#WindowAnimation */ public WindowAnimationFrameStats getWindowAnimationFrameStats() { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Getting window animation frame stats"); Loading @@ -1081,6 +1103,7 @@ public final class UiAutomation { /** * Grants a runtime permission to a package. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to grant the permission. Loading @@ -1104,15 +1127,13 @@ public final class UiAutomation { /** * Grants a runtime permission to a package for a user. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to grant the permission. */ public void grantRuntimePermissionAsUser(String packageName, String permission, UserHandle userHandle) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Granting runtime permission"); Loading @@ -1127,6 +1148,7 @@ public final class UiAutomation { /** * Revokes a runtime permission from a package. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to revoke the permission. Loading @@ -1150,15 +1172,13 @@ public final class UiAutomation { /** * Revokes a runtime permission from a package. * * @param packageName The package to which to grant. * @param permission The permission to grant. * @throws SecurityException if unable to revoke the permission. */ public void revokeRuntimePermissionAsUser(String packageName, String permission, UserHandle userHandle) { synchronized (mLock) { throwIfNotConnectedLocked(); } try { if (DEBUG) { Log.i(LOG_TAG, "Revoking runtime permission"); Loading Loading @@ -1186,9 +1206,6 @@ public final class UiAutomation { * @see #adoptShellPermissionIdentity() */ public ParcelFileDescriptor executeShellCommand(String command) { synchronized (mLock) { throwIfNotConnectedLocked(); } warnIfBetterCommand(command); ParcelFileDescriptor source = null; Loading Loading @@ -1229,9 +1246,6 @@ public final class UiAutomation { */ @TestApi public ParcelFileDescriptor[] executeShellCommandRw(String command) { synchronized (mLock) { throwIfNotConnectedLocked(); } warnIfBetterCommand(command); ParcelFileDescriptor source_read = null; Loading Loading @@ -1276,15 +1290,21 @@ public final class UiAutomation { return stringBuilder.toString(); } @GuardedBy("mLock") private void throwIfConnectedLocked() { if (mConnectionState == ConnectionState.CONNECTED) { throw new IllegalStateException("UiAutomation connected, " + this); } } @GuardedBy("mLock") private void throwIfNotConnectedLocked() { if (mConnectionState != ConnectionState.CONNECTED) { throw new IllegalStateException("UiAutomation not connected, " + this); final String msg = useAccessibility() ? "UiAutomation not connected, " : "UiAutomation not connected: Accessibility-dependent method called with " + "FLAG_DONT_USE_ACCESSIBILITY set, "; throw new IllegalStateException(msg + this); } } Loading @@ -1298,11 +1318,16 @@ public final class UiAutomation { } } private boolean useAccessibility() { return (mFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0; } private class IAccessibilityServiceClientImpl extends IAccessibilityServiceClientWrapper { public IAccessibilityServiceClientImpl(Looper looper, int generationId) { super(null, looper, new Callbacks() { private final int mGenerationId = generationId; /** * True if UiAutomation doesn't interact with this client anymore. * Used by methods below to stop sending notifications or changing members Loading
non-updatable-api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -6532,6 +6532,7 @@ package android.app { method public android.graphics.Bitmap takeScreenshot(); method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException; field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1 field public static final int FLAG_DONT_USE_ACCESSIBILITY = 2; // 0x2 field public static final int ROTATION_FREEZE_0 = 0; // 0x0 field public static final int ROTATION_FREEZE_180 = 2; // 0x2 field public static final int ROTATION_FREEZE_270 = 3; // 0x3
services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java +28 −15 Original line number Diff line number Diff line Loading @@ -72,7 +72,8 @@ class UiAutomationManager { }; /** * Register a UiAutomation. Only one may be registered at a time. * Register a UiAutomation if it uses the accessibility subsystem. Only one may be registered * at a time. * * @param owner A binder object owned by the process that owns the UiAutomation to be * registered. Loading @@ -80,6 +81,7 @@ class UiAutomationManager { * @param accessibilityServiceInfo The UiAutomation's service info * @param flags The UiAutomation's flags * @param id The id for the service connection * @see UiAutomation#FLAG_DONT_USE_ACCESSIBILITY */ void registerUiTestAutomationServiceLocked(IBinder owner, IAccessibilityServiceClient serviceClient, Loading @@ -88,13 +90,14 @@ class UiAutomationManager { AccessibilitySecurityPolicy securityPolicy, AbstractAccessibilityServiceConnection.SystemSupport systemSupport, WindowManagerInternal windowManagerInternal, SystemActionPerformer systemActionPerfomer, SystemActionPerformer systemActionPerformer, AccessibilityWindowManager awm, int flags) { synchronized (mLock) { accessibilityServiceInfo.setComponentName(COMPONENT_NAME); if (mUiAutomationService != null) { throw new IllegalStateException("UiAutomationService " + serviceClient throw new IllegalStateException( "UiAutomationService " + mUiAutomationService.mServiceInterface + "already registered!"); } Loading @@ -106,12 +109,17 @@ class UiAutomationManager { return; } mUiAutomationFlags = flags; mSystemSupport = systemSupport; // Ignore registering UiAutomation if it is not allowed to use the accessibility // subsystem. if (!useAccessibility()) { return; } mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id, mainHandler, mLock, securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer, awm); systemActionPerformer, awm); mUiAutomationServiceOwner = owner; mUiAutomationFlags = flags; mUiAutomationServiceInfo = accessibilityServiceInfo; mUiAutomationService.mServiceInterface = serviceClient; mUiAutomationService.onAdded(); Loading @@ -130,15 +138,15 @@ class UiAutomationManager { void unregisterUiTestAutomationServiceLocked(IAccessibilityServiceClient serviceClient) { synchronized (mLock) { if ((mUiAutomationService == null) if (useAccessibility() && ((mUiAutomationService == null) || (serviceClient == null) || (mUiAutomationService.mServiceInterface == null) || (serviceClient.asBinder() != mUiAutomationService.mServiceInterface.asBinder())) { != mUiAutomationService.mServiceInterface.asBinder()))) { throw new IllegalStateException("UiAutomationService " + serviceClient + " not registered!"); } destroyUiAutomationService(); } } Loading @@ -150,14 +158,19 @@ class UiAutomationManager { } boolean isUiAutomationRunningLocked() { return (mUiAutomationService != null); return (mUiAutomationService != null || !useAccessibility()); } boolean suppressingAccessibilityServicesLocked() { return (mUiAutomationService != null) && ((mUiAutomationFlags return (mUiAutomationService != null || !useAccessibility()) && ((mUiAutomationFlags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0); } boolean useAccessibility() { return ((mUiAutomationFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0); } boolean isTouchExplorationEnabledLocked() { return (mUiAutomationService != null) && mUiAutomationService.mRequestTouchExplorationMode; Loading Loading @@ -209,14 +222,14 @@ class UiAutomationManager { mUiAutomationService.onRemoved(); mUiAutomationService.resetLocked(); mUiAutomationService = null; mUiAutomationFlags = 0; if (mUiAutomationServiceOwner != null) { mUiAutomationServiceOwner.unlinkToDeath( mUiAutomationServiceOwnerDeathRecipient, 0); mUiAutomationServiceOwner = null; } mSystemSupport.onClientChangeLocked(false); } mUiAutomationFlags = 0; mSystemSupport.onClientChangeLocked(false); } } Loading @@ -227,9 +240,9 @@ class UiAutomationManager { int id, Handler mainHandler, Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, WindowManagerInternal windowManagerInternal, SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager awm) { SystemActionPerformer systemActionPerformer, AccessibilityWindowManager awm) { super(context, COMPONENT_NAME, accessibilityServiceInfo, id, mainHandler, lock, securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer, securityPolicy, systemSupport, windowManagerInternal, systemActionPerformer, awm); mMainHandler = mainHandler; } Loading