Prevent AccessibilityInteractionClient.getWindows()
returns partially cached windows list.
It could happen that AccessibilityWindowInfo cache is
cleared. And after that calling
AccessibilityInteractionClient.getWindow(windowId)
would add that window to cache. And while cache is
not empty after that AccessibilityInteractionClient
returns its content on getWindows() request even
if it does not contain all windows.
Change-Id: I70dc96d50e3368285fd482a98769a93ae2c15f22
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index d0dde00..1da305f 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -43,6 +43,8 @@
private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ private boolean mIsAllWindowsCached;
+
private final SparseArray<AccessibilityWindowInfo> mWindowCache =
new SparseArray<>();
@@ -52,6 +54,24 @@
private final SparseArray<AccessibilityWindowInfo> mTempWindowArray =
new SparseArray<>();
+ public void setWindows(List<AccessibilityWindowInfo> windows) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Set windows");
+ }
+ clearWindowCache();
+ if (windows == null) {
+ return;
+ }
+ final int windowCount = windows.size();
+ for (int i = 0; i < windowCount; i++) {
+ final AccessibilityWindowInfo window = windows.get(i);
+ addWindow(window);
+ }
+ mIsAllWindowsCached = true;
+ }
+ }
+
public void addWindow(AccessibilityWindowInfo window) {
synchronized (mLock) {
if (DEBUG) {
@@ -186,6 +206,10 @@
public List<AccessibilityWindowInfo> getWindows() {
synchronized (mLock) {
+ if (!mIsAllWindowsCached) {
+ return null;
+ }
+
final int windowCount = mWindowCache.size();
if (windowCount > 0) {
// Careful to return the windows in a decreasing layer order.
@@ -280,12 +304,7 @@
if (DEBUG) {
Log.i(LOG_TAG, "clear()");
}
- final int windowCount = mWindowCache.size();
- for (int i = windowCount - 1; i >= 0; i--) {
- AccessibilityWindowInfo window = mWindowCache.valueAt(i);
- window.recycle();
- mWindowCache.removeAt(i);
- }
+ clearWindowCache();
final int nodesForWindowCount = mNodeCache.size();
for (int i = 0; i < nodesForWindowCount; i++) {
final int windowId = mNodeCache.keyAt(i);
@@ -297,6 +316,16 @@
}
}
+ private void clearWindowCache() {
+ final int windowCount = mWindowCache.size();
+ for (int i = windowCount - 1; i >= 0; i--) {
+ AccessibilityWindowInfo window = mWindowCache.valueAt(i);
+ window.recycle();
+ mWindowCache.removeAt(i);
+ }
+ mIsAllWindowsCached = false;
+ }
+
private void clearNodesForWindowLocked(int windowId) {
if (DEBUG) {
Log.i(LOG_TAG, "clearNodesForWindowLocked(" + windowId + ")");
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index b49cbc6..1406fbd 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -228,11 +228,7 @@
windows = connection.getWindows();
Binder.restoreCallingIdentity(identityToken);
if (windows != null) {
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
- sAccessibilityCache.addWindow(window);
- }
+ sAccessibilityCache.setWindows(windows);
return windows;
}
} else {