diff options
| author | Jacky Kao <jackykao@google.com> | 2019-09-12 09:59:04 +0800 |
|---|---|---|
| committer | Jacky Kao <jackykao@google.com> | 2019-09-16 17:00:39 +0800 |
| commit | 35b8966e77daf6ba16dd67d0dd4e50b3bc329db5 (patch) | |
| tree | f9bb0dd97c4dd0207cc92ff6760a74074b6deb87 /core/java/android | |
| parent | 2cd85a8ae055a79e7557deb06e776b4acb628b53 (diff) | |
Modifying the mechanism of A11y window cache
For supoorting new API as below, the A11y window cache needs to modify
from one dimension to two dimension. The first dimension is window Id,
the second(new) dimention is the display Id.
SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays()
Bug: 133279356
Test: a11y CTS & unit tests
Change-Id: Ida49ef22de67bd81353a896491dcae56ed751fd1
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityCache.java | 204 | ||||
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityInteractionClient.java | 13 |
2 files changed, 159 insertions, 58 deletions
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index 484d9a1d173b..dc8bf9b5fbae 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -71,7 +71,9 @@ public class AccessibilityCache { private boolean mIsAllWindowsCached; - private final SparseArray<AccessibilityWindowInfo> mWindowCache = + // The SparseArray of all {@link AccessibilityWindowInfo}s on all displays. + // The key of outer SparseArray is display ID and the key of inner SparseArray is window ID. + private final SparseArray<SparseArray<AccessibilityWindowInfo>> mWindowCacheByDisplay = new SparseArray<>(); private final SparseArray<LongSparseArray<AccessibilityNodeInfo>> mNodeCache = @@ -84,34 +86,66 @@ public class AccessibilityCache { mAccessibilityNodeRefresher = nodeRefresher; } - public void setWindows(List<AccessibilityWindowInfo> windows) { + /** + * Sets all {@link AccessibilityWindowInfo}s of all displays into the cache. + * The key of SparseArray is display ID. + * + * @param windowsOnAllDisplays The accessibility windows of all displays. + */ + public void setWindowsOnAllDisplays( + SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays) { synchronized (mLock) { if (DEBUG) { Log.i(LOG_TAG, "Set windows"); } - clearWindowCache(); - if (windows == null) { + clearWindowCacheLocked(); + if (windowsOnAllDisplays == null) { return; } - final int windowCount = windows.size(); - for (int i = 0; i < windowCount; i++) { - final AccessibilityWindowInfo window = windows.get(i); - addWindow(window); + + final int displayCounts = windowsOnAllDisplays.size(); + for (int i = 0; i < displayCounts; i++) { + final List<AccessibilityWindowInfo> windowsOfDisplay = + windowsOnAllDisplays.valueAt(i); + + if (windowsOfDisplay == null) { + continue; + } + + final int displayId = windowsOnAllDisplays.keyAt(i); + final int windowCount = windowsOfDisplay.size(); + for (int j = 0; j < windowCount; j++) { + addWindowByDisplayLocked(displayId, windowsOfDisplay.get(j)); + } } mIsAllWindowsCached = true; } } + /** + * Sets an {@link AccessibilityWindowInfo} into the cache. + * + * @param window The accessibility window. + */ public void addWindow(AccessibilityWindowInfo window) { synchronized (mLock) { if (DEBUG) { - Log.i(LOG_TAG, "Caching window: " + window.getId()); + Log.i(LOG_TAG, "Caching window: " + window.getId() + " at display Id [ " + + window.getDisplayId() + " ]"); } - final int windowId = window.getId(); - mWindowCache.put(windowId, new AccessibilityWindowInfo(window)); + addWindowByDisplayLocked(window.getDisplayId(), window); } } + private void addWindowByDisplayLocked(int displayId, AccessibilityWindowInfo window) { + SparseArray<AccessibilityWindowInfo> windows = mWindowCacheByDisplay.get(displayId); + if (windows == null) { + windows = new SparseArray<>(); + mWindowCacheByDisplay.put(displayId, windows); + } + final int windowId = window.getId(); + windows.put(windowId, new AccessibilityWindowInfo(window)); + } /** * Notifies the cache that the something in the UI changed. As a result * the cache will either refresh some nodes or evict some nodes. @@ -236,44 +270,82 @@ public class AccessibilityCache { } } - public List<AccessibilityWindowInfo> getWindows() { + /** + * Gets all {@link AccessibilityWindowInfo}s of all displays from the cache. + * + * @return All cached {@link AccessibilityWindowInfo}s of all displays + * or null if such not found. The key of SparseArray is display ID. + */ + public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() { synchronized (mLock) { if (!mIsAllWindowsCached) { return null; } + final SparseArray<List<AccessibilityWindowInfo>> returnWindows = new SparseArray<>(); + final int displayCounts = mWindowCacheByDisplay.size(); - final int windowCount = mWindowCache.size(); - if (windowCount > 0) { - // Careful to return the windows in a decreasing layer order. - SparseArray<AccessibilityWindowInfo> sortedWindows = mTempWindowArray; - sortedWindows.clear(); + if (displayCounts > 0) { + for (int i = 0; i < displayCounts; i++) { + final int displayId = mWindowCacheByDisplay.keyAt(i); + final SparseArray<AccessibilityWindowInfo> windowsOfDisplay = + mWindowCacheByDisplay.valueAt(i); - for (int i = 0; i < windowCount; i++) { - AccessibilityWindowInfo window = mWindowCache.valueAt(i); - sortedWindows.put(window.getLayer(), window); - } + if (windowsOfDisplay == null) { + continue; + } - // It's possible in transient conditions for two windows to share the same - // layer, which results in sortedWindows being smaller than mWindowCache - final int sortedWindowCount = sortedWindows.size(); - List<AccessibilityWindowInfo> windows = new ArrayList<>(sortedWindowCount); - for (int i = sortedWindowCount - 1; i >= 0; i--) { - AccessibilityWindowInfo window = sortedWindows.valueAt(i); - windows.add(new AccessibilityWindowInfo(window)); - sortedWindows.removeAt(i); - } + final int windowCount = windowsOfDisplay.size(); + if (windowCount > 0) { + // Careful to return the windows in a decreasing layer order. + SparseArray<AccessibilityWindowInfo> sortedWindows = mTempWindowArray; + sortedWindows.clear(); - return windows; + for (int j = 0; j < windowCount; j++) { + AccessibilityWindowInfo window = windowsOfDisplay.valueAt(j); + sortedWindows.put(window.getLayer(), window); + } + + // It's possible in transient conditions for two windows to share the same + // layer, which results in sortedWindows being smaller than + // mWindowCacheByDisplay + final int sortedWindowCount = sortedWindows.size(); + List<AccessibilityWindowInfo> windows = + new ArrayList<>(sortedWindowCount); + for (int j = sortedWindowCount - 1; j >= 0; j--) { + AccessibilityWindowInfo window = sortedWindows.valueAt(j); + windows.add(new AccessibilityWindowInfo(window)); + sortedWindows.removeAt(j); + } + returnWindows.put(displayId, windows); + } + } + return returnWindows; } return null; } } + /** + * Gets an {@link AccessibilityWindowInfo} by windowId. + * + * @param windowId The id of the window. + * + * @return The {@link AccessibilityWindowInfo} or null if such not found. + */ public AccessibilityWindowInfo getWindow(int windowId) { synchronized (mLock) { - AccessibilityWindowInfo window = mWindowCache.get(windowId); - if (window != null) { - return new AccessibilityWindowInfo(window); + final int displayCounts = mWindowCacheByDisplay.size(); + for (int i = 0; i < displayCounts; i++) { + final SparseArray<AccessibilityWindowInfo> windowsOfDisplay = + mWindowCacheByDisplay.valueAt(i); + if (windowsOfDisplay == null) { + continue; + } + + AccessibilityWindowInfo window = windowsOfDisplay.get(windowId); + if (window != null) { + return new AccessibilityWindowInfo(window); + } } return null; } @@ -358,7 +430,7 @@ public class AccessibilityCache { if (DEBUG) { Log.i(LOG_TAG, "clear()"); } - clearWindowCache(); + clearWindowCacheLocked(); final int nodesForWindowCount = mNodeCache.size(); for (int i = nodesForWindowCount - 1; i >= 0; i--) { final int windowId = mNodeCache.keyAt(i); @@ -370,8 +442,23 @@ public class AccessibilityCache { } } - private void clearWindowCache() { - mWindowCache.clear(); + private void clearWindowCacheLocked() { + if (DEBUG) { + Log.i(LOG_TAG, "clearWindowCacheLocked"); + } + final int displayCounts = mWindowCacheByDisplay.size(); + + if (displayCounts > 0) { + for (int i = displayCounts - 1; i >= 0; i--) { + final int displayId = mWindowCacheByDisplay.keyAt(i); + final SparseArray<AccessibilityWindowInfo> windows = + mWindowCacheByDisplay.get(displayId); + if (windows != null) { + windows.clear(); + } + mWindowCacheByDisplay.remove(displayId); + } + } mIsAllWindowsCached = false; } @@ -444,32 +531,41 @@ public class AccessibilityCache { public void checkIntegrity() { synchronized (mLock) { // Get the root. - if (mWindowCache.size() <= 0 && mNodeCache.size() == 0) { + if (mWindowCacheByDisplay.size() <= 0 && mNodeCache.size() == 0) { return; } AccessibilityWindowInfo focusedWindow = null; AccessibilityWindowInfo activeWindow = null; - final int windowCount = mWindowCache.size(); - for (int i = 0; i < windowCount; i++) { - AccessibilityWindowInfo window = mWindowCache.valueAt(i); + final int displayCounts = mWindowCacheByDisplay.size(); + for (int i = 0; i < displayCounts; i++) { + final SparseArray<AccessibilityWindowInfo> windowsOfDisplay = + mWindowCacheByDisplay.valueAt(i); - // Check for one active window. - if (window.isActive()) { - if (activeWindow != null) { - Log.e(LOG_TAG, "Duplicate active window:" + window); - } else { - activeWindow = window; - } + if (windowsOfDisplay == null) { + continue; } - // Check for one focused window. - if (window.isFocused()) { - if (focusedWindow != null) { - Log.e(LOG_TAG, "Duplicate focused window:" + window); - } else { - focusedWindow = window; + final int windowCount = windowsOfDisplay.size(); + for (int j = 0; j < windowCount; j++) { + final AccessibilityWindowInfo window = windowsOfDisplay.valueAt(j); + + // Check for one active window. + if (window.isActive()) { + if (activeWindow != null) { + Log.e(LOG_TAG, "Duplicate active window:" + window); + } else { + activeWindow = window; + } + } + // Check for one focused window. + if (window.isFocused()) { + if (focusedWindow != null) { + Log.e(LOG_TAG, "Duplicate focused window:" + window); + } else { + focusedWindow = window; + } } } } diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java index 4db6f4f808f2..d9fa9f24f1ae 100644 --- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java +++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java @@ -28,6 +28,7 @@ import android.os.SystemClock; import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; +import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -267,12 +268,14 @@ public final class AccessibilityInteractionClient try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { - List<AccessibilityWindowInfo> windows = sAccessibilityCache.getWindows(); - if (windows != null) { + SparseArray<List<AccessibilityWindowInfo>> allWindows = + sAccessibilityCache.getWindowsOnAllDisplays(); + List<AccessibilityWindowInfo> windows; + if (allWindows != null) { if (DEBUG) { Log.i(LOG_TAG, "Windows cache hit"); } - return windows; + return allWindows.valueAt(Display.DEFAULT_DISPLAY); } if (DEBUG) { Log.i(LOG_TAG, "Windows cache miss"); @@ -284,7 +287,9 @@ public final class AccessibilityInteractionClient Binder.restoreCallingIdentity(identityToken); } if (windows != null) { - sAccessibilityCache.setWindows(windows); + allWindows = new SparseArray<>(); + allWindows.put(Display.DEFAULT_DISPLAY, windows); + sAccessibilityCache.setWindowsOnAllDisplays(allWindows); return windows; } } else { |
