diff options
| author | 2024-10-23 14:48:50 +0000 | |
|---|---|---|
| committer | 2024-10-23 14:52:10 +0000 | |
| commit | 8cd5cb68e195acb7ef34e8d1852fcc6cfd388f2d (patch) | |
| tree | 71b88ec892101567655ad8c59f8a63b5773ac3ed | |
| parent | 7875655e9f772f175bc57799a88917101571649a (diff) | |
Fix a race when an editText was removed and added immediately again
In some rare cases, the hide request that was triggered by removing a view was applied in InsetsController too late. A following show request could have been applied before, resulting in the IME not being shown.
This was caused by InputMethodManager, as some methods (e.g., closeCurrentInput()) did not call into InsetsController#hide, but into IMMS.
This CL fixes this race condition by calling directly into InsetsController#hide, instead of using IInputMethodManagerGlobalInvoker.
Test: atest WindowInsetsControllerTests#testShowIme_immediatelyAfterDetachAndReattach --rerun-until-failure 100
Fix: 373971329
Flag: android.view.inputmethod.refactor_insets_controller
Change-Id: Ib2dc444d3d08b23e36df1c2c72e630115804f80f
| -rw-r--r-- | core/java/android/view/inputmethod/InputMethodManager.java | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 47fc43735c4d..d34f86c8e0d7 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2557,21 +2557,24 @@ public final class InputMethodManager { public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags, ResultReceiver resultReceiver) { return hideSoftInputFromWindow(windowToken, flags, resultReceiver, - SoftInputShowHideReason.HIDE_SOFT_INPUT); + SoftInputShowHideReason.HIDE_SOFT_INPUT, null); } private boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags, - ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { + ResultReceiver resultReceiver, @SoftInputShowHideReason int reason, + @Nullable ImeTracker.Token statsToken) { // Get served view initially for statsToken creation. final View initialServedView; synchronized (mH) { initialServedView = getServedViewLocked(); } - final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, - ImeTracker.ORIGIN_CLIENT, reason, ImeTracker.isFromUser(initialServedView)); - ImeTracker.forLatency().onRequestHide(statsToken, - ImeTracker.ORIGIN_CLIENT, reason, ActivityThread::currentApplication); + if (statsToken == null) { + statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, + ImeTracker.ORIGIN_CLIENT, reason, ImeTracker.isFromUser(initialServedView)); + ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT, reason, + ActivityThread::currentApplication); + } ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow", this, null /* icProto */); checkFocus(); @@ -2646,8 +2649,14 @@ public final class InputMethodManager { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); - return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, view.getWindowToken(), - statsToken, flags, null, reason, mAsyncShowHideMethodEnabled); + if (Flags.refactorInsetsController()) { + return hideSoftInputFromWindow(view.getWindowToken(), flags, + null /* resultReceiver */, reason, statsToken); + } else { + return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, + view.getWindowToken(), statsToken, flags, null, reason, + mAsyncShowHideMethodEnabled); + } } } @@ -3143,7 +3152,7 @@ public final class InputMethodManager { if (rootInsets != null && rootInsets.isVisible(WindowInsets.Type.ime())) { hideSoftInputFromWindow(view.getWindowToken(), hideFlags, null /* resultReceiver */, - SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT); + SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT, null); } else { showSoftInput(view, showFlags, null /* resultReceiver */, SoftInputShowHideReason.SHOW_TOGGLE_SOFT_INPUT); @@ -3721,14 +3730,19 @@ public final class InputMethodManager { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED); - IInputMethodManagerGlobalInvoker.hideSoftInput( - mClient, - rootView.getWindowToken(), - statsToken, - HIDE_NOT_ALWAYS, - null, - reason, - true /*async */); + if (Flags.refactorInsetsController()) { + mCurRootView.getInsetsController().hide(WindowInsets.Type.ime(), + false /* fromIme */, statsToken); + } else { + IInputMethodManagerGlobalInvoker.hideSoftInput( + mClient, + rootView.getWindowToken(), + statsToken, + HIDE_NOT_ALWAYS, + null, + reason, + true /*async */); + } } } |