From d438917585af3d10562c46859f110ac43718a7b8 Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Fri, 1 Oct 2021 01:43:51 +0800 Subject: [PATCH] Fix IME aboves popupwindow when the app is in split-screen As now the new split-screen system has been migated to wmShell with using WINDOWING_MODE_MULTI_WINDOW to setup the split task. so inSplitScreenWindowingMode() will no longer be true since this method is used for legacy split-screen. It affects WindowState#needsRelativeLayeringToIme can not check if the app is in split-screen window and makes system can't set relative layering to IME for popupWindow to make it above IME. Note that setting relative layering with IME also benefits for other non-fullscreen windowing mode like in bubble/freeform mode, the dropdown menu can above the IME when the parent window is IME layering target. Changing to use DC#isImeAttachedToApp() to fix this layering issue. Fix: 201504527 Test: atest ZOrderingTest#\ testPopupWindowAndParentIsImeTarget_expectHigherThanIme_inMultiWindow Test: manual as issue steps 1) Go to "Create contact" in Phone. 2) Enter split-screen mode. 3) Click on a text box of "Create contact". 4) Click the menu button to show the menu of "Create contact". 5) Expect the layer of the menu should above the IME surface. Change-Id: I2f466a2305e56e4fd2a0c509d7c8027104cb51b6 --- .../com/android/server/wm/WindowState.java | 8 +++--- .../android/server/wm/WindowStateTests.java | 7 +++--- .../com/android/server/wm/ZOrderingTests.java | 25 +++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 22db2975ef41a..76bd58a9131b3 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5662,9 +5662,11 @@ class WindowState extends WindowContainer implements WindowManagerP } boolean needsRelativeLayeringToIme() { - // We only use the relative layering mode in split screen, as part of elevating the IME - // and windows above it's target above the docked divider. - if (!inSplitScreenWindowingMode()) { + // We use the relative layering when IME isn't attached to the app. Such as part of + // elevating the IME and windows above it's target above the docked divider in + // split-screen, or make the popupMenu to be above the IME when the parent window is the + // IME layering target in bubble/freeform mode. + if (mDisplayContent.isImeAttachedToApp()) { return false; } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index b17ea5e48db5d..e6ad68aafaecf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.view.InsetsState.ITYPE_IME; @@ -835,8 +836,7 @@ public class WindowStateTests extends WindowTestsBase { WindowState sameTokenWindow = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken, "SameTokenWindow"); mDisplayContent.setImeLayeringTarget(mAppWindow); - sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); assertTrue(sameTokenWindow.needsRelativeLayeringToIme()); sameTokenWindow.removeImmediately(); assertFalse(sameTokenWindow.needsRelativeLayeringToIme()); @@ -848,8 +848,7 @@ public class WindowStateTests extends WindowTestsBase { WindowState sameTokenWindow = createWindow(null, TYPE_APPLICATION_STARTING, mAppWindow.mToken, "SameTokenWindow"); mDisplayContent.setImeLayeringTarget(mAppWindow); - sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); assertFalse(sameTokenWindow.needsRelativeLayeringToIme()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java index d967891fdb76e..22ea3d5be71b3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; @@ -37,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER; import static com.google.common.truth.Truth.assertThat; @@ -493,4 +495,27 @@ public class ZOrderingTests extends WindowTestsBase { assertZOrderGreaterThan(mTransaction, mNavBarWindow.mToken.getSurfaceControl(), mDisplayContent.getImeContainer().getSurfaceControl()); } + + @Test + public void testPopupWindowAndParentIsImeTarget_expectHigherThanIme_inMultiWindow() { + // Simulate the app window is in multi windowing mode and being IME target + mAppWindow.getConfiguration().windowConfiguration.setWindowingMode( + WINDOWING_MODE_MULTI_WINDOW); + mDisplayContent.setImeLayeringTarget(mAppWindow); + mDisplayContent.setImeInputTarget(mAppWindow); + + // Create a popupWindow + assertWindowHigher(mImeWindow, mAppWindow); + final WindowState popupWindow = createWindow(mAppWindow, TYPE_APPLICATION_PANEL, + mDisplayContent, "PopupWindow"); + spyOn(popupWindow); + + mDisplayContent.assignChildLayers(mTransaction); + + // Verify the surface layer of the popupWindow should higher than IME + verify(popupWindow).needsRelativeLayeringToIme(); + assertThat(popupWindow.needsRelativeLayeringToIme()).isTrue(); + assertZOrderGreaterThan(mTransaction, popupWindow.getSurfaceControl(), + mDisplayContent.getImeContainer().getSurfaceControl()); + } }