Loading services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +42 −20 Original line number Diff line number Diff line Loading @@ -443,7 +443,10 @@ public class AccessibilityWindowManager { public void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId, IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows) { synchronized (mLock) { if (!Flags.computeWindowChangesOnA11y()) { // If the flag is enabled, it's already done in #createWindowInfoListLocked. updateWindowsByWindowAttributesLocked(windows); } if (DEBUG) { Slogf.i(LOG_TAG, "mDisplayId=%d, topFocusedDisplayId=%d, currentUserId=%d, " + "visibleBgUsers=%s", mDisplayId, topFocusedDisplayId, Loading Loading @@ -500,14 +503,15 @@ public class AccessibilityWindowManager { public void onAccessibilityWindowsChanged(boolean forceSend, int topFocusedDisplayId, @NonNull IBinder topFocusedWindowToken, @NonNull Point screenSize, @NonNull List<AccessibilityWindow> windows) { // TODO(b/322444245): Get a screenSize from DisplayManager#getDisplay(int) // .getRealSize(). final List<WindowInfo> windowInfoList = createWindowInfoList(screenSize, windows); synchronized (mLock) { final List<WindowInfo> windowInfoList = createWindowInfoListLocked(screenSize, windows); onWindowsForAccessibilityChanged(forceSend, topFocusedDisplayId, topFocusedWindowToken, windowInfoList); } } private static List<WindowInfo> createWindowInfoList(@NonNull Point screenSize, private List<WindowInfo> createWindowInfoListLocked(@NonNull Point screenSize, @NonNull List<AccessibilityWindow> visibleWindows) { final Set<IBinder> addedWindows = new ArraySet<>(); final List<WindowInfo> windows = new ArrayList<>(); Loading @@ -516,19 +520,28 @@ public class AccessibilityWindowManager { final Region regionInWindow = new Region(); final Region touchableRegionInScreen = new Region(); final int userId = mAccessibilityUserManager.getCurrentUserIdLocked(); // Iterate until we figure out what is touchable for the entire screen. boolean focusedWindowAdded = false; final Region unaccountedSpace = new Region(0, 0, screenSize.x, screenSize.y); for (final AccessibilityWindow a11yWindow : visibleWindows) { a11yWindow.getTouchableRegionInWindow(regionInWindow); if (windowMattersToAccessibility(a11yWindow, regionInWindow, unaccountedSpace)) { final WindowInfo window = a11yWindow.getWindowInfo(); if (window.token != null) { final int windowId = window.token != null ? findWindowIdLocked(userId, window.token) : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; if (windowMattersToAccessibilityLocked(a11yWindow, windowId, regionInWindow, unaccountedSpace)) { if (windowId >= 0) { // Even if token is null, the window will be used in calculating visible // windows, but is excluded from the accessibility window list. // TODO(b/322444245): We can call #updateWindowWithWindowAttributes() here. window.regionInScreen.set(regionInWindow); window.layer = addedWindows.size(); updateWindowWithWindowAttributes(window, mWindowAttributes.get(windowId)); windows.add(window); addedWindows.add(window.token); } Loading Loading @@ -577,8 +590,8 @@ public class AccessibilityWindowManager { return windows; } private static boolean windowMattersToAccessibility(AccessibilityWindow a11yWindow, Region regionInScreen, Region unaccountedSpace) { private boolean windowMattersToAccessibilityLocked(AccessibilityWindow a11yWindow, int windowId, Region regionInScreen, Region unaccountedSpace) { if (a11yWindow.ignoreRecentsAnimationForAccessibility()) { return false; } Loading @@ -595,6 +608,10 @@ public class AccessibilityWindowManager { return false; } if (isEmbeddedHierarchyWindowsLocked(windowId)) { return false; } // If the window is completely covered by other windows - ignore. if (unaccountedSpace.quickReject(regionInScreen)) { return false; Loading Loading @@ -975,14 +992,19 @@ public class AccessibilityWindowManager { private AccessibilityWindowInfo populateReportedWindowLocked(int userId, WindowInfo window, SparseArray<AccessibilityWindowInfo> oldWindowsById) { final int windowId = findWindowIdLocked(userId, window.token); // With the flag enabled, createWindowInfoListLocked() already removes invalid windows. if (!Flags.computeWindowChangesOnA11y()) { if (windowId < 0) { return null; } // Don't need to add the embedded hierarchy windows into the accessibility windows list. // Don't need to add the embedded hierarchy windows into the a11y windows list. if (isEmbeddedHierarchyWindowsLocked(windowId)) { return null; } } final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); reportedWindow.setId(windowId); Loading Loading @@ -1601,7 +1623,7 @@ public class AccessibilityWindowManager { return getWindowTokensForUserLocked(userId).keyAt(userIndex); } } return -1; return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; } /** Loading services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.os.IBinder; import android.os.LocaleList; Loading Loading @@ -433,6 +434,41 @@ public class AccessibilityWindowManagerWithAccessibilityWindowTest { assertThat(a11yWindows.get(1), windowId(focusedWindowId)); } @Test public void onWindowsChanged_embeddedWindows_shouldOnlyReportHost() throws RemoteException { final Rect embeddingBounds = new Rect(0, 0, 200, 100); // The embedded window comes front of the host window. final IBinder embeddedWindowLeashToken = Mockito.mock(IBinder.class); final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, false, embeddedWindowLeashToken, USER_SYSTEM_ID); final AccessibilityWindow embeddedWindow = createMockAccessibilityWindow( mA11yWindowTokens.get(embeddedWindowId), Display.DEFAULT_DISPLAY); setRegionForMockAccessibilityWindow(embeddedWindow, new Region(embeddingBounds)); mWindows.get(Display.DEFAULT_DISPLAY).set(0, embeddedWindow); final IBinder hostWindowLeashToken = Mockito.mock(IBinder.class); final int hostWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, false, hostWindowLeashToken, USER_SYSTEM_ID); final AccessibilityWindow hostWindow = createMockAccessibilityWindow( mA11yWindowTokens.get(hostWindowId), Display.DEFAULT_DISPLAY); setRegionForMockAccessibilityWindow(hostWindow, new Region(embeddingBounds)); mWindows.get(Display.DEFAULT_DISPLAY).set(1, hostWindow); mA11yWindowManager.associateEmbeddedHierarchyLocked( hostWindowLeashToken, embeddedWindowLeashToken); onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); assertThat(a11yWindows, not(hasItem(windowId(embeddedWindowId)))); assertThat(a11yWindows.get(0), windowId(hostWindowId)); final Rect bounds = new Rect(); a11yWindows.get(0).getBoundsInScreen(bounds); assertEquals(bounds, embeddingBounds); } @Test public void onWindowsChangedAndForceSend_shouldUpdateWindows() { assertNotEquals("new title", Loading Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +42 −20 Original line number Diff line number Diff line Loading @@ -443,7 +443,10 @@ public class AccessibilityWindowManager { public void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId, IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows) { synchronized (mLock) { if (!Flags.computeWindowChangesOnA11y()) { // If the flag is enabled, it's already done in #createWindowInfoListLocked. updateWindowsByWindowAttributesLocked(windows); } if (DEBUG) { Slogf.i(LOG_TAG, "mDisplayId=%d, topFocusedDisplayId=%d, currentUserId=%d, " + "visibleBgUsers=%s", mDisplayId, topFocusedDisplayId, Loading Loading @@ -500,14 +503,15 @@ public class AccessibilityWindowManager { public void onAccessibilityWindowsChanged(boolean forceSend, int topFocusedDisplayId, @NonNull IBinder topFocusedWindowToken, @NonNull Point screenSize, @NonNull List<AccessibilityWindow> windows) { // TODO(b/322444245): Get a screenSize from DisplayManager#getDisplay(int) // .getRealSize(). final List<WindowInfo> windowInfoList = createWindowInfoList(screenSize, windows); synchronized (mLock) { final List<WindowInfo> windowInfoList = createWindowInfoListLocked(screenSize, windows); onWindowsForAccessibilityChanged(forceSend, topFocusedDisplayId, topFocusedWindowToken, windowInfoList); } } private static List<WindowInfo> createWindowInfoList(@NonNull Point screenSize, private List<WindowInfo> createWindowInfoListLocked(@NonNull Point screenSize, @NonNull List<AccessibilityWindow> visibleWindows) { final Set<IBinder> addedWindows = new ArraySet<>(); final List<WindowInfo> windows = new ArrayList<>(); Loading @@ -516,19 +520,28 @@ public class AccessibilityWindowManager { final Region regionInWindow = new Region(); final Region touchableRegionInScreen = new Region(); final int userId = mAccessibilityUserManager.getCurrentUserIdLocked(); // Iterate until we figure out what is touchable for the entire screen. boolean focusedWindowAdded = false; final Region unaccountedSpace = new Region(0, 0, screenSize.x, screenSize.y); for (final AccessibilityWindow a11yWindow : visibleWindows) { a11yWindow.getTouchableRegionInWindow(regionInWindow); if (windowMattersToAccessibility(a11yWindow, regionInWindow, unaccountedSpace)) { final WindowInfo window = a11yWindow.getWindowInfo(); if (window.token != null) { final int windowId = window.token != null ? findWindowIdLocked(userId, window.token) : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; if (windowMattersToAccessibilityLocked(a11yWindow, windowId, regionInWindow, unaccountedSpace)) { if (windowId >= 0) { // Even if token is null, the window will be used in calculating visible // windows, but is excluded from the accessibility window list. // TODO(b/322444245): We can call #updateWindowWithWindowAttributes() here. window.regionInScreen.set(regionInWindow); window.layer = addedWindows.size(); updateWindowWithWindowAttributes(window, mWindowAttributes.get(windowId)); windows.add(window); addedWindows.add(window.token); } Loading Loading @@ -577,8 +590,8 @@ public class AccessibilityWindowManager { return windows; } private static boolean windowMattersToAccessibility(AccessibilityWindow a11yWindow, Region regionInScreen, Region unaccountedSpace) { private boolean windowMattersToAccessibilityLocked(AccessibilityWindow a11yWindow, int windowId, Region regionInScreen, Region unaccountedSpace) { if (a11yWindow.ignoreRecentsAnimationForAccessibility()) { return false; } Loading @@ -595,6 +608,10 @@ public class AccessibilityWindowManager { return false; } if (isEmbeddedHierarchyWindowsLocked(windowId)) { return false; } // If the window is completely covered by other windows - ignore. if (unaccountedSpace.quickReject(regionInScreen)) { return false; Loading Loading @@ -975,14 +992,19 @@ public class AccessibilityWindowManager { private AccessibilityWindowInfo populateReportedWindowLocked(int userId, WindowInfo window, SparseArray<AccessibilityWindowInfo> oldWindowsById) { final int windowId = findWindowIdLocked(userId, window.token); // With the flag enabled, createWindowInfoListLocked() already removes invalid windows. if (!Flags.computeWindowChangesOnA11y()) { if (windowId < 0) { return null; } // Don't need to add the embedded hierarchy windows into the accessibility windows list. // Don't need to add the embedded hierarchy windows into the a11y windows list. if (isEmbeddedHierarchyWindowsLocked(windowId)) { return null; } } final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); reportedWindow.setId(windowId); Loading Loading @@ -1601,7 +1623,7 @@ public class AccessibilityWindowManager { return getWindowTokensForUserLocked(userId).keyAt(userIndex); } } return -1; return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; } /** Loading
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.os.IBinder; import android.os.LocaleList; Loading Loading @@ -433,6 +434,41 @@ public class AccessibilityWindowManagerWithAccessibilityWindowTest { assertThat(a11yWindows.get(1), windowId(focusedWindowId)); } @Test public void onWindowsChanged_embeddedWindows_shouldOnlyReportHost() throws RemoteException { final Rect embeddingBounds = new Rect(0, 0, 200, 100); // The embedded window comes front of the host window. final IBinder embeddedWindowLeashToken = Mockito.mock(IBinder.class); final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, false, embeddedWindowLeashToken, USER_SYSTEM_ID); final AccessibilityWindow embeddedWindow = createMockAccessibilityWindow( mA11yWindowTokens.get(embeddedWindowId), Display.DEFAULT_DISPLAY); setRegionForMockAccessibilityWindow(embeddedWindow, new Region(embeddingBounds)); mWindows.get(Display.DEFAULT_DISPLAY).set(0, embeddedWindow); final IBinder hostWindowLeashToken = Mockito.mock(IBinder.class); final int hostWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, false, hostWindowLeashToken, USER_SYSTEM_ID); final AccessibilityWindow hostWindow = createMockAccessibilityWindow( mA11yWindowTokens.get(hostWindowId), Display.DEFAULT_DISPLAY); setRegionForMockAccessibilityWindow(hostWindow, new Region(embeddingBounds)); mWindows.get(Display.DEFAULT_DISPLAY).set(1, hostWindow); mA11yWindowManager.associateEmbeddedHierarchyLocked( hostWindowLeashToken, embeddedWindowLeashToken); onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); assertThat(a11yWindows, not(hasItem(windowId(embeddedWindowId)))); assertThat(a11yWindows.get(0), windowId(hostWindowId)); final Rect bounds = new Rect(); a11yWindows.get(0).getBoundsInScreen(bounds); assertEquals(bounds, embeddingBounds); } @Test public void onWindowsChangedAndForceSend_shouldUpdateWindows() { assertNotEquals("new title", Loading