From e27e307baaf033749ae301328379ea6cf6d46c59 Mon Sep 17 00:00:00 2001 From: Wilson Wu Date: Tue, 19 Apr 2022 18:06:28 +0800 Subject: [PATCH] Fix keyboard is attached to wrong task in split We introduced CL[1] to fix but it may cause a timing case that control target has already updated but the reparent in DC#updateImeParent is ignored because ImeLayeringTarget and ImeInputTarget are different. Also next updateImeParent won't be executed since the Ime control target didn't change. Attempt to fix this by force update the Ime parent if the control target is remote and the IME parent is not yet going to update to the remote one. [1]: I332c0e4fff62df5d7b793eda2767bb58fe85a938 Bug: 228791170 Test: Manual test Test: atest DisplayContentTests#testComputeImeParent_remoteControlTarget Change-Id: I834568231a8affbce55dc44c17fa0086f7999e35 --- .../com/android/server/wm/DisplayContent.java | 10 +++++++- .../server/wm/DisplayContentTests.java | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index dc441860f7c8d..2176db2971491 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4271,7 +4271,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp setImeInputTarget(target); mInsetsStateController.updateAboveInsetsState(mInsetsStateController .getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME)); - updateImeControlTarget(); + // Force updating the IME parent when the IME control target has been updated to the + // remote target but updateImeParent not happen because ImeLayeringTarget and + // ImeInputTarget are different. Then later updateImeParent would be ignored when there + // is no new IME control target to change the IME parent. + final boolean forceUpdateImeParent = mImeControlTarget == mRemoteInsetsControlTarget + && (mInputMethodSurfaceParent != null + && !mInputMethodSurfaceParent.isSameSurface( + mImeWindowsContainer.getParent().mSurfaceControl)); + updateImeControlTarget(forceUpdateImeParent); } // Unfreeze IME insets after the new target updated, in case updateAboveInsetsState may // deliver unrelated IME insets change to the non-IME requester. 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 32d201fafcfb6..8c1d0d720f20c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1167,6 +1167,31 @@ public class DisplayContentTests extends WindowTestsBase { assertNull(mDisplayContent.computeImeParent()); } + @Test + public void testComputeImeParent_remoteControlTarget() throws Exception { + final DisplayContent dc = mDisplayContent; + WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1"); + WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2"); + + dc.setImeLayeringTarget(app1); + dc.setImeInputTarget(app2); + dc.setRemoteInsetsController(createDisplayWindowInsetsController()); + dc.getImeTarget(IME_TARGET_LAYERING).getWindow().setWindowingMode( + WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); + dc.getImeInputTarget().getWindowState().setWindowingMode( + WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); + + // Expect ImeParent is null since ImeLayeringTarget and ImeInputTarget are different. + assertNull(dc.computeImeParent()); + + // ImeLayeringTarget and ImeInputTarget are updated to the same. + dc.setImeInputTarget(app1); + assertEquals(dc.getImeTarget(IME_TARGET_LAYERING), dc.getImeInputTarget()); + + // The ImeParent should be the display. + assertEquals(dc.getImeContainer().getParent().getSurfaceControl(), dc.computeImeParent()); + } + @Test public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { final DisplayContent dc = createNewDisplay();