From 9af1378c82c2e39c40383af117c568257152eee9 Mon Sep 17 00:00:00 2001 From: Eugene Susla Date: Thu, 22 Mar 2018 16:29:10 -0700 Subject: [DO NOT MERGE] Avoid sending content changed a11y events from wrong views The root cause of both attached bugs was the tree-merging algorithm in ViewRootImpl.SendWindowContentChangedAccessibilityEvent converging on a common predecessor that is marked not View#isImportantForAccessibility. As a result, such unlucky content changed events were discarded. Fixes: 72378611, 72950579 Test: ensure attached bugs are fixed Change-Id: I3c3c66151b6cd4773de4eadd417709e9a61a7cf2 (cherry picked from commit 3fb3c590400ae7bcc9bc7d5baba5a29678f9e873) --- core/java/android/view/ViewRootImpl.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'core/java/android/view/ViewRootImpl.java') diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e802232bae33..f6d9a16e4246 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -8305,6 +8305,12 @@ public final class ViewRootImpl implements ViewParent, public View mSource; public long mLastEventTimeMillis; + /** + * Override for {@link AccessibilityEvent#originStackTrace} to provide the stack trace + * of the original {@link #runOrPost} call instead of one for sending the delayed event + * from a looper. + */ + public StackTraceElement[] mOrigin; @Override public void run() { @@ -8322,6 +8328,7 @@ public final class ViewRootImpl implements ViewParent, AccessibilityEvent event = AccessibilityEvent.obtain(); event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); event.setContentChangeTypes(mChangeTypes); + if (AccessibilityEvent.DEBUG_ORIGIN) event.originStackTrace = mOrigin; source.sendAccessibilityEventUnchecked(event); } else { mLastEventTimeMillis = 0; @@ -8329,6 +8336,7 @@ public final class ViewRootImpl implements ViewParent, // In any case reset to initial state. source.resetSubtreeAccessibilityStateChanged(); mChangeTypes = 0; + if (AccessibilityEvent.DEBUG_ORIGIN) mOrigin = null; } public void runOrPost(View source, int changeType) { @@ -8352,12 +8360,18 @@ public final class ViewRootImpl implements ViewParent, // If there is no common predecessor, then mSource points to // a removed view, hence in this case always prefer the source. View predecessor = getCommonPredecessor(mSource, source); + if (predecessor != null) { + predecessor = predecessor.getSelfOrParentImportantForA11y(); + } mSource = (predecessor != null) ? predecessor : source; mChangeTypes |= changeType; return; } mSource = source; mChangeTypes = changeType; + if (AccessibilityEvent.DEBUG_ORIGIN) { + mOrigin = Thread.currentThread().getStackTrace(); + } final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis; final long minEventIntevalMillis = ViewConfiguration.getSendRecurringAccessibilityEventsInterval(); -- cgit v1.2.3