Ensure that a11y window state change event is sent on focus change
Currently when the focus changes, an accessibility event of TYPE_WINDOW_STATE_CHANGED is dispatched from ViewRootImpl. This logic is implemented in performTraversals(), but the logic depends on the value mAttachInfo.mHasWindowFocus, which is updated from an input event handleWindowFocusChanged(). There's no guarantee that always performTraversals() is called after handleWindowFocusChanged(). As a result, sometimes accessibility event is not dispatched after focus change. This change fixes the issue by explicitly dispatching the event in handleWindowFocusChanged() if needed. Bug: 260310672 Bug: 214318644 Test: Accessibility CTS Change-Id: I95cf3a7a9c7951f8b3862713ed7339688a8427d5
This commit is contained in:
@@ -470,16 +470,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private boolean mAppVisibilityChanged;
|
||||
int mOrigWindowType = -1;
|
||||
|
||||
/** Whether the window had focus during the most recent traversal. */
|
||||
boolean mHadWindowFocus;
|
||||
|
||||
/**
|
||||
* Whether the window lost focus during a previous traversal and has not
|
||||
* yet gained it back. Used to determine whether a WINDOW_STATE_CHANGE
|
||||
* accessibility events should be sent during traversal.
|
||||
*/
|
||||
boolean mLostWindowFocus;
|
||||
|
||||
// Set to true if the owner of this window is in the stopped state,
|
||||
// so the window should no longer be active.
|
||||
@UnsupportedAppUsage
|
||||
@@ -3573,20 +3563,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
|
||||
final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible;
|
||||
final boolean hasWindowFocus = mAttachInfo.mHasWindowFocus && isViewVisible;
|
||||
final boolean regainedFocus = hasWindowFocus && mLostWindowFocus;
|
||||
if (regainedFocus) {
|
||||
mLostWindowFocus = false;
|
||||
} else if (!hasWindowFocus && mHadWindowFocus) {
|
||||
mLostWindowFocus = true;
|
||||
}
|
||||
|
||||
if (changedVisibility || regainedFocus) {
|
||||
// Toasts are presented as notifications - don't present them as windows as well
|
||||
boolean isToast = mWindowAttributes.type == TYPE_TOAST;
|
||||
if (!isToast) {
|
||||
host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
}
|
||||
if (changedVisibility) {
|
||||
maybeFireAccessibilityWindowStateChangedEvent();
|
||||
}
|
||||
|
||||
mFirst = false;
|
||||
@@ -3594,8 +3572,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mNewSurfaceNeeded = false;
|
||||
mActivityRelaunched = false;
|
||||
mViewVisibility = viewVisibility;
|
||||
mHadWindowFocus = hasWindowFocus;
|
||||
|
||||
final boolean hasWindowFocus = mAttachInfo.mHasWindowFocus && isViewVisible;
|
||||
mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes);
|
||||
|
||||
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
|
||||
@@ -3838,6 +3816,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
~WindowManager.LayoutParams
|
||||
.SOFT_INPUT_IS_FORWARD_NAVIGATION;
|
||||
|
||||
maybeFireAccessibilityWindowStateChangedEvent();
|
||||
|
||||
// Refocusing a window that has a focused view should fire a
|
||||
// focus event for the view since the global focused view changed.
|
||||
fireAccessibilityFocusEventIfHasFocusedNode();
|
||||
@@ -3865,6 +3845,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
ensureTouchModeLocally(inTouchMode);
|
||||
}
|
||||
|
||||
private void maybeFireAccessibilityWindowStateChangedEvent() {
|
||||
// Toasts are presented as notifications - don't present them as windows as well.
|
||||
boolean isToast = mWindowAttributes != null && (mWindowAttributes.type == TYPE_TOAST);
|
||||
if (!isToast && mView != null) {
|
||||
mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireAccessibilityFocusEventIfHasFocusedNode() {
|
||||
if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user