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

Commit ded24ed7 authored by Felix Stern's avatar Felix Stern
Browse files

Posting show/hide call if view is running on a different thread

When we received a show/hide call via binder call from system_server, it was always directly sent to InsetsController. However, this did not take the possibility into account that the view is running on different thread.
This CL adds a check for that and, if needed, posts the show/hide call to the correct thread.

Fix: 407546107
Test: atest CtsInputMethodTestCases
Flag: EXEMPT bugfix
Change-Id: I99e89aa824f2063336784255f378b2a44b5b016e
parent 539679cd
Loading
Loading
Loading
Loading
+52 −6
Original line number Diff line number Diff line
@@ -1449,16 +1449,62 @@ public final class InputMethodManager {
                    final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2;
                    synchronized (mH) {
                        if (mCurRootView != null) {
                            final var insetsController = mCurRootView.getInsetsController();
                            if (insetsController != 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);
                                    }
                                }
                            }
                        } else {
                            ImeTracker.forLogging().onFailed(statsToken,
                                    ImeTracker.PHASE_CLIENT_HANDLE_SET_IME_VISIBILITY);