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

Commit 1934e139 authored by Shan Huang's avatar Shan Huang
Browse files

Fix IME callback not unregistered when IME is up during an IMM client

switch.

This can happen when one navigates from an activity showing IME
to another activity requesting to show IME. The following sequence would
happen:
- IMM of the current activity receives an UNBIND message with reason CLIENT_SWITCH
- A new IMM is created for the new activity requesting input and
  requests to bind.
- The new IMM requests to start input, triggering
  IMS#dispatchStartInputWithToken with a *new* ImeOnBackInvokedDispatcher instance than the one previously kept by IMS.

Previously, the ime dispatcher instance was updated before the existing
back callback was unregistered and caused the unregister call to fail.
The fix is to update the dispatcher after the other logic in
IMS#dispatcherStartInputWithToken (specifically, to after startInput(),
which calls doFinishInput() if input is already started).

Bug: 234416098
Test: atest CtsInputMethodTestCases

Change-Id: Ic7a5daab8709b808343388b095b5b6ad40adc777
parent 1f9afd72
Loading
Loading
Loading
Loading
+14 −5
Original line number Original line Diff line number Diff line
@@ -806,11 +806,6 @@ public class InputMethodService extends AbstractInputMethodService {
                @NonNull EditorInfo editorInfo, boolean restarting,
                @NonNull EditorInfo editorInfo, boolean restarting,
                @NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
                @NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
                @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
                @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
            mImeDispatcher = imeDispatcher;
            if (mWindow != null) {
                mWindow.getOnBackInvokedDispatcher().setImeOnBackInvokedDispatcher(
                        imeDispatcher);
            }
            mPrivOps.reportStartInputAsync(startInputToken);
            mPrivOps.reportStartInputAsync(startInputToken);
            mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags);
            mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags);
            if (restarting) {
            if (restarting) {
@@ -818,6 +813,15 @@ public class InputMethodService extends AbstractInputMethodService {
            } else {
            } else {
                startInput(inputConnection, editorInfo);
                startInput(inputConnection, editorInfo);
            }
            }
            // Update the IME dispatcher last, so that the previously registered back callback
            // (if any) can be unregistered using the old dispatcher if {@link #doFinishInput()}
            // is called from {@link #startInput(InputConnection, EditorInfo)} or
            // {@link #restartInput(InputConnection, EditorInfo)}.
            mImeDispatcher = imeDispatcher;
            if (mWindow != null) {
                mWindow.getOnBackInvokedDispatcher().setImeOnBackInvokedDispatcher(
                        imeDispatcher);
            }
        }
        }


        /**
        /**
@@ -3860,6 +3864,11 @@ public class InputMethodService extends AbstractInputMethodService {
    };
    };


    private void compatHandleBack() {
    private void compatHandleBack() {
        if (!mDecorViewVisible) {
            Log.e(TAG, "Back callback invoked on a hidden IME. Removing the callback...");
            unregisterCompatOnBackInvokedCallback();
            return;
        }
        final KeyEvent downEvent = createBackKeyEvent(
        final KeyEvent downEvent = createBackKeyEvent(
                KeyEvent.ACTION_DOWN, false /* isTracking */);
                KeyEvent.ACTION_DOWN, false /* isTracking */);
        onKeyDown(KeyEvent.KEYCODE_BACK, downEvent);
        onKeyDown(KeyEvent.KEYCODE_BACK, downEvent);