summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hiroki Sato <hirokisato@google.com> 2024-02-13 09:00:52 +0900
committer Hiroki Sato <hirokisato@google.com> 2024-03-18 00:10:46 +0000
commitdf8ad2073a9bd18c4b9833ead2e5678c76f12ea2 (patch)
tree557dd02e1819756e25e8e508ec915f07eb7965fc
parent959ba882f820ba9e78ac70d1ff654e326ef3507e (diff)
Exclude unnecessary window early in DisplayWindowsObserver
Previously, some windows are excluded from the final list of accessibility windows in populateReportedWindowLocked(). This is done after we compute touchable region to decide which windows are touchable and to be exposed. Thus, there are some corner cases where an unwanted window joins in touchable region computation and occludes an important window, resulting in missing window info. With this change, unnecessary windows are excluded when we compute touchable regions. This is a retry of abandoned CL [1] with a cleaner approach behind the computeWindowChangesOnA11y flag. [1] Iacff5b7e67a9e7e989671dc85ad884b0e9f2f2f0 Bug: 240885392 Bug: 254581919 Test: android.autofillservice.cts.servicebehavior.SettingsIntentTest Test: android.autofillservice.cts.inline.InlineTooltipTest Test: CtsAccessibilityServiceTestCases CtsAccessibilityTestCases AccessibilityWindowManagerWithAccessibilityWindowTest Change-Id: Id4b24284db40feaa744c9a5598d0067566fa3963
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java36
2 files changed, 63 insertions, 13 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 3a946f07f7b3..c570d65d8f57 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -527,14 +527,19 @@ public class AccessibilityWindowManager {
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 WindowInfo window = a11yWindow.getWindowInfo();
+ 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.
window.regionInScreen.set(regionInWindow);
window.layer = addedWindows.size();
- final int windowId = findWindowIdLocked(userId, window.token);
updateWindowWithWindowAttributes(window, mWindowAttributes.get(windowId));
windows.add(window);
@@ -585,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;
}
@@ -603,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;
@@ -983,14 +992,19 @@ public class AccessibilityWindowManager {
private AccessibilityWindowInfo populateReportedWindowLocked(int userId,
WindowInfo window, SparseArray<AccessibilityWindowInfo> oldWindowsById) {
final int windowId = findWindowIdLocked(userId, window.token);
- if (windowId < 0) {
- return null;
- }
- // Don't need to add the embedded hierarchy windows into the accessibility windows list.
- if (isEmbeddedHierarchyWindowsLocked(windowId)) {
- return null;
+ // 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 a11y windows list.
+ if (isEmbeddedHierarchyWindowsLocked(windowId)) {
+ return null;
+ }
}
+
final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
reportedWindow.setId(windowId);
@@ -1609,7 +1623,7 @@ public class AccessibilityWindowManager {
return getWindowTokensForUserLocked(userId).keyAt(userIndex);
}
}
- return -1;
+ return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java
index f6dc2f0f05b2..6e8d6dc3c120 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java
@@ -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;
@@ -434,6 +435,41 @@ public class AccessibilityWindowManagerWithAccessibilityWindowTest {
}
@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",
toString(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY)