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

Commit 96ceaf62 authored by ryanlwlin's avatar ryanlwlin Committed by Jacky Kao
Browse files

Use shellRoot to identify PIP menu window

Pip menu is an untouchable window which is exculded
from accessibility windows list. However it is touchable
when users touch in the pip mode window.

To fix it, we add this window to visible windows
list by comparing the window token.

Bug: 191736824
Test: a11y CTS & unit tests
Change-Id: I0ac0d0487d0bec9ef04a2ba5770ba499d5125b11
parent c6245d13
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1645,10 +1645,11 @@ final class AccessibilityController {

            // Ignore non-touchable windows, except the split-screen divider, which is
            // occasionally non-touchable but still useful for identifying split-screen
            // mode.
            // mode and the PIP menu.
            if (((a11yWindow.getFlags()
                    & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
                    && (a11yWindow.getType() != TYPE_DOCK_DIVIDER)) {
                    && (a11yWindow.getType() != TYPE_DOCK_DIVIDER
                    && !a11yWindow.isPIPMenu())) {
                return false;
            }

+21 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Slog;
@@ -104,9 +105,14 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
            inverseMatrix.set(mMagnificationSpecInverseMatrix.get(displayId));
        }

        final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
        final ShellRoot shellroot = dc.mShellRoots.get(WindowManager.SHELL_ROOT_LAYER_PIP);
        final IBinder pipMenuIBinder =
                shellroot != null ? shellroot.getAccessibilityWindowToken() : null;
        for (final InputWindowHandle windowHandle : inputWindowHandles) {
            final AccessibilityWindow accessibilityWindow =
                    AccessibilityWindow.initializeData(mService, windowHandle, inverseMatrix);
                    AccessibilityWindow.initializeData(mService, windowHandle, inverseMatrix,
                            pipMenuIBinder);

            outWindows.add(accessibilityWindow);
        }
@@ -334,6 +340,7 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
        private int mFlags;
        private int mType;
        private int mPrivateFlags;
        private boolean mIsPIPMenu;
        private boolean mIsFocused;
        private boolean mShouldMagnify;
        private boolean mIgnoreDuetoRecentsAnimation;
@@ -350,7 +357,7 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
         * @param inverseMatrix The magnification spec inverse matrix.
         */
        public static AccessibilityWindow initializeData(WindowManagerService service,
                InputWindowHandle inputWindowHandle, Matrix inverseMatrix) {
                InputWindowHandle inputWindowHandle, Matrix inverseMatrix, IBinder pipIBinder) {
            final IWindow window = inputWindowHandle.getWindow();
            final WindowState windowState = window != null ? service.mWindowMap.get(
                    window.asBinder()) : null;
@@ -361,6 +368,7 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
            instance.mDisplayId = inputWindowHandle.displayId;
            instance.mFlags = inputWindowHandle.layoutParamsFlags;
            instance.mType = inputWindowHandle.layoutParamsType;
            instance.mIsPIPMenu = inputWindowHandle.getWindow().asBinder().equals(pipIBinder);

            // TODO (b/199357848): gets the private flag of the window from other way.
            instance.mPrivateFlags = windowState != null ? windowState.mAttrs.privateFlags : 0;
@@ -491,6 +499,13 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
            return mTouchableRegionInScreen.isEmpty();
        }

        /**
         * @return true if this window is PIP menu.
         */
        public boolean isPIPMenu() {
            return mIsPIPMenu;
        }

        private static void getTouchableRegionInWindow(boolean shouldMagnify, Region inRegion,
                Region outRegion, Rect frame, Matrix inverseMatrix) {
            // Some modal windows, like the activity with Theme.dialog, has the full screen
@@ -547,10 +562,9 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
            // one is PIP.
            if (windowInfo.type == TYPE_DOCK_DIVIDER) {
                windowInfo.title = "Splitscreen Divider";
            } else {
            } else if (window.mIsPIPMenu) {
                windowInfo.title = "Picture-in-Picture menu";
            }

            return windowInfo;
        }

@@ -565,18 +579,19 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {

        @Override
        public String toString() {
            String builder = "A11yWindow=[" + mWindow
            String builder = "A11yWindow=[" + mWindow.asBinder()
                    + ", displayId=" + mDisplayId
                    + ", flag=0x" + Integer.toHexString(mFlags)
                    + ", type=" + mType
                    + ", privateFlag=0x" + Integer.toHexString(mPrivateFlags)
                    + ", focused=" + mIsFocused
                    + ", magnify=" + mShouldMagnify
                    + ", mShouldMagnify=" + mShouldMagnify
                    + ", ignoreDuetoRecentsAnimation=" + mIgnoreDuetoRecentsAnimation
                    + ", mIsTrustedOverlay=" + mIsTrustedOverlay
                    + ", regionInScreen=" + mTouchableRegionInScreen
                    + ", touchableRegion=" + mTouchableRegionInWindow
                    + ", letterBoxBounds=" + mLetterBoxBounds
                    + ", isPIPMenu=" + mIsPIPMenu
                    + ", windowInfo=" + mWindowInfo
                    + "]";

+6 −42
Original line number Diff line number Diff line
@@ -25,15 +25,14 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMAT
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.IWindow;
import android.view.SurfaceControl;
import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.animation.Animation;

@@ -136,48 +135,13 @@ public class ShellRoot {
                ANIMATION_TYPE_WINDOW_ANIMATION);
    }

    WindowInfo getWindowInfo() {
        if (mShellRootLayer != SHELL_ROOT_LAYER_DIVIDER
                && mShellRootLayer != SHELL_ROOT_LAYER_PIP) {
            return null;
        }
        if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER
                && !mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
            return null;
        }
        if (mShellRootLayer == SHELL_ROOT_LAYER_PIP
                && mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask() == null) {
            return null;
    @Nullable
    IBinder getAccessibilityWindowToken() {
        if (mAccessibilityWindow != null) {
            return mAccessibilityWindow.asBinder();
        }
        if (mAccessibilityWindow == null) {
        return null;
    }
        WindowInfo windowInfo = WindowInfo.obtain();
        windowInfo.displayId = mToken.getDisplayArea().getDisplayContent().mDisplayId;
        windowInfo.type = mToken.windowType;
        windowInfo.layer = mToken.getWindowLayerFromType();
        windowInfo.token = mAccessibilityWindow.asBinder();
        windowInfo.focused = false;
        windowInfo.hasFlagWatchOutsideTouch = false;
        final Rect regionRect = new Rect();


        // DividerView
        if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER) {
            windowInfo.inPictureInPicture = false;
            mDisplayContent.getDockedDividerController().getTouchRegion(regionRect);
            windowInfo.regionInScreen.set(regionRect);
            windowInfo.title = "Splitscreen Divider";
        }
        // PipMenuView
        if (mShellRootLayer == SHELL_ROOT_LAYER_PIP) {
            windowInfo.inPictureInPicture = true;
            mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask().getBounds(regionRect);
            windowInfo.regionInScreen.set(regionRect);
            windowInfo.title = "Picture-in-Picture menu";
        }
        return windowInfo;
    }

    void setAccessibilityWindow(IWindow window) {
        if (mAccessibilityWindow != null) {