Notify IMMS synchronously on IME insets hidden.
Currently, IMMS will be notified asynchronously when an IME hide animation finishes, via message dispatching through IMS (IMM#notifyImeHidden -> IMS#notifyImeHidden -> IMMS#hideMySoftInput). This creates a race condition when IMM#showSoftInput or WIC#show is called around the end of hide animation. This CL fixes the race condition by synchronously and directly calling IMMS#hideSoftInput from IMM#notifyImeHidden. Note that there is still another race condition for IMM#showSoftInput (not WIC#show) if it's called during an IME hide animation; IMM#showSoftInput ended up calling WIC#show asynchronously, but at that time the running IME hide animation may have already been finished successfully and WIC#show may fail to cancel the hide animation (then the cleanup IMM#notifyImeHidden hides the IME again disruptively). I will fix the latter issue in a separate CL. Bug: 221483132 Bug: 225674038 Test: atest InputMethodStressTest Test: atest CtsInputMethodTestCases Test: atest WindowInsetsAnimationControllerTests Change-Id: I7c71dc5a1d6b61aa79d1666f0e257e6401e4adb2
This commit is contained in:
@@ -53,7 +53,6 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
|
||||
private static final int DO_APP_PRIVATE_COMMAND = 100;
|
||||
private static final int DO_FINISH_SESSION = 110;
|
||||
private static final int DO_VIEW_CLICKED = 115;
|
||||
private static final int DO_NOTIFY_IME_HIDDEN = 120;
|
||||
private static final int DO_REMOVE_IME_SURFACE = 130;
|
||||
private static final int DO_FINISH_INPUT = 140;
|
||||
private static final int DO_INVALIDATE_INPUT = 150;
|
||||
@@ -133,10 +132,6 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
|
||||
mInputMethodSession.viewClicked(msg.arg1 == 1);
|
||||
return;
|
||||
}
|
||||
case DO_NOTIFY_IME_HIDDEN: {
|
||||
mInputMethodSession.notifyImeHidden();
|
||||
return;
|
||||
}
|
||||
case DO_REMOVE_IME_SURFACE: {
|
||||
mInputMethodSession.removeImeSurface();
|
||||
return;
|
||||
@@ -197,11 +192,6 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
|
||||
mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyImeHidden() {
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_IME_HIDDEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeImeSurface() {
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_IME_SURFACE));
|
||||
|
||||
@@ -1059,10 +1059,6 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
return viewRoot == null ? null : viewRoot.getInputToken();
|
||||
}
|
||||
|
||||
private void notifyImeHidden() {
|
||||
requestHideSelf(0 /* flags */, SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
|
||||
}
|
||||
|
||||
private void scheduleImeSurfaceRemoval() {
|
||||
if (mShowInputRequested || mWindowVisible || mWindow == null
|
||||
|| mImeSurfaceScheduledForRemoval) {
|
||||
@@ -1225,14 +1221,6 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
InputMethodService.this.onUpdateCursorAnchorInfo(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify IME that window is hidden.
|
||||
* @hide
|
||||
*/
|
||||
public final void notifyImeHidden() {
|
||||
InputMethodService.this.notifyImeHidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify IME that surface can be now removed.
|
||||
* @hide
|
||||
|
||||
@@ -23,7 +23,6 @@ import static android.view.InsetsController.AnimationType;
|
||||
import static android.view.InsetsState.ITYPE_IME;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.IBinder;
|
||||
import android.os.Trace;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -104,7 +103,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify {@link InputMethodService} that IME window is hidden.
|
||||
* Notify {@link com.android.server.inputmethod.InputMethodManagerService} that
|
||||
* IME insets are hidden.
|
||||
*/
|
||||
@Override
|
||||
void notifyHidden() {
|
||||
|
||||
@@ -2521,7 +2521,7 @@ public final class InputMethodManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify IME directly that it is no longer visible.
|
||||
* Notify IMMS that IME insets are no longer visible.
|
||||
*
|
||||
* @param windowToken the window from which this request originates. If this doesn't match the
|
||||
* currently served view, the request is ignored.
|
||||
@@ -2533,7 +2533,13 @@ public final class InputMethodManager {
|
||||
synchronized (mH) {
|
||||
if (mCurrentInputMethodSession != null && mCurRootView != null
|
||||
&& mCurRootView.getWindowToken() == windowToken) {
|
||||
mCurrentInputMethodSession.notifyImeHidden();
|
||||
try {
|
||||
mService.hideSoftInput(mClient, windowToken, 0 /* flags */,
|
||||
null /* resultReceiver */,
|
||||
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,13 +194,6 @@ public interface InputMethodSession {
|
||||
*/
|
||||
public void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo);
|
||||
|
||||
/**
|
||||
* Notifies {@link android.inputmethodservice.InputMethodService} that IME has been
|
||||
* hidden from user.
|
||||
* @hide
|
||||
*/
|
||||
public void notifyImeHidden();
|
||||
|
||||
/**
|
||||
* Notify IME directly to remove surface as it is no longer visible.
|
||||
* @hide
|
||||
|
||||
@@ -105,15 +105,6 @@ final class InputMethodSessionWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
void notifyImeHidden() {
|
||||
try {
|
||||
mSession.notifyImeHidden();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "IME died", e);
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
void viewClicked(boolean focusChanged) {
|
||||
try {
|
||||
|
||||
@@ -50,8 +50,6 @@ oneway interface IInputMethodSession {
|
||||
|
||||
void updateCursorAnchorInfo(in CursorAnchorInfo cursorAnchorInfo);
|
||||
|
||||
void notifyImeHidden();
|
||||
|
||||
void removeImeSurface();
|
||||
|
||||
void finishInput();
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.platform.test.annotations.RootPermissionTest;
|
||||
import android.platform.test.rule.UnlockScreenRule;
|
||||
import android.view.WindowInsets;
|
||||
@@ -78,9 +77,6 @@ public final class ImeOpenCloseStressTest {
|
||||
instrumentation.runOnMainSync(activity::hideIme);
|
||||
waitOnMainUntil(msgPrefix + "IME should be hidden",
|
||||
() -> !activity.isAnimating() && !isImeShown(editText));
|
||||
// b/b/221483132, wait until IMS and IMMS handles IMM#notifyImeHidden.
|
||||
// There is no good signal, so we just wait a second.
|
||||
SystemClock.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user