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

Commit f4644c1d authored by Johannes Gallmann's avatar Johannes Gallmann
Browse files

Split ImeOnBackInvokedDispatcher into two classes

ImeOnBackInvokedDispatcher was getting increasingly confusing because it
was shared between the app process and IME process. It contained some
logic that was only used at the app side and some logic that was only
used at the IME side.

This CL aims to simplify it by splitting the code into two new classes:
ImeBackCallbackProxy (app side) and ImeBackCallbackSender (IME side).
This makes it a lot clearer to readers what happens at the app side and
what happens at the IME side.

Bug: 438718906
Test: KeyboardVisibilityControlTest
Flag: EXEMPT low-risk refactor which would be difficult to flag
Change-Id: Id34d2170daf7144a5105d7fafb0507639d95e1f5
parent 2c325801
Loading
Loading
Loading
Loading
+11 −16
Original line number Original line Diff line number Diff line
@@ -58,8 +58,6 @@ import static android.view.inputmethod.Flags.FLAG_CONNECTIONLESS_HANDWRITING;
import static android.view.inputmethod.Flags.FLAG_VERIFY_KEY_EVENT;
import static android.view.inputmethod.Flags.FLAG_VERIFY_KEY_EVENT;
import static android.view.inputmethod.Flags.ctrlShiftShortcut;
import static android.view.inputmethod.Flags.ctrlShiftShortcut;


import static com.android.window.flags.Flags.imeBackCallbackLeakPrevention;

import android.annotation.CallSuper;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.DrawableRes;
import android.annotation.DurationMillisLong;
import android.annotation.DurationMillisLong;
@@ -152,7 +150,7 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView;
import android.window.CompatOnBackInvokedCallback;
import android.window.CompatOnBackInvokedCallback;
import android.window.ImeOnBackInvokedDispatcher;
import android.window.ImeBackCallbackSender;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import android.window.OnBackInvokedDispatcher;
import android.window.WindowMetricsHelper;
import android.window.WindowMetricsHelper;
@@ -371,7 +369,7 @@ public class InputMethodService extends AbstractInputMethodService {
     * A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view.
     * A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view.
     **/
     **/
    private RingBuffer<MotionEvent> mPendingEvents;
    private RingBuffer<MotionEvent> mPendingEvents;
    private ImeOnBackInvokedDispatcher mImeDispatcher;
    private ImeBackCallbackSender mImeBackCallbackSender;
    private boolean mBackCallbackRegistered = false;
    private boolean mBackCallbackRegistered = false;
    private final CompatOnBackInvokedCallback mCompatBackCallback = this::compatHandleBack;
    private final CompatOnBackInvokedCallback mCompatBackCallback = this::compatHandleBack;
    private Runnable mImeSurfaceRemoverRunnable;
    private Runnable mImeSurfaceRemoverRunnable;
@@ -839,14 +837,11 @@ public class InputMethodService extends AbstractInputMethodService {
            // (if any) can be unregistered using the old dispatcher if {@link #doFinishInput()}
            // (if any) can be unregistered using the old dispatcher if {@link #doFinishInput()}
            // is called from {@link #startInput(InputConnection, EditorInfo)} or
            // is called from {@link #startInput(InputConnection, EditorInfo)} or
            // {@link #restartInput(InputConnection, EditorInfo)}.
            // {@link #restartInput(InputConnection, EditorInfo)}.
            final ImeOnBackInvokedDispatcher oldDispatcher = mImeDispatcher;
            mImeBackCallbackSender.setTargetAppPackageName(params.editorInfo.packageName);
            mImeDispatcher = params.imeDispatcher;
            mImeBackCallbackSender.setResultReceiver(params.imeBackCallbackReceiver);
            if (imeBackCallbackLeakPrevention() && oldDispatcher != null && mImeDispatcher != null
                    && oldDispatcher != mImeDispatcher) {
                mImeDispatcher.transferNonSystemCallbacksFrom(oldDispatcher);
            }
            if (mWindow != null) {
            if (mWindow != null) {
                mWindow.getOnBackInvokedDispatcher().setImeOnBackInvokedDispatcher(mImeDispatcher);
                mWindow.getOnBackInvokedDispatcher().setImeBackCallbackSender(
                        mImeBackCallbackSender);
                if (mDecorViewVisible && mShowInputRequested) {
                if (mDecorViewVisible && mShowInputRequested) {
                    // Back callback is typically registered in {@link #showWindow()}, but it's
                    // Back callback is typically registered in {@link #showWindow()}, but it's
                    // possible for {@link #doStartInput()} to be called without
                    // possible for {@link #doStartInput()} to be called without
@@ -1725,10 +1720,9 @@ public class InputMethodService extends AbstractInputMethodService {
                Context.LAYOUT_INFLATER_SERVICE);
                Context.LAYOUT_INFLATER_SERVICE);
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initSoftInputWindow");
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initSoftInputWindow");
        mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
        mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
        if (mImeDispatcher != null) {
        mImeBackCallbackSender = new ImeBackCallbackSender();
            mWindow.getOnBackInvokedDispatcher()
        mWindow.getOnBackInvokedDispatcher().setImeBackCallbackSender(mImeBackCallbackSender);
                    .setImeOnBackInvokedDispatcher(mImeDispatcher);

        }
        mNavigationBarController.onSoftInputWindowCreated(mWindow);
        mNavigationBarController.onSoftInputWindowCreated(mWindow);
        {
        {
            final Window window = mWindow.getWindow();
            final Window window = mWindow.getWindow();
@@ -1871,7 +1865,8 @@ public class InputMethodService extends AbstractInputMethodService {
            // when IME developers are doing something unsupported.
            // when IME developers are doing something unsupported.
            InputMethodPrivilegedOperationsRegistry.remove(mToken);
            InputMethodPrivilegedOperationsRegistry.remove(mToken);
        }
        }
        mImeDispatcher = null;
        mImeBackCallbackSender.clear();
        mImeBackCallbackSender = null;
    }
    }


    /**
    /**
+1 −1
Original line number Original line Diff line number Diff line
@@ -152,7 +152,7 @@ public class ImeBackAnimationController implements OnBackAnimationCallback {
        }
        }
        // Unregister all IME back callbacks so that back events are sent to the next callback
        // Unregister all IME back callbacks so that back events are sent to the next callback
        // even while the hide animation is playing
        // even while the hide animation is playing
        mInsetsController.getHost().getInputMethodManager().getImeOnBackInvokedDispatcher()
        mInsetsController.getHost().getInputMethodManager().getImeBackCallbackProxy()
                .preliminaryClear();
                .preliminaryClear();
    }
    }


+2 −2
Original line number Original line Diff line number Diff line
@@ -1375,7 +1375,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        if (!fromPredictiveBack && !visible && (types & ime()) != 0
        if (!fromPredictiveBack && !visible && (types & ime()) != 0
                && (mRequestedVisibleTypes & ime()) != 0) {
                && (mRequestedVisibleTypes & ime()) != 0) {
            // Clear IME back callbacks if a IME hide animation is requested
            // Clear IME back callbacks if a IME hide animation is requested
            mHost.getInputMethodManager().getImeOnBackInvokedDispatcher().preliminaryClear();
            mHost.getInputMethodManager().getImeBackCallbackProxy().preliminaryClear();
        }
        }
        // Basically, we accept the requested visibilities from the upstream callers...
        // Basically, we accept the requested visibilities from the upstream callers...
        setRequestedVisibleTypes(visible ? types : 0, types);
        setRequestedVisibleTypes(visible ? types : 0, types);
@@ -1834,7 +1834,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                // In case the IME back callbacks have been preliminarily cleared before, let's
                // In case the IME back callbacks have been preliminarily cleared before, let's
                // reregister them. This can happen if an IME hide animation was interrupted and the
                // reregister them. This can happen if an IME hide animation was interrupted and the
                // IME is requested to be shown again.
                // IME is requested to be shown again.
                getHost().getInputMethodManager().getImeOnBackInvokedDispatcher()
                getHost().getInputMethodManager().getImeBackCallbackProxy()
                        .undoPreliminaryClear();
                        .undoPreliminaryClear();
            }
            }
            ProtoLog.d(IME_INSETS_CONTROLLER, "Setting requestedVisibleTypes to %d (was %d)",
            ProtoLog.d(IME_INSETS_CONTROLLER, "Setting requestedVisibleTypes to %d (was %d)",
+1 −1
Original line number Original line Diff line number Diff line
@@ -12949,7 +12949,7 @@ public final class ViewRootImpl implements ViewParent,
        mCompatOnBackInvokedCallback = () -> {
        mCompatOnBackInvokedCallback = () -> {
            injectBackKeyEvents(/* preImeOnly */ false);
            injectBackKeyEvents(/* preImeOnly */ false);
        };
        };
        if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) {
        if (mOnBackInvokedDispatcher.hasImeBackCallbackSender()) {
            Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
            Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
            return;
            return;
        }
        }
+4 −3
Original line number Original line Diff line number Diff line
@@ -29,10 +29,10 @@ import android.annotation.UserIdInt;
import android.content.Context;
import android.content.Context;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.util.ExceptionUtils;
import android.util.ExceptionUtils;
import android.view.WindowManager;
import android.view.WindowManager;
import android.window.ImeOnBackInvokedDispatcher;


import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.inputmethod.DirectBootAwareness;
import com.android.internal.inputmethod.DirectBootAwareness;
@@ -299,7 +299,7 @@ final class IInputMethodManagerGlobalInvoker {
            @Nullable IRemoteInputConnection remoteInputConnection,
            @Nullable IRemoteInputConnection remoteInputConnection,
            @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
            @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
            int unverifiedTargetSdkVersion, @UserIdInt int userId,
            int unverifiedTargetSdkVersion, @UserIdInt int userId,
            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, boolean imeRequestedVisible) {
            @NonNull ResultReceiver imeBackCallbackReceiver, boolean imeRequestedVisible) {
        final IInputMethodManager service = getService();
        final IInputMethodManager service = getService();
        if (service == null) {
        if (service == null) {
            return -1;
            return -1;
@@ -308,7 +308,8 @@ final class IInputMethodManagerGlobalInvoker {
            service.startInputOrWindowGainedFocus(startInputReason, client, windowToken,
            service.startInputOrWindowGainedFocus(startInputReason, client, windowToken,
                    startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection,
                    startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection,
                    remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId,
                    remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId,
                    imeDispatcher, imeRequestedVisible, advanceAngGetStartInputSequenceNumber());
                    imeBackCallbackReceiver, imeRequestedVisible,
                    advanceAngGetStartInputSequenceNumber());
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
Loading