From 40c9baad6bd810358ff17ab63e9f29707951b74d Mon Sep 17 00:00:00 2001
From: mincheli
* Note: It is caller's responsibility to recycle the event. *
+ * * @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); @@ -692,9 +723,6 @@ public final class UiAutomation { */ @TestApi public void syncInputTransactions() { - synchronized (mLock) { - throwIfNotConnectedLocked(); - } try { // Calling out without a lock held. mUiAutomationConnection.syncInputTransactions(); @@ -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: @@ -752,11 +777,14 @@ public final class UiAutomation { ** Note: It is caller's responsibility to recycle the returned event. *
+ * * @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 { @@ -845,6 +873,8 @@ public final class UiAutomation { * * @throws TimeoutException If no idle state was detected within *globalTimeoutMillis.
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
public void waitForIdle(long idleTimeoutMillis, long globalTimeoutMillis)
throws TimeoutException {
@@ -874,9 +904,9 @@ public final class UiAutomation {
return;
}
try {
- mLock.wait(remainingIdleTimeMillis);
+ mLock.wait(remainingIdleTimeMillis);
} catch (InterruptedException ie) {
- /* ignore */
+ /* ignore */
}
}
}
@@ -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();
@@ -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) {
@@ -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()
@@ -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()
@@ -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");
@@ -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");
@@ -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.
@@ -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");
@@ -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.
@@ -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");
@@ -1186,9 +1206,6 @@ public final class UiAutomation {
* @see #adoptShellPermissionIdentity()
*/
public ParcelFileDescriptor executeShellCommand(String command) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
warnIfBetterCommand(command);
ParcelFileDescriptor source = null;
@@ -1229,9 +1246,6 @@ public final class UiAutomation {
*/
@TestApi
public ParcelFileDescriptor[] executeShellCommandRw(String command) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
warnIfBetterCommand(command);
ParcelFileDescriptor source_read = null;
@@ -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);
}
}
@@ -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
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index bb40e24a68acc..a868c718447d3 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -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
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 3d6a12884ec64..4473754e2b680 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -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.
@@ -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,
@@ -88,14 +90,15 @@ 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
- + "already registered!");
+ throw new IllegalStateException(
+ "UiAutomationService " + mUiAutomationService.mServiceInterface
+ + "already registered!");
}
try {
@@ -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();
@@ -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();
}
}
@@ -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;
@@ -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);
}
}
@@ -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;
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
index c8baca610bdc1..8062bfec3703a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -170,6 +170,30 @@ public class UiAutomationManagerTest {
verify(mMockSystemSupport).onClientChangeLocked(false);
}
+ @Test
+ public void uiAutomationWithDontUseAccessibilityFlagAfterUnregistering_notifiesSystem()
+ throws Exception {
+ register(UiAutomation.FLAG_DONT_USE_ACCESSIBILITY);
+ unregister();
+ verify(mMockSystemSupport).onClientChangeLocked(false);
+ }
+
+ @Test
+ public void uiAutomationWithDontUseAccessibilityFlag_disableAccessibilityFunctions()
+ throws Exception {
+ register(0);
+ assertTrue(mUiAutomationManager.isUiAutomationRunningLocked());
+ unregister();
+ assertFalse(mUiAutomationManager.isUiAutomationRunningLocked());
+ register(UiAutomation.FLAG_DONT_USE_ACCESSIBILITY);
+ assertTrue(mUiAutomationManager.isUiAutomationRunningLocked());
+ assertFalse(mUiAutomationManager.useAccessibility());
+ assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked());
+ assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked());
+ assertEquals(0, mUiAutomationManager.getRelevantEventTypes());
+ assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked());
+ }
+
private void register(int flags) {
mUiAutomationManager.registerUiTestAutomationServiceLocked(mMockOwner,
mMockAccessibilityServiceClient, mMockContext, mMockServiceInfo, SERVICE_ID,