diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 9d630293c82da..785ca908b7033 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -45,6 +45,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.util.ArraySet; +import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; @@ -128,14 +129,13 @@ final class AccessibilityController { */ public boolean setWindowsForAccessibilityCallbackLocked(int displayId, WindowsForAccessibilityCallback callback) { - if (callback != null) { - final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId); - if (dc == null) { - return false; - } + final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId); + if (dc == null) { + return false; + } - final Display display = dc.getDisplay(); - if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) { + if (callback != null) { + if (isEmbeddedDisplay(dc)) { // If this display is an embedded one, its window observer should have been set from // window manager after setting its parent window. But if its window observer is // empty, that means this mapping didn't be set, and needs to do this again. @@ -152,13 +152,22 @@ final class AccessibilityController { mWindowsForAccessibilityObserver.put(displayId, new WindowsForAccessibilityObserver(mService, displayId, callback)); } else { + if (isEmbeddedDisplay(dc)) { + // If this display is an embedded one, its window observer should be removed along + // with the window observer of its parent display removed because the window + // observer of the embedded display and its parent display is the same, and would + // be removed together when stopping the window tracking of its parent display. So + // here don't need to do removing window observer of the embedded display again. + return true; + } final WindowsForAccessibilityObserver windowsForA11yObserver = mWindowsForAccessibilityObserver.get(displayId); - if (windowsForA11yObserver == null) { + if (windowsForA11yObserver == null) { throw new IllegalStateException( "Windows for accessibility callback of display " + displayId + " already cleared!"); } + removeObserverOfEmbeddedDisplay(windowsForA11yObserver); mWindowsForAccessibilityObserver.remove(displayId); } return true; @@ -332,6 +341,7 @@ final class AccessibilityController { mWindowsForAccessibilityObserver.get(parentDisplayId); if (windowsForA11yObserver != null) { + windowsForA11yObserver.addEmbeddedDisplay(embeddedDisplayId); // Replaces the observer of embedded display to the one of parent display mWindowsForAccessibilityObserver.put(embeddedDisplayId, windowsForA11yObserver); } @@ -352,6 +362,23 @@ final class AccessibilityController { } } + private void removeObserverOfEmbeddedDisplay(WindowsForAccessibilityObserver + observerOfParentDisplay) { + final IntArray embeddedDisplayIdList = + observerOfParentDisplay.getAndClearEmbeddedDisplayIdList(); + + for (int index = 0; index < embeddedDisplayIdList.size(); index++) { + final int embeddedDisplayId = embeddedDisplayIdList.get(index); + mWindowsForAccessibilityObserver.remove(embeddedDisplayId); + } + } + + private static boolean isEmbeddedDisplay(DisplayContent dc) { + final Display display = dc.getDisplay(); + + return display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null; + } + /** * This class encapsulates the functionality related to display magnification. */ @@ -1179,6 +1206,8 @@ final class AccessibilityController { private final long mRecurringAccessibilityEventsIntervalMillis; + private final IntArray mEmbeddedDisplayIdList = new IntArray(0); + public WindowsForAccessibilityObserver(WindowManagerService windowManagerService, int displayId, WindowsForAccessibilityCallback callback) { @@ -1203,6 +1232,21 @@ final class AccessibilityController { } } + IntArray getAndClearEmbeddedDisplayIdList() { + final IntArray returnedArray = new IntArray(mEmbeddedDisplayIdList.size()); + returnedArray.addAll(mEmbeddedDisplayIdList); + mEmbeddedDisplayIdList.clear(); + + return returnedArray; + } + + void addEmbeddedDisplay(int displayId) { + if (displayId == mDisplayId) { + return; + } + mEmbeddedDisplayIdList.add(displayId); + } + /** * Check if windows have changed, and send them to the accessibility subsystem if they have. *