summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author sallyyuen <sallyyuen@google.com> 2021-11-15 12:35:36 -0800
committer sallyyuen <sallyyuen@google.com> 2021-11-22 15:54:41 -0800
commit85cfe63e23394b872bfcd354e4a043da3b86bf90 (patch)
tree8fa3672a00f8a00b7557e65feeddd10c807ebfa3
parent85b0025008ca48a5585f9ebdd001e8c5626b43bc (diff)
Refactor A11yInteractionClient so every service has its own cache
- Maintain a static collection of caches (sCaches). Lock is sConnectionCache - Initialize a cache when a connection is added. (client.addConnection) - Remove the cache when a connection is removed. (client.removeConnection) - System server should not have its cache initialized, can remove parameter in AccessibiltyInteractionClient constructor I tried to maintain a local reference (mAccessibilityCache) to the service cache for each client to avoid accessing the static collection for each request. But since the process is not immediately killed when the service is turned off, ensuring resources are cleared correctly is big time investment that can be done later if desired. Bug: 192489177 Test: Build and use talkback, do the slew of tests. atest CtsAccessibilityServiceTestCases CtsAccessibilityTestCases CtsUiAutomationTestCases FrameworksServicesTests:com.android.server.accessibility FrameworksCoreTests:com.android.internal.accessibility FrameworksCoreTests:android.view.accessibiliity Change-Id: Ic30f6915c7b3c186a512ed8b410bf6e842eff5fb
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java11
-rw-r--r--core/java/android/app/UiAutomation.java2
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java3
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java231
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java8
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java46
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java5
7 files changed, 186 insertions, 120 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 0f852b404440..09af72d6cc12 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2071,7 +2071,7 @@ public abstract class AccessibilityService extends Service {
try {
connection.setServiceInfo(mInfo);
mInfo = null;
- AccessibilityInteractionClient.getInstance(this).clearCache();
+ AccessibilityInteractionClient.getInstance(this).clearCache(mConnectionId);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
re.rethrowFromSystemServer();
@@ -2421,7 +2421,7 @@ public abstract class AccessibilityService extends Service {
if (event != null) {
// Send the event to AccessibilityCache via AccessibilityInteractionClient
AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
- event);
+ event, mConnectionId);
if (serviceWantsEvent
&& (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
// Send the event to AccessibilityService
@@ -2451,7 +2451,7 @@ public abstract class AccessibilityService extends Service {
args.recycle();
if (connection != null) {
AccessibilityInteractionClient.getInstance(mContext).addConnection(
- mConnectionId, connection);
+ mConnectionId, connection, /*initializeCache=*/true);
if (mContext != null) {
try {
connection.setAttributionTag(mContext.getAttributionTag());
@@ -2466,7 +2466,8 @@ public abstract class AccessibilityService extends Service {
AccessibilityInteractionClient.getInstance(mContext).removeConnection(
mConnectionId);
mConnectionId = AccessibilityInteractionClient.NO_ID;
- AccessibilityInteractionClient.getInstance(mContext).clearCache();
+ AccessibilityInteractionClient.getInstance(mContext)
+ .clearCache(mConnectionId);
mCallback.init(AccessibilityInteractionClient.NO_ID, null);
}
return;
@@ -2478,7 +2479,7 @@ public abstract class AccessibilityService extends Service {
return;
}
case DO_CLEAR_ACCESSIBILITY_CACHE: {
- AccessibilityInteractionClient.getInstance(mContext).clearCache();
+ AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
return;
}
case DO_ON_KEY_EVENT: {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 828b17156536..58ded716cf40 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -638,7 +638,7 @@ public final class UiAutomation {
final IAccessibilityServiceConnection connection;
synchronized (mLock) {
throwIfNotConnectedLocked();
- AccessibilityInteractionClient.getInstance().clearCache();
+ AccessibilityInteractionClient.getInstance().clearCache(mConnectionId);
connection = AccessibilityInteractionClient.getInstance()
.getConnection(mConnectionId);
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 9cd83135821b..de56d3ad7502 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -151,8 +151,7 @@ public final class AccessibilityInteractionController {
if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId
&& mHandler.hasAccessibilityCallback(message)) {
AccessibilityInteractionClient.getInstanceForThread(
- interrogatingTid, /* initializeCache= */true)
- .setSameThreadMessage(message);
+ interrogatingTid).setSameThreadMessage(message);
} else {
// For messages without callback of interrogating client, just handle the
// message immediately if this is UI thread.
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index bc2148840187..dc4c59a1e1ec 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -115,13 +115,13 @@ public final class AccessibilityInteractionClient
from a window, mapping from windowId -> timestamp. */
private static final SparseLongArray sScrollingWindows = new SparseLongArray();
- private static AccessibilityCache sAccessibilityCache;
+ private static SparseArray<AccessibilityCache> sCaches = new SparseArray<>();
private final AtomicInteger mInteractionIdCounter = new AtomicInteger();
private final Object mInstanceLock = new Object();
- private final AccessibilityManager mAccessibilityManager;
+ private final AccessibilityManager mAccessibilityManager;
private volatile int mInteractionId = -1;
private volatile int mCallingUid = Process.INVALID_UID;
@@ -150,7 +150,7 @@ public final class AccessibilityInteractionClient
@UnsupportedAppUsage()
public static AccessibilityInteractionClient getInstance() {
final long threadId = Thread.currentThread().getId();
- return getInstanceForThread(threadId, true);
+ return getInstanceForThread(threadId);
}
/**
@@ -161,17 +161,11 @@ public final class AccessibilityInteractionClient
*
* @return The client for a given <code>threadId</code>.
*/
- public static AccessibilityInteractionClient getInstanceForThread(long threadId,
- boolean initializeCache) {
+ public static AccessibilityInteractionClient getInstanceForThread(long threadId) {
synchronized (sStaticLock) {
AccessibilityInteractionClient client = sClients.get(threadId);
if (client == null) {
- if (Binder.getCallingUid() == Process.SYSTEM_UID) {
- // Don't initialize a cache for the system process
- client = new AccessibilityInteractionClient(false);
- } else {
- client = new AccessibilityInteractionClient(initializeCache);
- }
+ client = new AccessibilityInteractionClient();
sClients.put(threadId, client);
}
return client;
@@ -182,20 +176,11 @@ public final class AccessibilityInteractionClient
* @return The client for the current thread.
*/
public static AccessibilityInteractionClient getInstance(Context context) {
- return getInstance(/* initializeCache= */true, context);
- }
-
- /**
- * @param initializeCache whether to initialize the cache in a new client instance
- * @return The client for the current thread.
- */
- public static AccessibilityInteractionClient getInstance(boolean initializeCache,
- Context context) {
final long threadId = Thread.currentThread().getId();
if (context != null) {
- return getInstanceForThread(threadId, initializeCache, context);
+ return getInstanceForThread(threadId, context);
}
- return getInstanceForThread(threadId, initializeCache);
+ return getInstanceForThread(threadId);
}
/**
@@ -204,19 +189,14 @@ public final class AccessibilityInteractionClient
* We do not have a thread local variable since other threads should be able to
* look up the correct client knowing a thread id. See ViewRootImpl for details.
*
- * @param initializeCache whether to initialize the cache in a new client instance
* @return The client for a given <code>threadId</code>.
*/
- public static AccessibilityInteractionClient getInstanceForThread(
- long threadId, boolean initializeCache, Context context) {
+ public static AccessibilityInteractionClient getInstanceForThread(long threadId,
+ Context context) {
synchronized (sStaticLock) {
AccessibilityInteractionClient client = sClients.get(threadId);
if (client == null) {
- if (Binder.getCallingUid() == Process.SYSTEM_UID) {
- client = new AccessibilityInteractionClient(false, context);
- } else {
- client = new AccessibilityInteractionClient(initializeCache, context);
- }
+ client = new AccessibilityInteractionClient(context);
sClients.put(threadId, client);
}
return client;
@@ -238,12 +218,30 @@ public final class AccessibilityInteractionClient
/**
* Adds a cached accessibility service connection.
*
+ * Adds a cache if {@code initializeCache} is true
* @param connectionId The connection id.
* @param connection The connection.
+ * @param initializeCache whether to initialize a cache
*/
- public static void addConnection(int connectionId, IAccessibilityServiceConnection connection) {
+ public static void addConnection(int connectionId, IAccessibilityServiceConnection connection,
+ boolean initializeCache) {
synchronized (sConnectionCache) {
sConnectionCache.put(connectionId, connection);
+ if (!initializeCache) {
+ return;
+ }
+ sCaches.put(connectionId, new AccessibilityCache(
+ new AccessibilityCache.AccessibilityNodeRefresher()));
+ }
+ }
+
+ /**
+ * Gets a cached associated with the connection id if available.
+ *
+ */
+ public static AccessibilityCache getCache(int connectionId) {
+ synchronized (sConnectionCache) {
+ return sCaches.get(connectionId);
}
}
@@ -255,6 +253,7 @@ public final class AccessibilityInteractionClient
public static void removeConnection(int connectionId) {
synchronized (sConnectionCache) {
sConnectionCache.remove(connectionId);
+ sCaches.remove(connectionId);
}
}
@@ -263,32 +262,21 @@ public final class AccessibilityInteractionClient
* tests need to be able to verify this class's interactions with the cache
*/
@VisibleForTesting
- public static void setCache(AccessibilityCache cache) {
- sAccessibilityCache = cache;
+ public static void setCache(int connectionId, AccessibilityCache cache) {
+ synchronized (sConnectionCache) {
+ sCaches.put(connectionId, cache);
+ }
}
private AccessibilityInteractionClient() {
/* reducing constructor visibility */
- this(true);
- }
-
- private AccessibilityInteractionClient(boolean initializeCache) {
- initializeCache(initializeCache);
mAccessibilityManager = null;
}
- private AccessibilityInteractionClient(boolean initializeCache, Context context) {
- initializeCache(initializeCache);
+ private AccessibilityInteractionClient(Context context) {
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
}
- private static void initializeCache(boolean initialize) {
- if (initialize && sAccessibilityCache == null) {
- sAccessibilityCache = new AccessibilityCache(
- new AccessibilityCache.AccessibilityNodeRefresher());
- }
- }
-
/**
* Sets the message to be processed if the interacted view hierarchy
* and the interacting client are running in the same thread.
@@ -333,7 +321,7 @@ public final class AccessibilityInteractionClient
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
+ * {@link AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param bypassCache Whether to bypass the cache.
* @return The {@link AccessibilityWindowInfo}.
@@ -344,21 +332,28 @@ public final class AccessibilityInteractionClient
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
AccessibilityWindowInfo window;
- if (!bypassCache && sAccessibilityCache != null) {
- window = sAccessibilityCache.getWindow(accessibilityWindowId);
- if (window != null) {
- if (DEBUG) {
- Log.i(LOG_TAG, "Window cache hit");
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache != null) {
+ if (!bypassCache) {
+ window = cache.getWindow(accessibilityWindowId);
+ if (window != null) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Window cache hit");
+ }
+ if (shouldTraceClient()) {
+ logTraceClient(connection, "getWindow cache",
+ "connectionId=" + connectionId + ";accessibilityWindowId="
+ + accessibilityWindowId + ";bypassCache=false");
+ }
+ return window;
}
- if (shouldTraceClient()) {
- logTraceClient(connection, "getWindow cache",
- "connectionId=" + connectionId + ";accessibilityWindowId="
- + accessibilityWindowId + ";bypassCache=false");
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Window cache miss");
}
- return window;
}
+ } else {
if (DEBUG) {
- Log.i(LOG_TAG, "Window cache miss");
+ Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
}
}
@@ -374,9 +369,9 @@ public final class AccessibilityInteractionClient
+ bypassCache);
}
- if (window != null && sAccessibilityCache != null) {
- if (!bypassCache) {
- sAccessibilityCache.addWindow(window);
+ if (window != null) {
+ if (!bypassCache && cache != null) {
+ cache.addWindow(window);
}
return window;
}
@@ -418,8 +413,9 @@ public final class AccessibilityInteractionClient
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
SparseArray<List<AccessibilityWindowInfo>> windows;
- if (sAccessibilityCache != null) {
- windows = sAccessibilityCache.getWindowsOnAllDisplays();
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache != null) {
+ windows = cache.getWindowsOnAllDisplays();
if (windows != null) {
if (DEBUG) {
Log.i(LOG_TAG, "Windows cache hit");
@@ -433,6 +429,10 @@ public final class AccessibilityInteractionClient
if (DEBUG) {
Log.i(LOG_TAG, "Windows cache miss");
}
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+ }
}
long populationTimeStamp;
@@ -447,8 +447,8 @@ public final class AccessibilityInteractionClient
logTraceClient(connection, "getWindows", "connectionId=" + connectionId);
}
if (windows != null) {
- if (sAccessibilityCache != null) {
- sAccessibilityCache.setWindowsOnAllDisplays(windows, populationTimeStamp);
+ if (cache != null) {
+ cache.setWindowsOnAllDisplays(windows, populationTimeStamp);
}
return windows;
}
@@ -533,28 +533,35 @@ public final class AccessibilityInteractionClient
try {
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
- if (!bypassCache && sAccessibilityCache != null) {
- AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getNode(
- accessibilityWindowId, accessibilityNodeId);
- if (cachedInfo != null) {
+ if (!bypassCache) {
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache != null) {
+ AccessibilityNodeInfo cachedInfo = cache.getNode(
+ accessibilityWindowId, accessibilityNodeId);
+ if (cachedInfo != null) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Node cache hit for "
+ + idToString(accessibilityWindowId, accessibilityNodeId));
+ }
+ if (shouldTraceClient()) {
+ logTraceClient(connection,
+ "findAccessibilityNodeInfoByAccessibilityId cache",
+ "connectionId=" + connectionId + ";accessibilityWindowId="
+ + accessibilityWindowId + ";accessibilityNodeId="
+ + accessibilityNodeId + ";bypassCache="
+ + bypassCache + ";prefetchFlags=" + prefetchFlags
+ + ";arguments=" + arguments);
+ }
+ return cachedInfo;
+ }
if (DEBUG) {
- Log.i(LOG_TAG, "Node cache hit for "
+ Log.i(LOG_TAG, "Node cache miss for "
+ idToString(accessibilityWindowId, accessibilityNodeId));
}
- if (shouldTraceClient()) {
- logTraceClient(connection,
- "findAccessibilityNodeInfoByAccessibilityId cache",
- "connectionId=" + connectionId + ";accessibilityWindowId="
- + accessibilityWindowId + ";accessibilityNodeId="
- + accessibilityNodeId + ";bypassCache=" + bypassCache
- + ";prefetchFlags=" + prefetchFlags + ";arguments="
- + arguments);
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
}
- return cachedInfo;
- }
- if (DEBUG) {
- Log.i(LOG_TAG, "Node cache miss for "
- + idToString(accessibilityWindowId, accessibilityNodeId));
}
} else {
// No need to prefech nodes in bypass cache case.
@@ -758,19 +765,19 @@ public final class AccessibilityInteractionClient
}
/**
- * Finds the {@link android.view.accessibility.AccessibilityNodeInfo} that has the
+ * Finds the {@link AccessibilityNodeInfo} that has the
* specified focus type. The search is performed in the window whose id is specified
* and starts from the node whose accessibility id is specified.
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
+ * {@link AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window. Use
- * {@link android.view.accessibility.AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
+ * {@link AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
* windows
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
+ * {@link AccessibilityNodeInfo#ROOT_NODE_ID}
* to start from the root.
* @param focusType The focus type.
* @return The accessibility focused {@link AccessibilityNodeInfo}.
@@ -781,8 +788,9 @@ public final class AccessibilityInteractionClient
try {
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
- if (sAccessibilityCache != null) {
- AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getFocus(focusType,
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache != null) {
+ AccessibilityNodeInfo cachedInfo = cache.getFocus(focusType,
accessibilityNodeId, accessibilityWindowId);
if (cachedInfo != null) {
if (DEBUG) {
@@ -796,6 +804,10 @@ public final class AccessibilityInteractionClient
Log.i(LOG_TAG, "Focused node cache miss with "
+ idToString(accessibilityWindowId, accessibilityNodeId));
}
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+ }
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
if (shouldTraceClient()) {
@@ -956,16 +968,25 @@ public final class AccessibilityInteractionClient
}
/**
- * Clears the accessibility cache.
+ * Clears the cache associated with {@code connectionId}
+ * @param connectionId the connection id
+ * TODO(207417185): Modify UnsupportedAppUsage
*/
@UnsupportedAppUsage()
- public void clearCache() {
- if (sAccessibilityCache != null) {
- sAccessibilityCache.clear();
+ public void clearCache(int connectionId) {
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache == null) {
+ return;
}
+ cache.clear();
}
- public void onAccessibilityEvent(AccessibilityEvent event) {
+ /**
+ * Informs the cache associated with {@code connectionId} of {@code event}
+ * @param event the event
+ * @param connectionId the connection id
+ */
+ public void onAccessibilityEvent(AccessibilityEvent event, int connectionId) {
switch (event.getEventType()) {
case AccessibilityEvent.TYPE_VIEW_SCROLLED:
updateScrollingWindow(event.getWindowId(), SystemClock.uptimeMillis());
@@ -978,9 +999,14 @@ public final class AccessibilityInteractionClient
default:
break;
}
- if (sAccessibilityCache != null) {
- sAccessibilityCache.onAccessibilityEvent(event);
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache == null) {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+ }
+ return;
}
+ cache.onAccessibilityEvent(event);
}
/**
@@ -1216,8 +1242,15 @@ public final class AccessibilityInteractionClient
}
}
info.setSealed(true);
- if (!bypassCache && sAccessibilityCache != null) {
- sAccessibilityCache.add(info);
+ if (!bypassCache) {
+ AccessibilityCache cache = getCache(connectionId);
+ if (cache == null) {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+ }
+ return;
+ }
+ cache.add(info);
}
}
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 33c6a4bae33f..e689b5d33107 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -45,7 +45,6 @@ import androidx.test.runner.AndroidJUnit4;
import com.google.common.base.Throwables;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -82,13 +81,6 @@ public class AccessibilityCacheTest {
mAccessibilityCache = new AccessibilityCache(mAccessibilityNodeRefresher);
}
- @After
- public void tearDown() {
- // Make sure we're recycling all of our window and node infos.
- mAccessibilityCache.clear();
- AccessibilityInteractionClient.getInstance().clearCache();
- }
-
@Test
public void testEmptyCache_returnsNull() {
assertNull(mAccessibilityCache.getNode(0, 0));
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index 7e1e7f4bdd7f..3e061d208937 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -17,6 +17,9 @@
package android.view.accessibility;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.MockitoAnnotations.initMocks;
@@ -40,6 +43,8 @@ import org.mockito.Mock;
@RunWith(AndroidJUnit4.class)
public class AccessibilityInteractionClientTest {
private static final int MOCK_CONNECTION_ID = 0xabcd;
+ private static final int MOCK_CONNECTION_OTHER_ID = 0xabce;
+
private MockConnection mMockConnection = new MockConnection();
@Mock private AccessibilityCache mMockCache;
@@ -47,8 +52,8 @@ public class AccessibilityInteractionClientTest {
@Before
public void setUp() {
initMocks(this);
- AccessibilityInteractionClient.setCache(mMockCache);
- AccessibilityInteractionClient.addConnection(MOCK_CONNECTION_ID, mMockConnection);
+ AccessibilityInteractionClient.addConnection(
+ MOCK_CONNECTION_ID, mMockConnection, /*initializeCache=*/true);
}
/**
@@ -58,6 +63,7 @@ public class AccessibilityInteractionClientTest {
*/
@Test
public void findA11yNodeInfoByA11yId_whenBypassingCache_doesntTouchCache() {
+ AccessibilityInteractionClient.setCache(MOCK_CONNECTION_ID, mMockCache);
final int windowId = 0x1234;
final long accessibilityNodeId = 0x4321L;
AccessibilityNodeInfo nodeFromConnection = AccessibilityNodeInfo.obtain();
@@ -71,6 +77,42 @@ public class AccessibilityInteractionClientTest {
verifyZeroInteractions(mMockCache);
}
+ @Test
+ public void getCache_differentConnections_returnsDifferentCaches() {
+ MockConnection mOtherMockConnection = new MockConnection();
+ AccessibilityInteractionClient.addConnection(
+ MOCK_CONNECTION_OTHER_ID, mOtherMockConnection, /*initializeCache=*/true);
+
+ AccessibilityCache firstCache = AccessibilityInteractionClient.getCache(MOCK_CONNECTION_ID);
+ AccessibilityCache secondCache = AccessibilityInteractionClient.getCache(
+ MOCK_CONNECTION_OTHER_ID);
+ assertNotEquals(firstCache, secondCache);
+ }
+
+ @Test
+ public void getCache_addConnectionWithoutCache_returnsNullCache() {
+ // Need to first remove from process cache
+ AccessibilityInteractionClient.removeConnection(MOCK_CONNECTION_OTHER_ID);
+
+ MockConnection mOtherMockConnection = new MockConnection();
+ AccessibilityInteractionClient.addConnection(
+ MOCK_CONNECTION_OTHER_ID, mOtherMockConnection, /*initializeCache=*/false);
+
+ AccessibilityCache cache = AccessibilityInteractionClient.getCache(
+ MOCK_CONNECTION_OTHER_ID);
+ assertNull(cache);
+ }
+
+ @Test
+ public void getCache_removeConnection_returnsNull() {
+ AccessibilityCache cache = AccessibilityInteractionClient.getCache(MOCK_CONNECTION_ID);
+ assertNotNull(cache);
+
+ AccessibilityInteractionClient.removeConnection(MOCK_CONNECTION_ID);
+ cache = AccessibilityInteractionClient.getCache(MOCK_CONNECTION_ID);
+ assertNull(cache);
+ }
+
private static class MockConnection extends AccessibilityServiceConnectionImpl {
AccessibilityNodeInfo mInfoToReturn;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a11e2641e5c9..d0b298f8d730 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3528,9 +3528,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mConnectionId = service.mId;
- mClient = AccessibilityInteractionClient.getInstance(/* initializeCache= */false,
- mContext);
- mClient.addConnection(mConnectionId, service);
+ mClient = AccessibilityInteractionClient.getInstance(mContext);
+ mClient.addConnection(mConnectionId, service, /*initializeCache=*/false);
//TODO: (multi-display) We need to support multiple displays.
DisplayManager displayManager = (DisplayManager)