Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cd5cb68 authored by Felix Stern's avatar Felix Stern
Browse files

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
parent 7875655e
Loading
Loading
Loading
Loading
+31 −17
Original line number Diff line number Diff line
@@ -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,
        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);
            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,6 +3730,10 @@ public final class InputMethodManager {

            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);

            if (Flags.refactorInsetsController()) {
                mCurRootView.getInsetsController().hide(WindowInsets.Type.ime(),
                        false /* fromIme */, statsToken);
            } else {
                IInputMethodManagerGlobalInvoker.hideSoftInput(
                        mClient,
                        rootView.getWindowToken(),
@@ -3731,6 +3744,7 @@ public final class InputMethodManager {
                        true /*async */);
            }
        }
    }

    /**
     * Register for IME state callbacks and applying visibility in