From 35433f34399ec97cbd955d7f3fea362828461f3e Mon Sep 17 00:00:00 2001 From: ryanlwlin Date: Mon, 22 Nov 2021 11:36:07 +0800 Subject: [PATCH] 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: I3d30d93bb92db467f37b7e659e2baea1a69cab16 --- .../server/wm/AccessibilityController.java | 5 +- .../wm/AccessibilityWindowsPopulator.java | 27 ++++++++--- .../java/com/android/server/wm/ShellRoot.java | 47 +++---------------- 3 files changed, 30 insertions(+), 49 deletions(-) diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 03abe8931e28c..8f703c5c77612 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -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; } diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java index cf1ff7713d707..246f9acf55bb8 100644 --- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java +++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java @@ -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); } @@ -335,6 +341,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; @@ -351,7 +358,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; @@ -362,6 +369,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; @@ -492,6 +500,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 @@ -548,10 +563,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; } @@ -566,18 +580,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 + "]"; diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java index 8ec9ef23a3f6b..f9d7b53e4e780 100644 --- a/services/core/java/com/android/server/wm/ShellRoot.java +++ b/services/core/java/com/android/server/wm/ShellRoot.java @@ -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,46 +135,12 @@ public class ShellRoot { ANIMATION_TYPE_WINDOW_ANIMATION); } - WindowInfo getWindowInfo() { - if (mShellRootLayer != SHELL_ROOT_LAYER_DIVIDER - && mShellRootLayer != SHELL_ROOT_LAYER_PIP) { - return null; + @Nullable + IBinder getAccessibilityWindowToken() { + if (mAccessibilityWindow != null) { + return mAccessibilityWindow.asBinder(); } - if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER) { - return null; - } - if (mShellRootLayer == SHELL_ROOT_LAYER_PIP - && mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask() == null) { - return null; - } - 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; + return null; } void setAccessibilityWindow(IWindow window) {