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
This commit is contained in:
Wilson Wu
2022-04-19 18:06:28 +08:00
parent ba95ddf69d
commit e27e307baa
2 changed files with 34 additions and 1 deletions

View File

@@ -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.

View File

@@ -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();