Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f69c16c authored by Phil Weaver's avatar Phil Weaver
Browse files

Fix a11y cache correctness bug

If two views change, their common ancestor can send
a subtree_changed event. But the cache is dropping
events that come from views that it hasn't cached.

Now clearing the cache entirely when a node not in
the cache sends a subtree changed event, since we
don't know which nodes are descendents and which
may have changed.

I'm not thrilled with this change, since it may
degrade performance, but I want to fix the correctness
problem quickly.

Bug: 111554539
Test: atest AccessibilityCacheTest
Change-Id: Ib32d3622cddd7001663943eff71e823d21f5e500
(cherry picked from commit a4002c8d)
parent 82b0d17b
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -418,20 +418,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;
    }

    /**
+20 −0
Original line number Diff line number Diff line
@@ -299,6 +299,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