From 14a345124c4c5c1e8cc0fd82ebfe69bca45926c1 Mon Sep 17 00:00:00 2001 From: Jacky Kao Date: Thu, 16 Apr 2020 15:53:49 +0800 Subject: [PATCH] Fix CTS test case failure android.accessibilityservice.cts.AccessibilityEmbeddedDisplayTest# testA11yWindowNotifyWhenResizeWindowInActivityViewAfterServiceOffAndOn Removing the windowsForA11yObserver of embedded displays when removing the windowsForA11yObserver of its parent display because the windowsForA11yObserver is the same of them. Bug: 153342178 Test: a11y CTS & unit tests Test: atest --iterations 20 AccessibilityEmbeddedDisplayTest Change-Id: Idd21692cc599b565219e1cd3960d0cee3298e66b --- .../server/wm/AccessibilityController.java | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) 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. *