diff options
| author | 2019-01-07 21:57:45 +0000 | |
|---|---|---|
| committer | 2019-01-07 21:57:45 +0000 | |
| commit | 259e7840ffff64aed94fa07ac68dbbe8f96de0f7 (patch) | |
| tree | e4125a23c6ab431b440b3237cd3e5121a25da52b | |
| parent | 72efe39d7db7eb05d8cf5da6c642636ba02b3396 (diff) | |
| parent | 5e1c1caabf17cbfab7b39d3a82a6a2fc65e87318 (diff) | |
Merge "Fixed bug where certain focusable windows are reported to accessibility out of z order."
| -rw-r--r-- | services/core/java/com/android/server/wm/AccessibilityController.java | 155 |
1 files changed, 74 insertions, 81 deletions
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index fe0b5c250da8..caebf1528270 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 class AccessibilityController { final int visibleWindowCount = visibleWindows.size(); HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>(); - for (int i = visibleWindowCount - 1; i >= 0; 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; - } + // 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); - // 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 @@ final class AccessibilityController { 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; |