Fix unexpected IME switcher dialog hidden

Previous CL[1] gives a wrong signal for IMMS might thought the IME
surface parent has changed by transfering to the new IME control
target, but actually that signal mixtured the forcing IME parent
flag, so IME switcher dialog may hidden in such misleading way.

Also, in WM didn't consider the control change might related
to the app is relaunching case, and it's the intermediate state we
should not report to IMMS for this misleading control changed signal.
(i.e. in WindowState#removeImmediately, if the window is during
relaunching and we should not set null IME input target to affect
DC#updateImeParent)

[1]: Iae3dd713b1e980067d28debea4e0a03707aa7938

Fix: 224998014
Fix: 215448483
Fix: 227553661
Test: manul as below steps:
1)  Installed alternate keyboard app (swift keyboard).
2). From all apps > Tap on search > Keyboard pops up
    > Swipe up navigation to exit all apps.
3). From all apps > Open Settings > Tap on Search > Keyboard pops up
    > Tap on switch input button on navigation and observing.
4). Expect IME switcher dialog should be shown and not be dismissed.

Change-Id: Ib0813e2c12909ede4e582eb3499599e3cc253490
This commit is contained in:
Ming-Shin Lu
2022-03-18 00:27:45 +08:00
parent 3fda2bf279
commit dfca56d77e
4 changed files with 29 additions and 19 deletions

View File

@@ -133,10 +133,13 @@ public abstract class InputMethodManagerInternal {
*
* @param windowToken the window token that is now in control, or {@code null} if no client
* window is in control of the IME.
* @param imeParentChanged {@code true} when the window manager thoughts the IME surface parent
* will end up to change later, or {@code false} otherwise.
*/
public abstract void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged);
public abstract void reportImeControl(@Nullable IBinder windowToken);
/**
* Indicates that the IME window has re-parented to the new target when the IME control changed.
*/
public abstract void onImeParentChanged();
/**
* Destroys the IME surface.
@@ -226,8 +229,11 @@ public abstract class InputMethodManagerInternal {
}
@Override
public void reportImeControl(@Nullable IBinder windowToken,
boolean imeParentChanged) {
public void reportImeControl(@Nullable IBinder windowToken) {
}
@Override
public void onImeParentChanged() {
}
@Override

View File

@@ -5620,19 +5620,23 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
public void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) {
public void reportImeControl(@Nullable IBinder windowToken) {
synchronized (ImfLock.class) {
if (mCurFocusedWindow != windowToken) {
// mCurPerceptible was set by the focused window, but it is no longer in
// control, so we reset mCurPerceptible.
mCurPerceptible = true;
}
if (imeParentChanged) {
// Hide the IME method menu earlier when the IME surface parent will change in
// case seeing the dialog dismiss flickering during the next focused window
// starting the input connection.
mMenuController.hideInputMethodMenu();
}
}
}
@Override
public void onImeParentChanged() {
synchronized (ImfLock.class) {
// Hide the IME method menu when the IME surface parent will change in
// case seeing the dialog dismiss flickering during the next focused window
// starting the input connection.
mMenuController.hideInputMethodMenu();
}
}

View File

@@ -4257,18 +4257,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// Update Ime parent when IME insets leash created or the new IME layering target might
// updated from setImeLayeringTarget, which is the best time that default IME visibility
// has been settled down after IME control target changed.
final boolean imeParentChanged =
prevImeControlTarget != mImeControlTarget || forceUpdateImeParent;
if (imeParentChanged) {
final boolean imeControlChanged = prevImeControlTarget != mImeControlTarget;
if (imeControlChanged || forceUpdateImeParent) {
updateImeParent();
}
final WindowState win = InsetsControlTarget.asWindowOrNull(mImeControlTarget);
final IBinder token = win != null ? win.mClient.asBinder() : null;
// Note: not allowed to call into IMMS with the WM lock held, hence the post.
mWmService.mH.post(() ->
InputMethodManagerInternal.get().reportImeControl(token, imeParentChanged)
);
mWmService.mH.post(() -> InputMethodManagerInternal.get().reportImeControl(token));
}
void updateImeParent() {
@@ -4290,6 +4287,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// do a force update to make sure there is a layer set for the new parent.
assignRelativeLayerForIme(getSyncTransaction(), true /* forceUpdate */);
scheduleAnimation();
mWmService.mH.post(() -> InputMethodManagerInternal.get().onImeParentChanged());
}
}

View File

@@ -2465,7 +2465,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
dc.setImeLayeringTarget(null);
dc.computeImeTarget(true /* updateImeTarget */);
}
if (dc.getImeInputTarget() == this) {
if (dc.getImeInputTarget() == this
&& (mActivityRecord == null || !mActivityRecord.isRelaunching())) {
dc.updateImeInputAndControlTarget(null);
}