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

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

Fix onKeyPreIme not called when enableOnBackInvokedCallback=false

Currently, IME callbacks are registered regardless of enableOnBackInvokedCallback being false. That causes the whole logic of onKeyPreIme in ViewRootImpl to be skipped entirely, because back events are directly dispatched to the IME callback. Instead, we should not register the IME callback if the app has not set enableOnBackInvokedCallback=true. In that case, back events will be dispatched to the compat-callback from ViewRoot which will inject BACK_KEY events which are piped through the usual key handling (including onKeyPreIme).

Bug: 336470108
Flag: NONE
Test: atest FrameworksCoreTests:WindowOnBackInvokedDispatcherTest
Test: Manual, i.e. verifying that onKeyPreIme is called when enableOnBackInvokedCallback=false
Change-Id: I8222cbc94ec25a366ced1139e3f99831114efbd5
parent 02aea3b1
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -17163,7 +17163,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * associated with the view hierarchy. This can be used to intercept
     * key events in special situations before the IME consumes them; a
     * typical example would be handling the BACK key to update the application's
     * UI instead of allowing the IME to see it and close itself.
     * UI instead of allowing the IME to see it and close itself. Due to a bug,
     * this function is not called for BACK key events on Android T and U, when
     * the IME is shown.
     *
     * @param keyCode The value in event.getKeyCode().
     * @param event Description of the key event.
+8 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.window;

import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -27,6 +29,8 @@ import android.os.ResultReceiver;
import android.util.Log;
import android.view.ViewRootImpl;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;

/**
@@ -280,7 +284,8 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
        sendStopDispatching();
    }

    static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
    @VisibleForTesting(visibility = PACKAGE)
    public static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
        @NonNull
        private final IOnBackInvokedCallback mIOnBackInvokedCallback;
        /**
@@ -327,7 +332,8 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
     * Subclass of ImeOnBackInvokedCallback indicating that a predictive IME back animation may be
     * played instead of invoking the callback.
     */
    static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback {
    @VisibleForTesting(visibility = PACKAGE)
    public static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback {
        DefaultImeOnBackAnimationCallback(@NonNull IOnBackInvokedCallback iCallback, int id,
                int priority) {
            super(iCallback, id, priority);
+6 −0
Original line number Diff line number Diff line
@@ -176,6 +176,12 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
                return;
            }
            if ((callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback
                    || callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
                    && !isOnBackInvokedCallbackEnabled()) {
                // Fall back to compat back key injection if legacy back behaviour should be used.
                return;
            }
            if (!mOnBackInvokedCallbacks.containsKey(priority)) {
                mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
            }
+32 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.ImeBackAnimationController;
import android.view.MotionEvent;

import androidx.test.filters.SmallTest;
@@ -77,6 +78,12 @@ public class WindowOnBackInvokedDispatcherTest {
    @Mock
    private OnBackAnimationCallback mCallback2;
    @Mock
    private ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback mImeCallback;
    @Mock
    private ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback mDefaultImeCallback;
    @Mock
    private ImeBackAnimationController mImeBackAnimationController;
    @Mock
    private Context mContext;
    @Mock
    private ApplicationInfo mApplicationInfo;
@@ -103,7 +110,7 @@ public class WindowOnBackInvokedDispatcherTest {
        doReturn(mApplicationInfo).when(mContext).getApplicationInfo();

        mDispatcher = new WindowOnBackInvokedDispatcher(mContext, Looper.getMainLooper());
        mDispatcher.attachToWindow(mWindowSession, mWindow, null);
        mDispatcher.attachToWindow(mWindowSession, mWindow, mImeBackAnimationController);
    }

    private void waitForIdle() {
@@ -419,4 +426,28 @@ public class WindowOnBackInvokedDispatcherTest {
        // onBackPressed is called from animator, so it can happen more than once.
        verify(mCallback1, atLeast(1)).onBackProgressed(any());
    }

    @Test
    public void registerImeCallbacks_onBackInvokedCallbackEnabled() throws RemoteException {
        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback);
        assertCallbacksSize(/* default */ 1, /* overlay */ 0);
        assertSetCallbackInfo();
        assertTopCallback(mImeBackAnimationController);

        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback);
        assertCallbacksSize(/* default */ 2, /* overlay */ 0);
        assertSetCallbackInfo();
        assertTopCallback(mImeCallback);
    }

    @Test
    public void registerImeCallbacks_legacyBack() throws RemoteException {
        doReturn(false).when(mApplicationInfo).isOnBackInvokedCallbackEnabled();

        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback);
        assertNoSetCallbackInfo();

        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback);
        assertNoSetCallbackInfo();
    }
}