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

Commit 2a452c40 authored by Shan Huang's avatar Shan Huang Committed by Automerger Merge Worker
Browse files

Merge "Revert "Migrate InputMethodService to use OnBackInvokedDispatcher""...

Merge "Revert "Migrate InputMethodService to use OnBackInvokedDispatcher"" into tm-dev am: a81f250b am: 9b04660e am: 84230c42

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17805640



Change-Id: I20a32e716c2b8466215e118147e11ec023185d4a
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 34539396 84230c42
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;
@@ -350,9 +346,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.
@@ -1613,7 +1606,6 @@ public class InputMethodService extends AbstractInputMethodService {
    @Override public void onDestroy() {
        mDestroyed = true;
        super.onDestroy();
        unregisterOnBackInvokedCallback();
        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
                mInsetsComputer);
        doFinishInput();
@@ -2588,7 +2580,6 @@ public class InputMethodService extends AbstractInputMethodService {
        cancelImeSurfaceRemoval();
        mInShowWindow = false;
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        registerOnBackInvokedCallback();
    }


@@ -2634,56 +2625,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}.
     *
@@ -2729,7 +2670,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