Populate a11y action in event throttle of ViewRootImpl

In ViewRootImpl#SendWindowContentChangedAccessibilityEvent throttles
a11y events of TYPE_WINDOW_CONTENT_CHANGED, and may merge multiple
events into one.

This changes adds merging logic of AccessibilityEvent#getAction.

Bug: 263246622
Test: CtsAccessibilityServiceTestCases
Change-Id: I3b80a26520f1ec6587deb7991b9d6287e3067131
This commit is contained in:
Hiroki Sato
2022-12-21 18:02:22 +09:00
parent 44fdc24abb
commit a9eff61100
2 changed files with 35 additions and 0 deletions

View File

@@ -228,6 +228,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -10833,6 +10834,12 @@ public final class ViewRootImpl implements ViewParent,
public View mSource;
public long mLastEventTimeMillis;
/**
* Keep track of action that caused the event.
* This is empty if there's no performing actions for pending events.
* This is zero if there're multiple events performed for pending events.
*/
@NonNull public OptionalInt mAction = OptionalInt.empty();
/**
* Override for {@link AccessibilityEvent#originStackTrace} to provide the stack trace
* of the original {@link #runOrPost} call instead of one for sending the delayed event
@@ -10856,6 +10863,7 @@ public final class ViewRootImpl implements ViewParent,
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
event.setContentChangeTypes(mChangeTypes);
if (mAction.isPresent()) event.setAction(mAction.getAsInt());
if (AccessibilityEvent.DEBUG_ORIGIN) event.originStackTrace = mOrigin;
source.sendAccessibilityEventUnchecked(event);
} else {
@@ -10864,6 +10872,7 @@ public final class ViewRootImpl implements ViewParent,
// In any case reset to initial state.
source.resetSubtreeAccessibilityStateChanged();
mChangeTypes = 0;
mAction = OptionalInt.empty();
if (AccessibilityEvent.DEBUG_ORIGIN) mOrigin = null;
}
@@ -10893,10 +10902,27 @@ public final class ViewRootImpl implements ViewParent,
}
mSource = (predecessor != null) ? predecessor : source;
mChangeTypes |= changeType;
final int performingAction = mAccessibilityManager.getPerformingAction();
if (performingAction != 0) {
if (mAction.isEmpty()) {
mAction = OptionalInt.of(performingAction);
} else if (mAction.getAsInt() != performingAction) {
// Multiple actions are performed for pending events. We cannot decide one
// action here.
// We're doing best effort to set action value, and it's fine to set
// no action this case.
mAction = OptionalInt.of(0);
}
}
return;
}
mSource = source;
mChangeTypes = changeType;
if (mAccessibilityManager.getPerformingAction() != 0) {
mAction = OptionalInt.of(mAccessibilityManager.getPerformingAction());
}
if (AccessibilityEvent.DEBUG_ORIGIN) {
mOrigin = Thread.currentThread().getStackTrace();
}

View File

@@ -1274,6 +1274,15 @@ public final class AccessibilityManager {
mPerformingAction = actionId;
}
/**
* Get the id of {@link AccessibilityNodeInfo.AccessibilityAction} currently being performed.
*
* @hide
*/
public int getPerformingAction() {
return mPerformingAction;
}
/**
* Registers a {@link HighTextContrastChangeListener} for changes in
* the global high text contrast state of the system.