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

Commit a3015cb3 authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Optimize IME Input Target Update

In [1] we started reporting the Binder (token) of the
startInputOrWindowGainedFocus window through InputMethodService
setImeWindowStatus, sending this value to WindowManagerService, but not
using it there.

However, this was quite slow, and in many cases was reported after the
IME started showing, so in [2] we modified this further to report the
token through InputMethodService dispatchStartInput, into
reportStartInputAsync, still without using the value in WindowManager.

Later in [3] we started using the reported token to update the IME
Control Target (and the IME Input Target). However, there is no need for
this flow to take a round trip through InputMethodService, as there are
no checks there, and we don't need to synchronize with the IME. Instead,
all the checks are done inside the InputMethodManagerService.

This optimizes the IME Input Target update flow by removing the round
trip into InputMethodService, aiming to reduce some flickers that could
be caused by slower updates.

  [1]: I54fb1faf513883a54293a756e4c9d2ae9453d778
  [2]: I032b91ce722a16b17518a5d88015c574d7d3e51b
  [3]: I9e8984b7e5aa989a53ece9e2576393f795b9ef94

Flag: android.view.inputmethod.optimize_ime_input_target_update
Bug: 427397699
Test: atest CtsInputMethodTestCases
Change-Id: I8e25eb09c89b40b52f28d7e18124e43ecb8dc99e
parent d40f9b88
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -825,7 +825,9 @@ public class InputMethodService extends AbstractInputMethodService {
        @Override
        public final void dispatchStartInput(@Nullable InputConnection inputConnection,
                @NonNull IInputMethod.StartInputParams params) {
            if (!Flags.optimizeImeInputTargetUpdate()) {
                mPrivOps.reportStartInputAsync(params.startInputToken);
            }
            onNavButtonFlagsChanged(params.navigationBarFlags);
            if (params.restarting) {
                restartInput(inputConnection, params.editorInfo);
+7 −0
Original line number Diff line number Diff line
@@ -204,3 +204,10 @@ flag {
  description: "Disables restoring the IME visibility after activity recreation (e.g. rotation), without an explicit show request."
  bug: "391859600"
}

flag {
  name: "optimize_ime_input_target_update"
  namespace: "input_method"
  description: "Optimizes the IME Input Target update flow by bypassing the InputMethodService, as there are no checks done there"
  bug: "427397699"
}
+14 −5
Original line number Diff line number Diff line
@@ -1887,15 +1887,16 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            userData.mBoundToMethod = true;
        }

        final var focusedWindow = userData.mImeBindingState.mFocusedWindow;
        final Binder startInputToken = new Binder();
        mImeTargetWindowMap.put(startInputToken, userData.mImeBindingState.mFocusedWindow);
        mImeTargetWindowMap.put(startInputToken, focusedWindow);
        final boolean restarting = !initial;
        final StartInputInfo info = new StartInputInfo(userId,
                bindingController.getCurToken(), bindingController.getCurTokenDisplayId(),
                bindingController.getCurId(), startInputReason,
                restarting, UserHandle.getUserId(userData.mCurClient.mUid),
                userData.mCurClient.mSelfReportedDisplayId,
                userData.mImeBindingState.mFocusedWindow, userData.mCurEditorInfo,
                focusedWindow, userData.mCurEditorInfo,
                userData.mImeBindingState.mFocusedWindowSoftInputMode,
                bindingController.getSequenceNumber());
        mStartInputHistory.addEntry(info);
@@ -1917,15 +1918,20 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        setEnabledSessionLocked(session, userData);
        session.mMethod.startInput(startInputToken, userData.mCurInputConnection,
                userData.mCurEditorInfo, restarting, navButtonFlags, userData.mCurImeDispatcher);
        if (isShowRequestedForCurrentWindow(userId)
                && userData.mImeBindingState.mFocusedWindow != null) {
        if (Flags.optimizeImeInputTargetUpdate()) {
            if (focusedWindow != null) {
                mWindowManagerInternal.updateImeTargetWindow(focusedWindow);
            }
            userData.mVisibilityStateComputer.setLastImeTargetWindow(focusedWindow);
        }
        if (isShowRequestedForCurrentWindow(userId) && focusedWindow != null) {
            ProtoLog.v(IMMS_DEBUG, "Attach new input asks to show input");
            // Re-use current statsToken, if it exists.
            final var statsToken = userData.mCurStatsToken != null ? userData.mCurStatsToken
                    : createStatsTokenForFocusedClient(true /* show */,
                            SoftInputShowHideReason.ATTACH_NEW_INPUT, userId);
            userData.mCurStatsToken = null;
            showCurrentInputInternal(userData.mImeBindingState.mFocusedWindow, statsToken);
            showCurrentInputInternal(focusedWindow, statsToken);
        }

        final var curId = bindingController.getCurId();
@@ -2777,6 +2783,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    @BinderThread
    @GuardedBy("ImfLock.class")
    private void reportStartInputLocked(IBinder startInputToken, @NonNull UserData userData) {
        if (Flags.optimizeImeInputTargetUpdate()) {
            return;
        }
        final IBinder targetWindowToken = mImeTargetWindowMap.get(startInputToken);
        if (targetWindowToken != null) {
            mWindowManagerInternal.updateImeTargetWindow(targetWindowToken);