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

Commit 3460c8e5 authored by Felix Stern's avatar Felix Stern
Browse files

Unify handler posting to InsetsController from different methods

Different methods of InputMethodManager call into InsetsController#show/hide. If the view is running on a different thread, the call will be posted on the view handler. As this logic was duplicated in those function, this CL unifies them in one method that is then called.

Bug: 407546107
Test: atest CtsInputMethodTestCases
Flag: EXEMPT refactor
Change-Id: I9836dded7b955690b8ac768fe849654d182346a9
parent ded24ed7
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ public interface ImeTracker {
            PHASE_SERVER_IME_INVOKER,
            PHASE_SERVER_CLIENT_INVOKER,
            PHASE_SERVER_ALREADY_VISIBLE,
            PHASE_CLIENT_INSETS_CONTROLLER_DISPATCH,
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface Phase {}
@@ -449,8 +450,10 @@ public interface ImeTracker {
    /** Reached the IME client invoker on the server. */
    int PHASE_SERVER_CLIENT_INVOKER = ImeProtoEnums.PHASE_SERVER_CLIENT_INVOKER;
    /** The server will dispatch the show request to the IME, but this is already visible. */
    int PHASE_SERVER_ALREADY_VISIBLE =
            ImeProtoEnums.PHASE_SERVER_ALREADY_VISIBLE;
    int PHASE_SERVER_ALREADY_VISIBLE = ImeProtoEnums.PHASE_SERVER_ALREADY_VISIBLE;
    /** The show/hide request will be dispatched to the InsetsController of the ViewRootImpl. */
    int PHASE_CLIENT_INSETS_CONTROLLER_DISPATCH =
            ImeProtoEnums.PHASE_CLIENT_INSETS_CONTROLLER_DISPATCH;

    /**
     * Called when an IME request is started.
+69 −121
Original line number Diff line number Diff line
@@ -1451,60 +1451,7 @@ public final class InputMethodManager {
                        if (mCurRootView != null) {
                            ImeTracker.forLogging().onProgress(statsToken,
                                    ImeTracker.PHASE_CLIENT_HANDLE_SET_IME_VISIBILITY);

                            final View view = mCurRootView.getView();
                            if (view == null) {
                                if (android.tracing.Flags.imetrackerProtolog()) {
                                    ProtoLog.w(INPUT_METHOD_MANAGER_WITH_LOGCAT,
                                            "Received input visibility: no view available");
                                } else {
                                    Log.w(TAG, "Received input visibility: no view available");
                                }
                                ImeTracker.forLogging().onFailed(statsToken,
                                        ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
                                return;
                            }

                            Handler vh = view.getHandler();
                            if (vh == null) {
                                // If the view doesn't have a handler, something has changed out
                                // from under us.
                                ImeTracker.forLogging().onFailed(statsToken,
                                        ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
                                return;
                            }
                            ImeTracker.forLogging().onProgress(statsToken,
                                    ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);

                            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 (android.tracing.Flags.imetrackerProtolog()) {
                                    ProtoLog.v(INPUT_METHOD_MANAGER_DEBUG,
                                            "Received input visibility: reschedule to view thread");
                                } else if (DEBUG) {
                                    Log.v(TAG,
                                            "Received input visibility: reschedule to view thread");
                                }
                                final var viewRootImpl = mCurRootView;

                                if (visible) {
                                    vh.post(() -> viewRootImpl.getInsetsController().show(
                                            WindowInsets.Type.ime(), statsToken));
                                } else {
                                    vh.post(() -> viewRootImpl.getInsetsController().hide(
                                            WindowInsets.Type.ime(), statsToken));
                                }
                            } else {
                                final var insetsController = mCurRootView.getInsetsController();
                                if (insetsController != null) {
                                    if (visible) {
                                        insetsController.show(WindowInsets.Type.ime(), statsToken);
                                    } else {
                                        insetsController.hide(WindowInsets.Type.ime(), statsToken);
                                    }
                                }
                            }
                            setImeVisibilityOnInsetsController(mCurRootView, visible, statsToken);
                        } else {
                            ImeTracker.forLogging().onFailed(statsToken,
                                    ImeTracker.PHASE_CLIENT_HANDLE_SET_IME_VISIBILITY);
@@ -2532,7 +2479,6 @@ public final class InputMethodManager {
                            & WindowInsets.Type.ime()) == 0
                    || viewRootImpl.getInsetsController()
                            .isPredictiveBackImeHideAnimInProgress())) {
                Handler vh = view.getHandler();
                ImeTracker.forLogging().onProgress(statsToken,
                        ImeTracker.PHASE_CLIENT_NO_ONGOING_USER_ANIMATION);
                if (resultReceiver != null) {
@@ -2542,21 +2488,7 @@ public final class InputMethodManager {
                            imeReqVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN
                                    : InputMethodManager.RESULT_SHOWN, null);
                }
                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 (android.tracing.Flags.imetrackerProtolog()) {
                        ProtoLog.v(INPUT_METHOD_MANAGER_DEBUG,
                                "Show soft input: reschedule to view thread");
                    } else if (DEBUG) {
                        Log.v(TAG, "Show soft input: reschedule to view thread");
                    }
                    final var finalStatsToken = statsToken;
                    vh.post(() -> viewRootImpl.getInsetsController().show(WindowInsets.Type.ime(),
                            finalStatsToken));
                } else {
                    viewRootImpl.getInsetsController().show(WindowInsets.Type.ime(), statsToken);
                }
                setImeVisibilityOnInsetsController(viewRootImpl, true /* visible */, statsToken);
                return true;
            }
            ImeTracker.forLogging().onCancelled(statsToken,
@@ -2731,8 +2663,7 @@ public final class InputMethodManager {

            final var viewRootImpl = servedView.getViewRootImpl();
            if (viewRootImpl != null) {
                Handler vh = servedView.getHandler();
                if (vh == null) {
                if (servedView.getHandler() == 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,
@@ -2742,8 +2673,6 @@ public final class InputMethodManager {
                    return CompatChanges.isChangeEnabled(
                            ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW);
                }
                ImeTracker.forLogging().onProgress(statsToken,
                        ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);

                final boolean imeReqVisible = hasViewImeRequestedVisible(
                        viewRootImpl.getView());
@@ -2752,21 +2681,7 @@ public final class InputMethodManager {
                            !imeReqVisible ? InputMethodManager.RESULT_UNCHANGED_HIDDEN
                                    : InputMethodManager.RESULT_HIDDEN, null);
                }
                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 (android.tracing.Flags.imetrackerProtolog()) {
                        ProtoLog.v(INPUT_METHOD_MANAGER_DEBUG,
                                "Hiding soft input: reschedule to view thread");
                    } else if (DEBUG) {
                        Log.v(TAG, "Hiding soft input: reschedule to view thread");
                    }
                    final var finalStatsToken = statsToken;
                    vh.post(() -> viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime(),
                            finalStatsToken));
                } else {
                    viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime(), statsToken);
                }
                setImeVisibilityOnInsetsController(viewRootImpl, false /* visible */, statsToken);
                if (!CompatChanges.isChangeEnabled(
                        ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW)) {
                    // if the IME was not visible before, the additional hide won't change
@@ -2864,6 +2779,69 @@ public final class InputMethodManager {
                view, /* delegatorPackageName= */ null, /* handwritingDelegateFlags= */ 0);
    }

    private static void setImeVisibilityOnInsetsController(@NonNull ViewRootImpl viewRootImpl,
            boolean visible, @NonNull ImeTracker.Token statsToken) {
        final View view = viewRootImpl.getView();
        if (view == null) {
            if (android.tracing.Flags.imetrackerProtolog()) {
                ProtoLog.w(INPUT_METHOD_MANAGER_WITH_LOGCAT,
                        "Cannot set IME visibility: no view available for %s",
                        (visible ? "show" : "hide"));
            } else {
                Log.w(TAG, "Cannot set IME visibility: no view available for " + (visible ? "show"
                        : "hide"));
            }
            ImeTracker.forLogging().onFailed(statsToken,
                    ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
            return;
        }

        final Handler vh = view.getHandler();
        if (vh == null) {
            // If the view doesn't have a handler, something has changed out from under us.
            ImeTracker.forLogging().onFailed(statsToken,
                    ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
            return;
        }
        ImeTracker.forLogging().onProgress(statsToken,
                ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);

        final var insetsController = viewRootImpl.getInsetsController();
        if (insetsController == null) {
            ImeTracker.forLogging().onFailed(statsToken,
                    ImeTracker.PHASE_CLIENT_INSETS_CONTROLLER_DISPATCH);
            return;
        }
        ImeTracker.forLogging().onProgress(statsToken,
                ImeTracker.PHASE_CLIENT_INSETS_CONTROLLER_DISPATCH);

        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 (android.tracing.Flags.imetrackerProtolog()) {
                ProtoLog.v(INPUT_METHOD_MANAGER_DEBUG,
                        "Rescheduling %s IME visibility to view thread",
                        (visible ? "show" : "hide"));
            } else if (DEBUG) {
                Log.v(TAG, "Rescheduling " + (visible ? "show" : "hide")
                        + " IME visibility to view thread");
            }
            vh.post(() -> {
                if (visible) {
                    insetsController.show(WindowInsets.Type.ime(), statsToken);
                } else {
                    insetsController.hide(WindowInsets.Type.ime(), statsToken);
                }
            });
        } else {
            if (visible) {
                insetsController.show(WindowInsets.Type.ime(), statsToken);
            } else {
                insetsController.hide(WindowInsets.Type.ime(), statsToken);
            }
        }
    }

    private void sendFailureCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<Boolean> callback) {
        if (executor == null || callback == null) {
@@ -3908,8 +3886,7 @@ public final class InputMethodManager {
                ActivityThread::currentApplication);

        synchronized (mH) {
            final View rootView = mCurRootView != null ? mCurRootView.getView() : null;
            if (rootView == null) {
            if (mCurRootView == null) {
                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
                ImeTracker.forLatency().onHideFailed(statsToken,
                        ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
@@ -3921,37 +3898,8 @@ public final class InputMethodManager {
                }
                return;
            }

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

            synchronized (mH) {
                Handler vh = rootView.getHandler();
                if (vh == null) {
                    // If the view doesn't have a handler, something has changed out from
                    // under us.
                    ImeTracker.forLogging().onFailed(statsToken,
                            ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
                    return;
                }
                ImeTracker.forLogging().onProgress(statsToken,
                        ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);

                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 (android.tracing.Flags.imetrackerProtolog()) {
                        ProtoLog.v(INPUT_METHOD_MANAGER_DEBUG,
                                "Close current input: reschedule hide to view thread");
                    } else if (DEBUG) {
                        Log.v(TAG, "Close current input: reschedule hide to view thread");
                    }
                    final var viewRootImpl = mCurRootView;
                    vh.post(() -> viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime(),
                            statsToken));
                } else {
                    mCurRootView.getInsetsController().hide(WindowInsets.Type.ime(), statsToken);
                }
            }
            setImeVisibilityOnInsetsController(mCurRootView, false, statsToken);
        }
    }