Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87ad3578 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Id4b24284,I32514c70 into main

* changes:
  Exclude unnecessary window early in DisplayWindowsObserver
  Update window info by attributes in an earlier stage
parents e1ee2666 df8ad207
Loading
Loading
Loading
Loading
+42 −20
Original line number Diff line number Diff line
@@ -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,
@@ -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<>();
@@ -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);
                    }
@@ -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;
            }
@@ -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;
@@ -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);
@@ -1601,7 +1623,7 @@ public class AccessibilityWindowManager {
                return getWindowTokensForUserLocked(userId).keyAt(userIndex);
            }
        }
        return -1;
        return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
    }

    /**
+36 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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",