Merge "Fixed bug where certain focusable windows are reported to accessibility out of z order."
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index fe0b5c2..caebf15 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1066,93 +1066,19 @@
final int visibleWindowCount = visibleWindows.size();
HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
- for (int i = visibleWindowCount - 1; i >= 0; i--) {
+
+ // Iterate until we figure out what is touchable for the entire screen.
+ for (int i = visibleWindowCount - 1; i >= 0 && !unaccountedSpace.isEmpty(); i--) {
final WindowState windowState = visibleWindows.valueAt(i);
- final int flags = windowState.mAttrs.flags;
- final Task task = windowState.getTask();
- // If the window is part of a task that we're finished with - ignore.
- if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
- continue;
- }
-
- // Ignore non-touchable windows, except the split-screen divider, which is
- // occasionally non-touchable but still useful for identifying split-screen
- // mode.
- if (((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
- && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)) {
- continue;
- }
-
- // Compute the bounds in the screen.
final Rect boundsInScreen = mTempRect;
computeWindowBoundsInScreen(windowState, boundsInScreen);
- // If the window is completely covered by other windows - ignore.
- if (unaccountedSpace.quickReject(boundsInScreen)) {
- continue;
- }
-
- // Add windows of certain types not covered by modal windows.
- if (isReportedWindowType(windowState.mAttrs.type)) {
- // Add the window to the ones to be reported.
+ if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace,
+ skipRemainingWindowsForTasks)) {
addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows);
- if (windowState.isFocused()) {
- focusedWindowAdded = true;
- }
- }
-
- if (windowState.mAttrs.type !=
- WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
-
- // Account for the space this window takes if the window
- // is not an accessibility overlay which does not change
- // the reported windows.
- unaccountedSpace.op(boundsInScreen, unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
-
- // If a window is modal it prevents other windows from being touched
- if ((flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
- // Account for all space in the task, whether the windows in it are
- // touchable or not. The modal window blocks all touches from the task's
- // area.
- unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
-
- if (task != null) {
- // If the window is associated with a particular task, we can skip the
- // rest of the windows for that task.
- skipRemainingWindowsForTasks.add(task.mTaskId);
- continue;
- } else {
- // If the window is not associated with a particular task, then it is
- // globally modal. In this case we can skip all remaining windows.
- break;
- }
- }
- }
-
- // We figured out what is touchable for the entire screen - done.
- if (unaccountedSpace.isEmpty()) {
- break;
- }
- }
-
- // Always report the focused window.
- if (!focusedWindowAdded) {
- for (int i = visibleWindowCount - 1; i >= 0; i--) {
- WindowState windowState = visibleWindows.valueAt(i);
- if (windowState.isFocused()) {
- // Compute the bounds in the screen.
- Rect boundsInScreen = mTempRect;
- computeWindowBoundsInScreen(windowState, boundsInScreen);
-
- // Add the window to the ones to be reported.
- addPopulatedWindowInfo(
- windowState, boundsInScreen, windows, addedWindows);
- break;
- }
+ updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace,
+ skipRemainingWindowsForTasks);
}
}
@@ -1221,6 +1147,73 @@
clearAndRecycleWindows(windows);
}
+ private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen,
+ Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
+ if (windowState.isFocused()) {
+ return true;
+ }
+
+ // If the window is part of a task that we're finished with - ignore.
+ final Task task = windowState.getTask();
+ if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
+ return false;
+ }
+
+ // Ignore non-touchable windows, except the split-screen divider, which is
+ // occasionally non-touchable but still useful for identifying split-screen
+ // mode.
+ if (((windowState.mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
+ && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)) {
+ return false;
+ }
+
+ // If the window is completely covered by other windows - ignore.
+ if (unaccountedSpace.quickReject(boundsInScreen)) {
+ return false;
+ }
+
+ // Add windows of certain types not covered by modal windows.
+ if (isReportedWindowType(windowState.mAttrs.type)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen,
+ Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
+ if (windowState.mAttrs.type
+ != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
+
+ // Account for the space this window takes if the window
+ // is not an accessibility overlay which does not change
+ // the reported windows.
+ unaccountedSpace.op(boundsInScreen, unaccountedSpace,
+ Region.Op.REVERSE_DIFFERENCE);
+
+ // If a window is modal it prevents other windows from being touched
+ if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
+ // Account for all space in the task, whether the windows in it are
+ // touchable or not. The modal window blocks all touches from the task's
+ // area.
+ unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
+ Region.Op.REVERSE_DIFFERENCE);
+
+ final Task task = windowState.getTask();
+ if (task != null) {
+ // If the window is associated with a particular task, we can skip the
+ // rest of the windows for that task.
+ skipRemainingWindowsForTasks.add(task.mTaskId);
+ } else {
+ // If the window is not associated with a particular task, then it is
+ // globally modal. In this case we can skip all remaining windows.
+ unaccountedSpace.setEmpty();
+ }
+ }
+ }
+ }
+
private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) {
// Get the touchable frame.
Region touchableRegion = mTempRegion1;