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

Commit 48bfc316 authored by Ming-Shin Lu's avatar Ming-Shin Lu
Browse files

Ignore onStartInput when WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR

CL[1] introduces new WINDOW_FOCUS_GAIN_REPORT_ONLY flows to notify
InputMethodService only reports IME input target to WM when focusing to
the next window and its input connection remains.

Originally in android Q and prior devices, we don't need such report
mechnism but just skip to start new input connection and ignore
onStartInput / onFinishInput for the above use case.

Since starts from Android R, new IME insets control APIs relying on this
mechanism (see CL[2]) to keep the actual IME input target up-to-date.

As we expected there should be no new input connection and additional
onFinishInput when CL[1] landed.

However, in IMMS, startInputUncheckedLocked will be called
to callback additional onStartInput for InputMethodService, which mostly
is not expected, except when focusing the same window after device
turned screen on, we need to start input and callback onStartInput to
align with the behavior of android Q or the prior platform.

Besides, to have more clear code logic and debugging concept of
ignoring onStartInput and onFinishInput only when focused the same editor
with input connection remains, we remove WINDOW_FOCUS_GAIN_REPORT_ONLY
reason and introduced 2 more start input reasons to distinguish the
different behavior:
    - WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR
    - WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR

[1]: I45a9814d812ad906f417c24200fd4219959e2423
[2]: I9e8984b7e5aa989a53ece9e2576393f795b9ef94

Fix: 158624922
Test: atest FocusHandlingTest InputMethodStartInputLifecycleTest
Test: manual as below steps:
    1. Use Gboard, Open the emoji keyboard
    2. Swipe down to reveal notification shade
    3. Swipe up to dismiss notifications
    4. Expect the Emoji keyboard is still open without close

Change-Id: I2da99ae67b9ce4051dec0c0f0e975ebe6e1ab118
parent ae64ae50
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package android.view.inputmethod;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;

import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR;
import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR;

import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -622,8 +625,11 @@ public final class InputMethodManager {
                        Log.v(TAG, "Reporting focus gain, without startInput"
                                + ", nextFocusIsServedView=" + nextFocusIsServedView);
                    }
                    final int startInputReason =
                            nextFocusIsServedView ? WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR
                                    : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR;
                    mService.startInputOrWindowGainedFocus(
                            StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
                            startInputReason, mClient,
                            focusedView.getWindowToken(), startInputFlags, softInputMode,
                            windowFlags,
                            nextFocusIsServedView ? mCurrentTextBoxAttribute : null,
+4 −2
Original line number Diff line number Diff line
@@ -46,8 +46,10 @@ public final class InputMethodDebug {
                return "UNSPECIFIED";
            case StartInputReason.WINDOW_FOCUS_GAIN:
                return "WINDOW_FOCUS_GAIN";
            case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY:
                return "WINDOW_FOCUS_GAIN_REPORT_ONLY";
            case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR:
                return "WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR";
            case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR:
                return "WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR";
            case StartInputReason.APP_CALLED_RESTART_INPUT_API:
                return "APP_CALLED_RESTART_INPUT_API";
            case StartInputReason.CHECK_FOCUS:
+18 −12
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@ import java.lang.annotation.Retention;
@IntDef(value = {
        StartInputReason.UNSPECIFIED,
        StartInputReason.WINDOW_FOCUS_GAIN,
        StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY,
        StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR,
        StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR,
        StartInputReason.APP_CALLED_RESTART_INPUT_API,
        StartInputReason.CHECK_FOCUS,
        StartInputReason.BOUND_TO_IMMS,
@@ -48,46 +49,51 @@ public @interface StartInputReason {
     * to (re)start a new connection.
     */
    int WINDOW_FOCUS_GAIN = 1;
    /**
     * {@link android.view.Window} gained focus and the focused view is same as current served
     * view and its input connection remains. {@link android.view.inputmethod.InputMethodManager}
     * just reports this window focus change event to sync IME input target for system.
     */
    int WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR = 2;
    /**
     * {@link android.view.Window} gained focus but there is no {@link android.view.View} that is
     * eligible to have IME focus, or the focused view is same as current served view and its
     * input connection remains. {@link android.view.inputmethod.InputMethodManager} just reports
     * this window focus change event to sync IME input target for system.
     * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports
     * this window focus change event for logging.
     */
    int WINDOW_FOCUS_GAIN_REPORT_ONLY = 2;
    int WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR = 3;
    /**
     * {@link android.view.inputmethod.InputMethodManager#restartInput(android.view.View)} is
     * either explicitly called by the application or indirectly called by some Framework class
     * (e.g. {@link android.widget.EditText}).
     */
    int APP_CALLED_RESTART_INPUT_API = 3;
    int APP_CALLED_RESTART_INPUT_API = 4;
    /**
     * {@link android.view.View} requested a new connection because of view focus change.
     */
    int CHECK_FOCUS = 4;
    int CHECK_FOCUS = 5;
    /**
     * {@link android.view.inputmethod.InputMethodManager} is responding to
     * {@link com.android.internal.view.IInputMethodClient#onBindMethod}.
     */
    int BOUND_TO_IMMS = 5;
    int BOUND_TO_IMMS = 6;
    /**
     * {@link android.view.inputmethod.InputMethodManager} is responding to
     * {@link com.android.internal.view.IInputMethodClient#onUnbindMethod}.
     */
    int UNBOUND_FROM_IMMS = 6;
    int UNBOUND_FROM_IMMS = 7;
    /**
     * {@link android.view.inputmethod.InputMethodManager} is responding to
     * {@link com.android.internal.view.IInputMethodClient#setActive}.
     */
    int ACTIVATED_BY_IMMS = 7;
    int ACTIVATED_BY_IMMS = 8;
    /**
     * {@link android.view.inputmethod.InputMethodManager} is responding to
     * {@link com.android.internal.view.IInputMethodClient#setActive}.
     */
    int DEACTIVATED_BY_IMMS = 8;
    int DEACTIVATED_BY_IMMS = 9;
    /**
     * {@link com.android.server.inputmethod.InputMethodManagerService} is responding to
     * {@link com.android.internal.view.IInputSessionCallback#sessionCreated}.
     */
    int SESSION_CREATED_BY_IME = 9;
    int SESSION_CREATED_BY_IME = 10;
}
+19 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.inputmethod;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;

import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.Manifest;
@@ -710,6 +712,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     */
    int mImeWindowVis;

    /**
     * Checks if the client needs to start input.
     */
    private boolean mCurClientNeedStartInput = false;

    private AlertDialog.Builder mDialogBuilder;
    private AlertDialog mSwitchingDialog;
    private IBinder mSwitchingDialogToken = new Binder();
@@ -3425,10 +3432,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
                        + " attribute=" + attribute + ", token = " + windowToken);
            }
            if (attribute != null) {
            // Needs to start input when the same window focus gain but not with the same editor,
            // or when the current client needs to start input (e.g. when focusing the same
            // window after device turned screen on).
            if (attribute != null && (startInputReason != WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR
                    || mCurClientNeedStartInput)) {
                if (mIsInteractive) {
                    mCurClientNeedStartInput = false;
                }
                return startInputUncheckedLocked(cs, inputContext, missingMethods,
                        attribute, startInputFlags, startInputReason);
            }

            return new InputBindResult(
                    InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
                    null, null, null, -1, null);
@@ -4381,6 +4396,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    private void handleSetInteractive(final boolean interactive) {
        synchronized (mMethodMap) {
            mIsInteractive = interactive;
            if (!interactive) {
                mCurClientNeedStartInput = true;
            }
            updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);

            // Inform the current client of the change in active status