diff options
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityCache.java | 14 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java | 20 |
2 files changed, 31 insertions, 3 deletions
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index 87e18b71069c..5d59e4205579 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -424,20 +424,28 @@ public class AccessibilityCache { * * @param nodes The nodes in the hosting window. * @param rootNodeId The id of the root to evict. + * + * @return {@code true} if the cache was cleared */ - private void clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes, + private boolean clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes, long rootNodeId) { AccessibilityNodeInfo current = nodes.get(rootNodeId); if (current == null) { - return; + // The node isn't in the cache, but its descendents might be. + clear(); + return true; } nodes.remove(rootNodeId); final int childCount = current.getChildCount(); for (int i = 0; i < childCount; i++) { final long childNodeId = current.getChildId(i); - clearSubTreeRecursiveLocked(nodes, childNodeId); + if (clearSubTreeRecursiveLocked(nodes, childNodeId)) { + current.recycle(); + return true; + } } current.recycle(); + return false; } /** diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java index e3852e1b627e..a88968bfd089 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java @@ -301,6 +301,26 @@ public class AccessibilityCacheTest { } @Test + public void subTreeChangeEventFromUncachedNode_clearsNodeInCache() { + AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1); + long id = nodeInfo.getSourceNodeId(); + mAccessibilityCache.add(nodeInfo); + nodeInfo.recycle(); + + AccessibilityEvent event = AccessibilityEvent + .obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); + event.setSource(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1)); + + mAccessibilityCache.onAccessibilityEvent(event); + AccessibilityNodeInfo shouldBeNull = mAccessibilityCache.getNode(WINDOW_ID_1, id); + if (shouldBeNull != null) { + shouldBeNull.recycle(); + } + assertNull(shouldBeNull); + } + + @Test public void scrollEvent_clearsNodeAndChild() { AccessibilityEvent event = AccessibilityEvent .obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED); |