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

Commit 331300d5 authored by Hiroki Sato's avatar Hiroki Sato
Browse files

Improve window content change events merging from multiple views

Since event throttled is merged into ViewRootImpl [1], even when events
from different nodes are merged, it looks like an event from a single
node.
Such an event should be marked as CHANGE_TYPE_SUBTREE.

Especially, without this change, there's a corner case where
AccessibilityCache is not able to invalidate node correctly. This case
is covered by a new CTS added together with this change.

This also updates a logic to change the event source to important parent
node, which was added in [2]. This should not be applied when there's
only a single node that is dispatching events, thus this change moves it
just before an event is actually dispatched.

[1] I1e1ecf1afc399e4103da82e6ed1779abfd3ec955
[2] I3c3c66151b6cd4773de4eadd417709e9a61a7cf2

Bug: 277305460
Test: CtsAccessibilityTestCases CtsAccessibilityServiceTestCases
Change-Id: Ic71f22ed6f6f54f49810dc83dc85dcd492dfc104
parent 9a62e2d0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -15015,6 +15015,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /** @hide */
    @Nullable
    View getSelfOrParentImportantForA11y() {
        if (isImportantForAccessibility()) return this;
        ViewParent parent = getParentForAccessibility();
+33 −8
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_B
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.accessibility.Flags.fixMergedContentChangeEvent;
import static android.view.accessibility.Flags.forceInvertColor;
import static android.view.accessibility.Flags.reduceWindowContentChangedEventThrottle;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
@@ -11492,6 +11493,15 @@ public final class ViewRootImpl implements ViewParent,
                event.setContentChangeTypes(mChangeTypes);
                if (mAction.isPresent()) event.setAction(mAction.getAsInt());
                if (AccessibilityEvent.DEBUG_ORIGIN) event.originStackTrace = mOrigin;
                if (fixMergedContentChangeEvent()) {
                    if ((mChangeTypes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0) {
                        final View importantParent = source.getSelfOrParentImportantForA11y();
                        if (importantParent != null) {
                            source = importantParent;
                        }
                    }
                }
                source.sendAccessibilityEventUnchecked(event);
            } else {
                mLastEventTimeMillis = 0;
@@ -11526,6 +11536,20 @@ public final class ViewRootImpl implements ViewParent,
            }
            if (mSource != null) {
                if (fixMergedContentChangeEvent()) {
                    View newSource = getCommonPredecessor(mSource, source);
                    if (newSource == null) {
                        // If there is no common predecessor, then mSource points to
                        // a removed view, hence in this case always prefer the source.
                        newSource = source;
                    }
                    mChangeTypes |= changeType;
                    if (mSource != newSource) {
                        mChangeTypes |= AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
                        mSource = newSource;
                    }
                } else {
                    // 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);
@@ -11534,6 +11558,7 @@ public final class ViewRootImpl implements ViewParent,
                    }
                    mSource = (predecessor != null) ? predecessor : source;
                    mChangeTypes |= changeType;
                }
                final int performingAction = mAccessibilityManager.getPerformingAction();
                if (performingAction != 0) {
+7 −0
Original line number Diff line number Diff line
@@ -51,6 +51,13 @@ flag {
    bug: "280130713"
}

flag {
    namespace: "accessibility"
    name: "fix_merged_content_change_event"
    description: "Fixes event type and source of content change event merged in ViewRootImpl"
    bug: "277305460"
}

flag {
    namespace: "accessibility"
    name: "flash_notification_system_api"