From 7bc66be81a87f3bf55f070597a0ba4be08a3b956 Mon Sep 17 00:00:00 2001 From: Taran Singh Date: Fri, 12 Mar 2021 18:24:37 +0000 Subject: [PATCH] Hide IME after re-parenting IME container to DisplayArea When IME is reparented to new DisplayAreaGoup, its surface is set visible again. In order to prevent it fom flashing, it should be explicitly hidden. IME will reappear with animation once its attached to new app in new DisplayArea Bug: 174533580 Test: Manually using steps in bug atest DualDisplayAreaGroupPolicyTest Change-Id: Icfe3ca6334a400f3241d67b3f5a8f5b08958919c --- .../com/android/server/wm/DisplayContent.java | 7 +++- .../android/server/wm/RootDisplayArea.java | 4 --- .../server/wm/DisplayContentTests.java | 15 -------- .../wm/DualDisplayAreaGroupPolicyTest.java | 35 +++++++++++++++++++ 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c78f9ec215161..b89081bfce9fc 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3686,10 +3686,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // config. (Only happens when the target window is in a different root DA) if (target != null) { RootDisplayArea targetRoot = target.getRootDisplayArea(); - if (targetRoot != null) { + if (targetRoot != null && targetRoot != mImeWindowsContainer.getRootDisplayArea()) { // Reposition the IME container to the target root to get the correct bounds and // config. targetRoot.placeImeContainer(mImeWindowsContainer); + // Directly hide the IME window so it doesn't flash immediately after reparenting. + // InsetsController will make IME visible again before animating it. + if (mInputMethodWindow != null) { + mInputMethodWindow.hide(false /* doAnimation */, false /* requestAnim */); + } } } // 2. Assign window layers based on the IME surface parent to make sure it is on top of the diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java index 505af05ed642f..cd20c8242d81b 100644 --- a/services/core/java/com/android/server/wm/RootDisplayArea.java +++ b/services/core/java/com/android/server/wm/RootDisplayArea.java @@ -79,10 +79,6 @@ class RootDisplayArea extends DisplayArea { */ void placeImeContainer(DisplayArea.Tokens imeContainer) { final RootDisplayArea previousRoot = imeContainer.getRootDisplayArea(); - if (previousRoot == this) { - // No need to reparent if IME container is below the same root. - return; - } List features = mFeatures; for (int i = 0; i < features.size(); i++) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 67fe7bf436b7c..2d79d112e5d1a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -328,21 +328,6 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(startingWin, imeTarget); } - @UseTestDisplay(addAllCommonWindows = true) - @Test - public void testComputeImeTarget_placeImeToTheTargetRoot() { - ActivityRecord activity = createActivityRecord(mDisplayContent); - - final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity, - "startingWin"); - startingWin.setHasSurface(true); - assertTrue(startingWin.canBeImeTarget()); - DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); - - WindowState imeTarget = mDisplayContent.computeImeTarget(true /* updateImeTarget */); - verify(imeTarget.getRootDisplayArea()).placeImeContainer(imeContainer); - } - @Test public void testUpdateImeParent_forceUpdateRelativeLayer() { final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java index e9c356d6c6c40..e9907c1fd1a51 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java @@ -310,6 +310,41 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { assertThat(mSecondRoot.findAreaForToken(imeToken)).isEqualTo(imeContainer); } + @Test + public void testPlaceImeContainer_hidesImeWhenParentChanges() { + setupImeWindow(); + final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer(); + final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD); + final WindowState firstActivityWin = + createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity, + "firstActivityWin"); + spyOn(firstActivityWin); + final WindowState secondActivityWin = + createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mSecondActivity, + "secondActivityWin"); + spyOn(secondActivityWin); + + // firstActivityWin should be the target + doReturn(true).when(firstActivityWin).canBeImeTarget(); + doReturn(false).when(secondActivityWin).canBeImeTarget(); + + WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */); + assertThat(imeTarget).isEqualTo(firstActivityWin); + verify(mFirstRoot).placeImeContainer(imeContainer); + + // secondActivityWin should be the target + doReturn(false).when(firstActivityWin).canBeImeTarget(); + doReturn(true).when(secondActivityWin).canBeImeTarget(); + + spyOn(mDisplay.mInputMethodWindow); + imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */); + + assertThat(imeTarget).isEqualTo(secondActivityWin); + verify(mSecondRoot).placeImeContainer(imeContainer); + // verify hide() was called on InputMethodWindow. + verify(mDisplay.mInputMethodWindow).hide(false /* doAnimation */, false /* requestAnim */); + } + @Test public void testResizableFixedOrientationApp_fixedOrientationLetterboxing() { mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);