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

Commit 6972b0ff authored by Jacky Kao's avatar Jacky Kao Committed by Android (Google) Code Review
Browse files

Merge "Improve the windows register and unregister mechanism"

parents 584424b1 5b8b7377
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -373,6 +373,20 @@ public class AccessibilityWindowManager {
            }
        }

        /**
         * Called when the display is reparented and becomes an embedded
         * display.
         *
         * @param embeddedDisplayId The embedded display Id.
         */
        @Override
        public void onDisplayReparented(int embeddedDisplayId) {
            // Removes the un-used window observer for the embedded display.
            synchronized (mLock) {
                mDisplayWindowsObservers.remove(embeddedDisplayId);
            }
        }

        private boolean shouldUpdateWindowsLocked(boolean forceSend,
                @NonNull List<WindowInfo> windows) {
            if (forceSend) {
+46 −29
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ import android.view.animation.Interpolator;
import com.android.internal.R;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.TraceBuffer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal;
@@ -172,11 +173,15 @@ final class AccessibilityController {

    /**
     * Sets a callback for observing which windows are touchable for the purposes
     * of accessibility on specified display.
     * of accessibility on specified display. When a display is reparented and becomes
     * an embedded one, the {@link WindowsForAccessibilityCallback#onDisplayReparented(int)}
     * will notify the accessibility framework to remove the un-used window observer of
     * this embedded display.
     *
     * @param displayId The logical display id.
     * @param callback The callback.
     * @return {@code false} if display id is not valid or an embedded display.
     * @return {@code false} if display id is not valid or an embedded display when the callback
     * isn't null.
     */
    boolean setWindowsForAccessibilityCallback(int displayId,
            WindowsForAccessibilityCallback callback) {
@@ -185,12 +190,13 @@ final class AccessibilityController {
                    TAG + ".setWindowsForAccessibilityCallback",
                    "displayId=" + displayId + "; callback={" + callback + "}");
        }

        if (callback != null) {
            final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
            if (dc == null) {
                return false;
            }

        if (callback != null) {
            WindowsForAccessibilityObserver observer =
                    mWindowsForAccessibilityObserver.get(displayId);
            if (isEmbeddedDisplay(dc)) {
@@ -209,21 +215,13 @@ final class AccessibilityController {
                if (Build.IS_DEBUGGABLE) {
                    throw new IllegalStateException(errorMessage);
                }
                removeObserverOfEmbeddedDisplay(observer);
                removeObserversForEmbeddedChildDisplays(observer);
                mWindowsForAccessibilityObserver.remove(displayId);
            }
            observer = new WindowsForAccessibilityObserver(mService, displayId, callback);
            mWindowsForAccessibilityObserver.put(displayId, observer);
            mAllObserversInitialized &= observer.mInitialized;
        } 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) {
@@ -234,7 +232,7 @@ final class AccessibilityController {
                    throw new IllegalStateException(errorMessage);
                }
            }
            removeObserverOfEmbeddedDisplay(windowsForA11yObserver);
            removeObserversForEmbeddedChildDisplays(windowsForA11yObserver);
            mWindowsForAccessibilityObserver.remove(displayId);
        }
        return true;
@@ -507,24 +505,36 @@ final class AccessibilityController {
        if (embeddedDisplayId == Display.DEFAULT_DISPLAY || parentWindow == null) {
            return;
        }
        mService.mH.sendMessage(PooledLambda.obtainMessage(
                AccessibilityController::updateWindowObserverOfEmbeddedDisplay,
                this, embeddedDisplayId, parentWindow));
    }

    private void updateWindowObserverOfEmbeddedDisplay(int embeddedDisplayId,
            WindowState parentWindow) {
        final WindowsForAccessibilityObserver windowsForA11yObserver;

        synchronized (mService.mGlobalLock) {
            // Finds the parent display of this embedded display
        final int parentDisplayId;
            WindowState candidate = parentWindow;
            while (candidate != null) {
                parentWindow = candidate;
                candidate = parentWindow.getDisplayContent().getParentWindow();
            }
        parentDisplayId = parentWindow.getDisplayId();
            final int parentDisplayId = parentWindow.getDisplayId();
            // Uses the observer of parent display
        final WindowsForAccessibilityObserver windowsForA11yObserver =
                mWindowsForAccessibilityObserver.get(parentDisplayId);
            windowsForA11yObserver = mWindowsForAccessibilityObserver.get(parentDisplayId);
        }

        if (windowsForA11yObserver != null) {
            windowsForA11yObserver.notifyDisplayReparented(embeddedDisplayId);
            windowsForA11yObserver.addEmbeddedDisplay(embeddedDisplayId);
            synchronized (mService.mGlobalLock) {
                // Replaces the observer of embedded display to the one of parent display
                mWindowsForAccessibilityObserver.put(embeddedDisplayId, windowsForA11yObserver);
            }
        }
    }

    void onImeSurfaceShownChanged(WindowState windowState, boolean shown) {
        if (mAccessibilityTracing.isEnabled()) {
@@ -555,7 +565,7 @@ final class AccessibilityController {
                + "mWindowsForAccessibilityObserver=" + mWindowsForAccessibilityObserver);
    }

    private void removeObserverOfEmbeddedDisplay(WindowsForAccessibilityObserver
    private void removeObserversForEmbeddedChildDisplays(WindowsForAccessibilityObserver
            observerOfParentDisplay) {
        final IntArray embeddedDisplayIdList =
                observerOfParentDisplay.getAndClearEmbeddedDisplayIdList();
@@ -1541,6 +1551,13 @@ final class AccessibilityController {
            mEmbeddedDisplayIdList.add(displayId);
        }

        void notifyDisplayReparented(int embeddedDisplayId) {
            // Notifies the A11y framework the display is reparented and
            // becomes an embedded display for removing the un-used
            // displayWindowObserver of this embedded one.
            mCallback.onDisplayReparented(embeddedDisplayId);
        }

        /**
         * Check if windows have changed, and send them to the accessibility subsystem if they have.
         *
+10 −0
Original line number Diff line number Diff line
@@ -115,6 +115,16 @@ public abstract class WindowManagerInternal {
         */
        void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId,
                IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows);

        /**
         * Called when the display is reparented and becomes an embedded
         * display. The {@link WindowsForAccessibilityCallback} with the given embedded
         * display will be replaced by the {@link WindowsForAccessibilityCallback}
         * associated with its parent display at the same time.
         *
         * @param embeddedDisplayId The embedded display Id.
         */
        void onDisplayReparented(int embeddedDisplayId);
    }

    /**
+13 −0
Original line number Diff line number Diff line
@@ -834,6 +834,19 @@ public class AccessibilityWindowManagerTest {
        assertNull(token);
    }

    @Test
    public void onDisplayReparented_shouldRemoveObserver() throws RemoteException {
        // Starts tracking window of second display.
        startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
        assertTrue(mA11yWindowManager.isTrackingWindowsLocked(SECONDARY_DISPLAY_ID));
        // Notifies the second display is an embedded one of the default display.
        final WindowsForAccessibilityCallback callbacks =
                mCallbackOfWindows.get(Display.DEFAULT_DISPLAY);
        callbacks.onDisplayReparented(SECONDARY_DISPLAY_ID);
        // Makes sure the observer of the second display is removed.
        assertFalse(mA11yWindowManager.isTrackingWindowsLocked(SECONDARY_DISPLAY_ID));
    }

    private void registerLeashedTokenAndWindowId() {
        mA11yWindowManager.registerIdLocked(mMockHostToken, HOST_WINDOW_ID);
        mA11yWindowManager.registerIdLocked(mMockEmbeddedToken, EMBEDDED_WINDOW_ID);