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

Commit 0a57e88a authored by Shan Huang's avatar Shan Huang
Browse files

Revert "Migrate InputMethodService to use OnBackInvokedDispatcher"

This reverts commit 38be9e32.

Reason for revert: Caused b/229642813 and b/229355440

Bug:229642813
Bug:229636388

Change-Id: I65e4f66ec2156d4e0812753d71ac82afd965fe3b
parent 38be9e32
Loading
Loading
Loading
Loading
+0 −60
Original line number Diff line number Diff line
@@ -101,7 +101,6 @@ import android.view.BatchedInputEventReceiver.SimpleBatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEventReceiver;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -135,10 +134,7 @@ import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import android.window.WindowMetricsHelper;
import android.window.WindowOnBackInvokedDispatcher;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IInputContentUriToken;
@@ -349,9 +345,6 @@ public class InputMethodService extends AbstractInputMethodService {
     **/
    private RingBuffer<MotionEvent> mPendingEvents;

    /** Callback to handle back invocation when IME window is shown. */
    private OnBackInvokedCallback mBackCallback;

    /**
     * Returns whether {@link InputMethodService} is responsible for rendering the back button and
     * the IME switcher button or not when the gestural navigation is enabled.
@@ -1612,7 +1605,6 @@ public class InputMethodService extends AbstractInputMethodService {
    @Override public void onDestroy() {
        mDestroyed = true;
        super.onDestroy();
        unregisterOnBackInvokedCallback();
        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
                mInsetsComputer);
        doFinishInput();
@@ -2587,7 +2579,6 @@ public class InputMethodService extends AbstractInputMethodService {
        cancelImeSurfaceRemoval();
        mInShowWindow = false;
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        registerOnBackInvokedCallback();
    }


@@ -2633,56 +2624,6 @@ public class InputMethodService extends AbstractInputMethodService {
        if (doShowInput) startExtractingText(false);
    }

    /**
     * Registers an {@link OnBackInvokedCallback} to handle back invocation when ahead-of-time
     *  back dispatching is enabled. We keep the KEYCODE_BACK based legacy code around to handle
     *  back on older devices.
     */
    private void registerOnBackInvokedCallback() {
        if (mBackCallback != null) {
            // A back callback has already been registered.
            return;
        }
        final ViewRootImpl viewRootImpl = mRootView == null ? null : mRootView.getViewRootImpl();
        if (viewRootImpl != null && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(
                viewRootImpl.mContext)) {
            final OnBackInvokedCallback callback = () -> {
                KeyEvent downEvent = createKeyEvent(
                        KeyEvent.ACTION_DOWN, false /* isTracking */);
                onKeyDown(KeyEvent.KEYCODE_BACK, downEvent);
                boolean hasStartedTracking =
                        (downEvent.getFlags() & KeyEvent.FLAG_START_TRACKING) != 0;
                KeyEvent upEvent = createKeyEvent(KeyEvent.ACTION_UP, hasStartedTracking);
                onKeyUp(KeyEvent.KEYCODE_BACK, upEvent);
            };
            viewRootImpl.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
                    OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback);
            mBackCallback = callback;
        }
    }

    private KeyEvent createKeyEvent(int action, boolean isTracking) {
        final long when = SystemClock.uptimeMillis();
        return new KeyEvent(when, when, action,
                KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
                KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY
                        | (isTracking ? KeyEvent.FLAG_TRACKING : 0),
                InputDevice.SOURCE_KEYBOARD);
    }

    private void unregisterOnBackInvokedCallback() {
        final ViewRootImpl viewRootImpl = mRootView == null ? null : mRootView.getViewRootImpl();
        if (viewRootImpl != null
                && mBackCallback != null
                && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(
                viewRootImpl.mContext)) {
            viewRootImpl.getOnBackInvokedDispatcher()
                    .unregisterOnBackInvokedCallback(mBackCallback);
        }
        mBackCallback = null;
    }

    /**
     * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}.
     *
@@ -2728,7 +2669,6 @@ public class InputMethodService extends AbstractInputMethodService {
        }
        mLastWasInFullscreenMode = mIsFullscreen;
        updateFullscreenMode();
        unregisterOnBackInvokedCallback();
    }

    /**
+2 −17
Original line number Diff line number Diff line
@@ -167,23 +167,6 @@ class BackNavigationController {
                currentActivity = window.mActivityRecord;
                currentTask = window.getTask();
                callbackInfo = window.getOnBackInvokedCallbackInfo();
                final DisplayContent displayContent = window.getDisplayContent();

                // When IME is shown, return the more prioritized callback between IME and app.
                // Priority ordering follows: OVERLAY, IME, DEFAULT.
                if (displayContent != null && displayContent.getImeContainer().isVisible()) {
                    WindowState imeWindow = displayContent.getImeContainer().getWindow(
                            windowState -> windowState.getOnBackInvokedCallbackInfo() != null);
                    if (imeWindow != null) {
                        OnBackInvokedCallbackInfo imeCallbackInfo =
                                imeWindow.getOnBackInvokedCallbackInfo();
                        if (imeCallbackInfo != null && (callbackInfo == null
                                || callbackInfo.getPriority() <= imeCallbackInfo.getPriority())) {
                            callbackInfo = imeCallbackInfo;
                        }
                    }
                }

                if (callbackInfo == null) {
                    Slog.e(TAG, "No callback registered, returning null.");
                    return null;
@@ -206,10 +189,12 @@ class BackNavigationController {
            // If we don't need to set up the animation, we return early. This is the case when
            // - We have an application callback.
            // - We don't have any ActivityRecord or Task to animate.
            // - The IME is opened, and we just need to close it.
            // - The home activity is the focused activity.
            if (backType == BackNavigationInfo.TYPE_CALLBACK
                    || currentActivity == null
                    || currentTask == null
                    || currentTask.getDisplayContent().getImeContainer().isVisible()
                    || currentActivity.isActivityTypeHome()) {
                return infoBuilder
                        .setType(backType)
+12 −58
Original line number Diff line number Diff line
@@ -20,8 +20,6 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.window.BackNavigationInfo.typeToString;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

@@ -83,8 +81,8 @@ public class BackNavigationControllerTests extends WindowTestsBase {

    @Test
    public void backNavInfo_HomeWhenBackToLauncher() {
        IOnBackInvokedCallback callback =
                withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_SYSTEM);
        Task task = createTopTaskWithActivity();
        IOnBackInvokedCallback callback = withSystemCallback(task);

        SurfaceControl.Transaction tx = mock(SurfaceControl.Transaction.class);
        BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(mWm,
@@ -105,7 +103,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
    public void backTypeCrossTaskWhenBackToPreviousTask() {
        Task taskA = createTask(mDefaultDisplay);
        createActivityRecord(taskA);
        withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_SYSTEM);
        withSystemCallback(createTopTaskWithActivity());
        BackNavigationInfo backNavigationInfo = startBackNavigation();
        assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
        assertThat(typeToString(backNavigationInfo.getType()))
@@ -157,7 +155,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
    @Test
    public void preparesForBackToHome() {
        Task task = createTopTaskWithActivity();
        withCallback(task, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
        withSystemCallback(task);

        BackNavigationInfo backNavigationInfo = startBackNavigation();
        assertThat(typeToString(backNavigationInfo.getType()))
@@ -167,8 +165,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
    @Test
    public void backTypeCallback() {
        Task task = createTopTaskWithActivity();
        IOnBackInvokedCallback appCallback =
                withCallback(task, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
        IOnBackInvokedCallback appCallback = withAppCallback(task);

        BackNavigationInfo backNavigationInfo = startBackNavigation();
        assertThat(typeToString(backNavigationInfo.getType()))
@@ -229,61 +226,18 @@ public class BackNavigationControllerTests extends WindowTestsBase {
                1, appLatch.getCount());
    }

    @Test
    public void returnsImeCallback_imeVisible() {
        // Set up a top activity with a default priority callback.
        IOnBackInvokedCallback appCallback =
                withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_DEFAULT);
        IOnBackInvokedCallback imeCallback = createOnBackInvokedCallback();

        // Set up an IME window with also a default priority callback.
        final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
        final WindowState imeWindow = createImeWindow();
        imeWindow.setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(
                        imeCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
        spyOn(imeContainer);
        // Simulate IME becoming visible.
        doReturn(true).when(imeContainer).isVisible();
        doReturn(imeWindow).when(imeContainer).getWindow(any());
        BackNavigationInfo backNavigationInfo = startBackNavigation();

        // Expect the IME callback to be selected.
        assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(imeCallback);
    }

    @Test
    public void returnsAppOverlayCallback_imeVisible() {
        // Set up a top activity with an overlay priority callback.
        IOnBackInvokedCallback appCallback =
                withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_OVERLAY);
        IOnBackInvokedCallback imeCallback = createOnBackInvokedCallback();

        // Set up an IME window with a default priority callback.
        final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
        final WindowState imeWindow = createImeWindow();
        imeWindow.setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(
                        imeCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
        spyOn(imeContainer);
        // Simulate IME becoming visible.
        doReturn(true).when(imeContainer).isVisible();
        doReturn(imeWindow).when(imeContainer).getWindow(any());
        BackNavigationInfo backNavigationInfo = startBackNavigation();

        // Expect the app callback to be selected.
        assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(appCallback);
    }

    private IOnBackInvokedCallback withCallback(Task task, int priority) {
    private IOnBackInvokedCallback withSystemCallback(Task task) {
        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(callback, priority));
                new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_SYSTEM));
        return callback;
    }

    private WindowState createImeWindow() {
        return createWindow(null, W_INPUT_METHOD, "mImeWindow", 12345 /* fake ime uide */);
    private IOnBackInvokedCallback withAppCallback(Task task) {
        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
        return callback;
    }

    @Nullable