UiAutomation supports new flag, FLAG_DO_NOT_USE_ACCESSIBILITY
UiAutomation should have an option not to engage accessibility. go/uiautomation_not_use_a11y Bug: 93087044 Test: atest UiAutomationManagerTest, atest CtsUiAutomationTestCases Change-Id: Icc6c359844817a07869a18345fe44ef3b2813dae
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
@@ -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>();
|
||||
@@ -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 {
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -354,8 +373,10 @@ public final class UiAutomation {
|
||||
} catch (RemoteException re) {
|
||||
throw new RuntimeException("Error while disconnecting " + this, re);
|
||||
} finally {
|
||||
mRemoteCallbackThread.quit();
|
||||
mRemoteCallbackThread = null;
|
||||
if (mRemoteCallbackThread != null) {
|
||||
mRemoteCallbackThread.quit();
|
||||
mRemoteCallbackThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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
|
||||
@@ -523,13 +541,18 @@ public final class UiAutomation {
|
||||
* </p>
|
||||
*
|
||||
* @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
|
||||
* {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
|
||||
* {@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);
|
||||
}
|
||||
@@ -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() {
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
@@ -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() {
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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 {
|
||||
* <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 {
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user