diff options
| -rw-r--r-- | core/java/android/view/inputmethod/ImeTracker.java | 6 | ||||
| -rw-r--r-- | core/java/android/view/inputmethod/InputMethodManager.java | 21 |
2 files changed, 26 insertions, 1 deletions
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java index d90455ab971d..2ca62a0725df 100644 --- a/core/java/android/view/inputmethod/ImeTracker.java +++ b/core/java/android/view/inputmethod/ImeTracker.java @@ -220,6 +220,7 @@ public interface ImeTracker { PHASE_WM_POSTING_CHANGED_IME_VISIBILITY, PHASE_WM_INVOKING_IME_REQUESTED_LISTENER, PHASE_CLIENT_ALREADY_HIDDEN, + PHASE_CLIENT_VIEW_HANDLER_AVAILABLE, }) @Retention(RetentionPolicy.SOURCE) @interface Phase {} @@ -424,6 +425,11 @@ public interface ImeTracker { ImeProtoEnums.PHASE_WM_INVOKING_IME_REQUESTED_LISTENER; /** IME is requested to be hidden, but already hidden. Don't hide to avoid another animation. */ int PHASE_CLIENT_ALREADY_HIDDEN = ImeProtoEnums.PHASE_CLIENT_ALREADY_HIDDEN; + /** + * The view's handler is needed to check if we're running on a different thread. We can't + * continue without. + */ + int PHASE_CLIENT_VIEW_HANDLER_AVAILABLE = ImeProtoEnums.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE; /** * Called when an IME request is started. diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 47fc43735c4d..9001251914d6 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2591,6 +2591,17 @@ public final class InputMethodManager { // TODO(b/322992891) handle case of HIDE_IMPLICIT_ONLY final var viewRootImpl = servedView.getViewRootImpl(); if (viewRootImpl != null) { + Handler vh = servedView.getHandler(); + if (vh == null) { + // If the view doesn't have a handler, something has changed out from + // under us. The current input has been closed before (from checkFocus). + ImeTracker.forLogging().onFailed(statsToken, + ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE); + return false; + } + ImeTracker.forLogging().onProgress(statsToken, + ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE); + if (resultReceiver != null) { final boolean imeReqVisible = (viewRootImpl.getInsetsController().getRequestedVisibleTypes() @@ -2599,7 +2610,15 @@ public final class InputMethodManager { !imeReqVisible ? InputMethodManager.RESULT_UNCHANGED_HIDDEN : InputMethodManager.RESULT_HIDDEN, null); } - viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime()); + if (vh.getLooper() != Looper.myLooper()) { + // The view is running on a different thread than our own, so + // we need to reschedule our work for over there. + if (DEBUG) Log.v(TAG, "Hiding soft input: reschedule to view thread"); + vh.post(() -> viewRootImpl.getInsetsController().hide( + WindowInsets.Type.ime())); + } else { + viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime()); + } } return true; } else { |