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

Commit 35d3f37b authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Tell the reason why IMM called startInput().

As a preparation to fix Bug 25373872, this CL introduces an additional
int parameter into the following two methods
  - IInputMethodManager.startInput()
  - IInputMethodManager.windowGainedFocus()
so that IMMS can know why IMM needs to start input.  Currently the
"startInputReason" parameter is used only for debug message only when
the OS is rebuilt with flipping IMMS#DEBUG to true.  Basically this
should have no impact in production builds except for a tiny overhead
of having one int parameter in some internal IPC calls.

Note that since 7663d80f [1] basically
IMMS#windowGainedFocus() has been a superset of IMMS#startInput().
Hence we should pass to "startInputReason" parameter to
IMMS#windowGainedFocus() as well as IMMS#startInput().

  [1]: Icb58bef75ef4bf9979f3e2ba88cea20db2e2c3fb

Bug: 25373872
Change-Id: Ia1fe120af7d71495c5f3a4fc0ec6390efb8240ca
parent 1fae5028
Loading
Loading
Loading
Loading
+29 −16
Original line number Diff line number Diff line
@@ -436,7 +436,8 @@ public final class InputMethodManager {
                        mCurId = res.id;
                        mBindSequence = res.sequence;
                    }
                    startInputInner(null, 0, 0, 0);
                    startInputInner(InputMethodClient.START_INPUT_REASON_BOUND_TO_IMMS,
                            null, 0, 0, 0);
                    return;
                }
                case MSG_UNBIND: {
@@ -461,7 +462,9 @@ public final class InputMethodManager {
                        startInput = mActive;
                    }
                    if (startInput) {
                        startInputInner(null, 0, 0, 0);
                        startInputInner(
                                InputMethodClient.START_INPUT_REASON_UNBOUND_FROM_IMMS, null, 0, 0,
                                0);
                    }
                    return;
                }
@@ -494,7 +497,10 @@ public final class InputMethodManager {
                            // In that case, we really should not call
                            // mServedInputConnection.finishComposingText.
                            if (checkFocusNoStartInput(mHasBeenInactive, false)) {
                                startInputInner(null, 0, 0, 0);
                                final int reason = active ?
                                        InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS :
                                        InputMethodClient.START_INPUT_REASON_DEACTIVATED_BY_IMMS;
                                startInputInner(reason, null, 0, 0, 0);
                            }
                        }
                    }
@@ -1119,17 +1125,22 @@ public final class InputMethodManager {
            mServedConnecting = true;
        }

        startInputInner(null, 0, 0, 0);
        startInputInner(InputMethodClient.START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API, null, 0,
                0, 0);
    }

    boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
    boolean startInputInner(@InputMethodClient.StartInputReason final int startInputReason,
            IBinder windowGainingFocus, int controlFlags, int softInputMode,
            int windowFlags) {
        final View view;
        synchronized (mH) {
            view = mServedView;
            
            // Make sure we have a window token for the served view.
            if (DEBUG) Log.v(TAG, "Starting input: view=" + view);
            if (DEBUG) {
                Log.v(TAG, "Starting input: view=" + view +
                        " reason=" + InputMethodClient.getStartInputReason(startInputReason));
            }
            if (view == null) {
                if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
                return false;
@@ -1157,7 +1168,7 @@ public final class InputMethodManager {
            vh.post(new Runnable() {
                @Override
                public void run() {
                    startInputInner(null, 0, 0, 0);
                    startInputInner(startInputReason, null, 0, 0, 0);
                }
            });
            return false;
@@ -1221,11 +1232,11 @@ public final class InputMethodManager {
                        + Integer.toHexString(controlFlags));
                InputBindResult res;
                if (windowGainingFocus != null) {
                    res = mService.windowGainedFocus(mClient, windowGainingFocus,
                    res = mService.windowGainedFocus(startInputReason, mClient, windowGainingFocus,
                            controlFlags, softInputMode, windowFlags,
                            tba, servedContext);
                } else {
                    res = mService.startInput(mClient,
                    res = mService.startInput(startInputReason, mClient,
                            servedContext, tba, controlFlags);
                }
                if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
@@ -1352,7 +1363,7 @@ public final class InputMethodManager {
     */
    public void checkFocus() {
        if (checkFocusNoStartInput(false, true)) {
            startInputInner(null, 0, 0, 0);
            startInputInner(InputMethodClient.START_INPUT_REASON_CHECK_FOCUS, null, 0, 0, 0);
        }
    }

@@ -1440,8 +1451,8 @@ public final class InputMethodManager {
            // should be done in conjunction with telling the system service
            // about the window gaining focus, to help make the transition
            // smooth.
            if (startInputInner(rootView.getWindowToken(),
                    controlFlags, softInputMode, windowFlags)) {
            if (startInputInner(InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN,
                    rootView.getWindowToken(), controlFlags, softInputMode, windowFlags)) {
                return;
            }
        }
@@ -1451,8 +1462,10 @@ public final class InputMethodManager {
        synchronized (mH) {
            try {
                if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
                mService.windowGainedFocus(mClient, rootView.getWindowToken(),
                        controlFlags, softInputMode, windowFlags, null, null);
                mService.windowGainedFocus(
                        InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
                        rootView.getWindowToken(), controlFlags, softInputMode, windowFlags, null,
                        null);
            } catch (RemoteException e) {
            }
        }
+9 −6
Original line number Diff line number Diff line
@@ -46,8 +46,9 @@ interface IInputMethodManager {
            in IInputContext inputContext, int uid, int pid);
    void removeClient(in IInputMethodClient client);

    InputBindResult startInput(in IInputMethodClient client,
            IInputContext inputContext, in EditorInfo attribute, int controlFlags);
    InputBindResult startInput(/* @InputMethodClient.StartInputReason */ int startInputReason,
            in IInputMethodClient client, IInputContext inputContext, in EditorInfo attribute,
            int controlFlags);
    void finishInput(in IInputMethodClient client);
    boolean showSoftInput(in IInputMethodClient client, int flags,
            in ResultReceiver resultReceiver);
@@ -55,9 +56,11 @@ interface IInputMethodManager {
            in ResultReceiver resultReceiver);
    // Report that a window has gained focus.  If 'attribute' is non-null,
    // this will also do a startInput.
    InputBindResult windowGainedFocus(in IInputMethodClient client, in IBinder windowToken,
            int controlFlags, int softInputMode, int windowFlags,
            in EditorInfo attribute, IInputContext inputContext);
    InputBindResult windowGainedFocus(
            /* @InputMethodClient.StartInputReason */ int startInputReason,
            in IInputMethodClient client, in IBinder windowToken, int controlFlags,
            int softInputMode, int windowFlags, in EditorInfo attribute,
            IInputContext inputContext);

    void showInputMethodPickerFromClient(in IInputMethodClient client,
            int auxiliarySubtypeMode);
+43 −0
Original line number Diff line number Diff line
@@ -23,6 +23,49 @@ import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.SOURCE;

public final class InputMethodClient {
    public static final int START_INPUT_REASON_UNSPECIFIED = 0;
    public static final int START_INPUT_REASON_WINDOW_FOCUS_GAIN = 1;
    public static final int START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY = 2;
    public static final int START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API = 3;
    public static final int START_INPUT_REASON_CHECK_FOCUS = 4;
    public static final int START_INPUT_REASON_BOUND_TO_IMMS = 5;
    public static final int START_INPUT_REASON_UNBOUND_FROM_IMMS = 6;
    public static final int START_INPUT_REASON_ACTIVATED_BY_IMMS = 7;
    public static final int START_INPUT_REASON_DEACTIVATED_BY_IMMS = 8;

    @Retention(SOURCE)
    @IntDef({START_INPUT_REASON_UNSPECIFIED, START_INPUT_REASON_WINDOW_FOCUS_GAIN,
            START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY,
            START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API, START_INPUT_REASON_CHECK_FOCUS,
            START_INPUT_REASON_BOUND_TO_IMMS, START_INPUT_REASON_ACTIVATED_BY_IMMS,
            START_INPUT_REASON_DEACTIVATED_BY_IMMS})
    public @interface StartInputReason {}

    public static String getStartInputReason(@StartInputReason final int reason) {
        switch (reason) {
            case START_INPUT_REASON_UNSPECIFIED:
                return "UNSPECIFIED";
            case START_INPUT_REASON_WINDOW_FOCUS_GAIN:
                return "WINDOW_FOCUS_GAIN";
            case START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY:
                return "WINDOW_FOCUS_GAIN_REPORT_ONLY";
            case START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API:
                return "APP_CALLED_RESTART_INPUT_API";
            case START_INPUT_REASON_CHECK_FOCUS:
                return "CHECK_FOCUS";
            case START_INPUT_REASON_BOUND_TO_IMMS:
                return "BOUND_TO_IMMS";
            case START_INPUT_REASON_UNBOUND_FROM_IMMS:
                return "UNBOUND_FROM_IMMS";
            case START_INPUT_REASON_ACTIVATED_BY_IMMS:
                return "ACTIVATED_BY_IMMS";
            case START_INPUT_REASON_DEACTIVATED_BY_IMMS:
                return "DEACTIVATED_BY_IMMS";
            default:
                return "Unknown=" + reason;
        }
    }

    public static final int UNBIND_REASON_UNSPECIFIED = 0;
    public static final int UNBIND_REASON_SWITCH_CLIENT = 1;
    public static final int UNBIND_REASON_SWITCH_IME = 2;
+31 −14
Original line number Diff line number Diff line
@@ -1290,8 +1290,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
    }

    InputBindResult startInputLocked(IInputMethodClient client,
            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
    InputBindResult startInputLocked(
            /* @InputMethodClient.StartInputReason */ final int startInputReason,
            IInputMethodClient client, IInputContext inputContext, EditorInfo attribute,
            int controlFlags) {
        // If no method is currently selected, do nothing.
        if (mCurMethodId == null) {
            return mNoBinding;
@@ -1320,8 +1322,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
    }

    InputBindResult startInputUncheckedLocked(@NonNull ClientState cs,
            IInputContext inputContext, @NonNull EditorInfo attribute, int controlFlags) {
    InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
            @NonNull EditorInfo attribute, int controlFlags) {
        // If no method is currently selected, do nothing.
        if (mCurMethodId == null) {
            return mNoBinding;
@@ -1442,15 +1444,26 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    }

    @Override
    public InputBindResult startInput(IInputMethodClient client,
            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
    public InputBindResult startInput(
            /* @InputMethodClient.StartInputReason */ final int startInputReason,
            IInputMethodClient client, IInputContext inputContext, EditorInfo attribute,
            int controlFlags) {
        if (!calledFromValidUser()) {
            return null;
        }
        synchronized (mMethodMap) {
            if (DEBUG) {
                Slog.v(TAG, "startInput: reason="
                        + InputMethodClient.getStartInputReason(startInputReason)
                        + " client = " + client.asBinder()
                        + " inputContext=" + inputContext
                        + " attribute=" + attribute
                        + " controlFlags=#" + Integer.toHexString(controlFlags));
            }
            final long ident = Binder.clearCallingIdentity();
            try {
                return startInputLocked(client, inputContext, attribute, controlFlags);
                return startInputLocked(startInputReason, client, inputContext, attribute,
                        controlFlags);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -2151,17 +2164,21 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    }

    @Override
    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
            int controlFlags, int softInputMode, int windowFlags,
            EditorInfo attribute, IInputContext inputContext) {
    public InputBindResult windowGainedFocus(
            /* @InputMethodClient.StartInputReason */ final int startInputReason,
            IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
            int windowFlags, EditorInfo attribute, IInputContext inputContext) {
        // Needs to check the validity before clearing calling identity
        final boolean calledFromValidUser = calledFromValidUser();

        InputBindResult res = null;
        long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mMethodMap) {
                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
                if (DEBUG) Slog.v(TAG, "windowGainedFocus: reason="
                        + InputMethodClient.getStartInputReason(startInputReason)
                        + " client=" + client.asBinder()
                        + " inputContext=" + inputContext
                        + " attribute=" + attribute
                        + " controlFlags=#" + Integer.toHexString(controlFlags)
                        + " softInputMode=#" + Integer.toHexString(softInputMode)
                        + " windowFlags=#" + Integer.toHexString(windowFlags));