Loading core/java/android/accessibilityservice/AccessibilityService.java +6 −5 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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()); Loading @@ -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; Loading @@ -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: { Loading core/java/android/app/UiAutomation.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading core/java/android/view/AccessibilityInteractionController.java +1 −2 Original line number Diff line number Diff line Loading @@ -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. Loading core/java/android/view/accessibility/AccessibilityInteractionClient.java +132 −99 Original line number Diff line number Diff line Loading @@ -115,7 +115,7 @@ 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(); Loading Loading @@ -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); } /** Loading @@ -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; Loading @@ -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); } /** Loading @@ -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; Loading @@ -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); } } Loading @@ -255,6 +253,7 @@ public final class AccessibilityInteractionClient public static void removeConnection(int connectionId) { synchronized (sConnectionCache) { sConnectionCache.remove(connectionId); sCaches.remove(connectionId); } } Loading @@ -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. Loading Loading @@ -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}. Loading @@ -344,8 +332,10 @@ public final class AccessibilityInteractionClient IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { AccessibilityWindowInfo window; if (!bypassCache && sAccessibilityCache != null) { window = sAccessibilityCache.getWindow(accessibilityWindowId); 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"); Loading @@ -361,6 +351,11 @@ public final class AccessibilityInteractionClient Log.i(LOG_TAG, "Window cache miss"); } } } else { if (DEBUG) { Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId); } } final long identityToken = Binder.clearCallingIdentity(); try { Loading @@ -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; } Loading Loading @@ -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"); Loading @@ -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; Loading @@ -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; } Loading Loading @@ -533,8 +533,10 @@ public final class AccessibilityInteractionClient try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { if (!bypassCache && sAccessibilityCache != null) { AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getNode( if (!bypassCache) { AccessibilityCache cache = getCache(connectionId); if (cache != null) { AccessibilityNodeInfo cachedInfo = cache.getNode( accessibilityWindowId, accessibilityNodeId); if (cachedInfo != null) { if (DEBUG) { Loading @@ -546,9 +548,9 @@ public final class AccessibilityInteractionClient "findAccessibilityNodeInfoByAccessibilityId cache", "connectionId=" + connectionId + ";accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" + accessibilityNodeId + ";bypassCache=" + bypassCache + ";prefetchFlags=" + prefetchFlags + ";arguments=" + arguments); + accessibilityNodeId + ";bypassCache=" + bypassCache + ";prefetchFlags=" + prefetchFlags + ";arguments=" + arguments); } return cachedInfo; } Loading @@ -556,6 +558,11 @@ public final class AccessibilityInteractionClient Log.i(LOG_TAG, "Node cache miss for " + idToString(accessibilityWindowId, accessibilityNodeId)); } } else { if (DEBUG) { Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId); } } } else { // No need to prefech nodes in bypass cache case. prefetchFlags &= ~AccessibilityNodeInfo.FLAG_PREFETCH_MASK; Loading Loading @@ -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}. Loading @@ -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) { Loading @@ -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()) { Loading Loading @@ -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()); Loading @@ -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); } /** Loading Loading @@ -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); } } } Loading core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +0 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading Loading
core/java/android/accessibilityservice/AccessibilityService.java +6 −5 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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()); Loading @@ -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; Loading @@ -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: { Loading
core/java/android/app/UiAutomation.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading
core/java/android/view/AccessibilityInteractionController.java +1 −2 Original line number Diff line number Diff line Loading @@ -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. Loading
core/java/android/view/accessibility/AccessibilityInteractionClient.java +132 −99 Original line number Diff line number Diff line Loading @@ -115,7 +115,7 @@ 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(); Loading Loading @@ -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); } /** Loading @@ -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; Loading @@ -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); } /** Loading @@ -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; Loading @@ -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); } } Loading @@ -255,6 +253,7 @@ public final class AccessibilityInteractionClient public static void removeConnection(int connectionId) { synchronized (sConnectionCache) { sConnectionCache.remove(connectionId); sCaches.remove(connectionId); } } Loading @@ -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. Loading Loading @@ -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}. Loading @@ -344,8 +332,10 @@ public final class AccessibilityInteractionClient IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { AccessibilityWindowInfo window; if (!bypassCache && sAccessibilityCache != null) { window = sAccessibilityCache.getWindow(accessibilityWindowId); 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"); Loading @@ -361,6 +351,11 @@ public final class AccessibilityInteractionClient Log.i(LOG_TAG, "Window cache miss"); } } } else { if (DEBUG) { Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId); } } final long identityToken = Binder.clearCallingIdentity(); try { Loading @@ -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; } Loading Loading @@ -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"); Loading @@ -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; Loading @@ -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; } Loading Loading @@ -533,8 +533,10 @@ public final class AccessibilityInteractionClient try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { if (!bypassCache && sAccessibilityCache != null) { AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getNode( if (!bypassCache) { AccessibilityCache cache = getCache(connectionId); if (cache != null) { AccessibilityNodeInfo cachedInfo = cache.getNode( accessibilityWindowId, accessibilityNodeId); if (cachedInfo != null) { if (DEBUG) { Loading @@ -546,9 +548,9 @@ public final class AccessibilityInteractionClient "findAccessibilityNodeInfoByAccessibilityId cache", "connectionId=" + connectionId + ";accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" + accessibilityNodeId + ";bypassCache=" + bypassCache + ";prefetchFlags=" + prefetchFlags + ";arguments=" + arguments); + accessibilityNodeId + ";bypassCache=" + bypassCache + ";prefetchFlags=" + prefetchFlags + ";arguments=" + arguments); } return cachedInfo; } Loading @@ -556,6 +558,11 @@ public final class AccessibilityInteractionClient Log.i(LOG_TAG, "Node cache miss for " + idToString(accessibilityWindowId, accessibilityNodeId)); } } else { if (DEBUG) { Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId); } } } else { // No need to prefech nodes in bypass cache case. prefetchFlags &= ~AccessibilityNodeInfo.FLAG_PREFETCH_MASK; Loading Loading @@ -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}. Loading @@ -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) { Loading @@ -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()) { Loading Loading @@ -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()); Loading @@ -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); } /** Loading Loading @@ -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); } } } Loading
core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +0 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading