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

Commit 81167407 authored by Jacky Kao's avatar Jacky Kao
Browse files

Supporting windows updated per display [Part III]

1. Getting all valid displays and starting or stopping the window
tracking when accessibility service enabled or disabled.
2. Updating the window tracking when any display is added or removed.
3. Making DisplayWindowsObserver class to be plural for multiple display.

Bug: 132854721
Test: a11y CTS & unit tests
Test: manually test talkback AP at second display
Change-Id: I1691f5c2092393a6ed396623e437e5d27e0cee9a
parent 204a7dd8
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -362,8 +362,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
            if (!permissionGranted) {
                return null;
            }
            // TODO [Multi-Display] (b/134891479) :
            // using correct display Id to replace DEFAULT_DISPLAY.
            List<AccessibilityWindowInfo> internalWindowList =
                    mA11yWindowManager.getWindowListLocked();
                    mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
            if (internalWindowList == null) {
                return null;
            }
@@ -1309,23 +1311,25 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
     */
    private void ensureWindowsAvailableTimed() {
        synchronized (mLock) {
            if (mA11yWindowManager.getWindowListLocked() != null) {
            // TODO [Multi-Display] (b/134891479) :
            // using correct display Id to replace DEFAULT_DISPLAY.
            if (mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) != null) {
                return;
            }
            // If we have no registered callback, update the state we
            // we may have to register one but it didn't happen yet.
            if (!mA11yWindowManager.isTrackingWindowsLocked()) {
            if (!mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) {
                // Invokes client change to make sure tracking window enabled.
                mSystemSupport.onClientChangeLocked(false);
            }
            // We have no windows but do not care about them, done.
            if (!mA11yWindowManager.isTrackingWindowsLocked()) {
            if (!mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) {
                return;
            }

            // Wait for the windows with a timeout.
            final long startMillis = SystemClock.uptimeMillis();
            while (mA11yWindowManager.getWindowListLocked() == null) {
            while (mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) == null) {
                final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
                final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
                if (remainMillis <= 0) {
+24 −8
Original line number Diff line number Diff line
@@ -272,9 +272,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        mSecurityPolicy = new AccessibilitySecurityPolicy(mContext, this);
        mMainHandler = new MainHandler(mContext.getMainLooper());
        mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
        mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
        mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
                mWindowManagerService, this, mSecurityPolicy, this);
        mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
        mSecurityPolicy.setAccessibilityWindowManager(mA11yWindowManager);

        registerBroadcastReceivers();
@@ -580,9 +580,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            // Make sure clients receiving this event will be able to get the
            // current state of the windows as the window manager may be delaying
            // the computation for performance reasons.
            // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
            // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY.
            boolean shouldComputeWindows = false;
            synchronized (mLock) {
                if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
                    && mA11yWindowManager.isTrackingWindowsLocked()) {
                        && mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) {
                    shouldComputeWindows = true;
                }
            }
            if (shouldComputeWindows) {
                WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
                wm.computeWindowsForAccessibility(Display.DEFAULT_DISPLAY);
            }
@@ -1656,10 +1662,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            }
        }

        // Gets all valid displays and start tracking windows of each display if there is at least
        // one bound service that can retrieve window content.
        final ArrayList<Display> displays = getValidDisplayList();
        for (int i = 0; i < displays.size(); i++) {
            final Display display = displays.get(i);
            if (display != null) {
                if (observingWindows) {
            mA11yWindowManager.startTrackingWindows();
                    mA11yWindowManager.startTrackingWindows(display.getDisplayId());
                } else {
            mA11yWindowManager.stopTrackingWindows();
                    mA11yWindowManager.stopTrackingWindows(display.getDisplayId());
                }
            }
        }
    }

@@ -2559,6 +2573,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                    }
                }
                updateMagnificationLocked(userState);
                updateWindowsForAccessibilityCallbackLocked(userState);
            }
        }

@@ -2586,6 +2601,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            if (mMagnificationController != null) {
                mMagnificationController.onDisplayRemoved(displayId);
            }
            mA11yWindowManager.stopTrackingWindows(displayId);
        }

        @Override
+210 −62

File changed.

Preview size limit exceeded, changes collapsed.

+16 −29
Original line number Diff line number Diff line
@@ -124,11 +124,11 @@ final class AccessibilityController {
                return false;
            }

            final Display display = dc.getDisplay();
            if (mWindowsForAccessibilityObserver.get(displayId) != null) {
                final Display display = dc.getDisplay();
                if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) {
                    // The window observer of this embedded display had been set from
                    // window manager after setting its parent window
                    // window manager after setting its parent window.
                    return true;
                } else {
                    throw new IllegalStateException(
@@ -136,9 +136,6 @@ final class AccessibilityController {
                                    + displayId + " already set!");
                }
            }
            if (display.getType() == Display.TYPE_OVERLAY) {
                return false;
            }
            mWindowsForAccessibilityObserver.put(displayId,
                    new WindowsForAccessibilityObserver(mService, displayId, callback));
        } else {
@@ -287,9 +284,8 @@ final class AccessibilityController {
    }

    public boolean hasCallbacksLocked() {
        // TODO: support multi-display for windows observer
        return (mDisplayMagnifiers.size() > 0
                || mWindowsForAccessibilityObserver != null);
                || mWindowsForAccessibilityObserver.size() > 0);
    }

    public void setForceShowMagnifiableBoundsLocked(int displayId, boolean show) {
@@ -1158,15 +1154,15 @@ final class AccessibilityController {
            }

            List<WindowInfo> windows = new ArrayList<>();
            final int topFocusedDisplayId;
            IBinder topFocusedWindowToken = null;

            synchronized (mService.mGlobalLock) {
                // Do not send the windows if there is no current focus as
                // Do not send the windows if there is no top focus as
                // the window manager is still looking for where to put it.
                // We will do the work when we get a focus change callback.
                // TODO [Multi-Display] : only checks top focused window
                if (!isCurrentFocusWindowOnDefaultDisplay()) {
                    return;
                }
                final WindowState topFocusedWindowState = getTopFocusWindow();
                if (topFocusedWindowState == null) return;

                final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
                if (dc == null) {
@@ -1229,9 +1225,13 @@ final class AccessibilityController {

                visibleWindows.clear();
                addedWindows.clear();
            }

            mCallback.onWindowsForAccessibilityChanged(forceSend, windows);
                // Gets the top focused display Id and window token for supporting multi-display.
                topFocusedDisplayId = mService.mRoot.getTopFocusedDisplayContent().getDisplayId();
                topFocusedWindowToken = topFocusedWindowState.mClient.asBinder();
            }
            mCallback.onWindowsForAccessibilityChanged(forceSend, topFocusedDisplayId,
                    topFocusedWindowToken, windows);

            // Recycle the windows as we do not need them.
            clearAndRecycleWindows(windows);
@@ -1410,22 +1410,9 @@ final class AccessibilityController {
            }
            return displayParentWindow;
        }
        // TODO [Multi-Display] : only checks top focused window
        private boolean isCurrentFocusWindowOnDefaultDisplay() {
            final WindowState focusedWindow =
                    mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
            if (focusedWindow == null) {
                return false;
            }

            final WindowState rootDisplayParentWindow = findRootDisplayParentWindow(focusedWindow);
            if (!focusedWindow.isDefaultDisplay()
                    && (rootDisplayParentWindow == null
                    || !rootDisplayParentWindow.isDefaultDisplay())) {
                return false;
            }

            return true;
        private WindowState getTopFocusWindow() {
            return mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
        }

        private class MyHandler extends Handler {
+4 −1
Original line number Diff line number Diff line
@@ -52,9 +52,12 @@ public abstract class WindowManagerInternal {
         * Called when the windows for accessibility changed.
         *
         * @param forceSend Send the windows for accessibility even if they haven't changed.
         * @param topFocusedDisplayId The display Id which has the top focused window.
         * @param topFocusedWindowToken The window token of top focused window.
         * @param windows The windows for accessibility.
         */
        void onWindowsForAccessibilityChanged(boolean forceSend, List<WindowInfo> windows);
        void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId,
                IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows);
    }

    /**
Loading