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

Commit a5ebd6b7 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Remove ZeroJankProxy.Callback#isInputShownLocked()

This reworks our previous CL [1], which addressed an observable
unintentional behavior change when ZeroJankProxy is enabled, in a way
that ZeroJankProxy.Callback does not need to have

  ZeroJankProxy.Callback#isInputShownLocked(),

which will soon need to become concurrent multi-user aware.

The problem is when it becomes concurrent multi-user aware,
ZeroJankProxy needs to know whose IME is in use, which is tricky
because the IME user ID is dynamically resolved with

  InputMethodManagerService#resolveImeUserIdLocked().

The core logic should remain unchanged.

 [1]: Ie2f262128eb32db5a7922373fdfaebd2945ea36a
      2aed6844

Bug: 349904272
Test: presubmit
Flag: android.view.inputmethod.use_zero_jank_proxy
Change-Id: Ib719f6018965c3554c8c2d8c2050ad51962d8a25
parent 755a500c
Loading
Loading
Loading
Loading
+108 −72
Original line number Diff line number Diff line
@@ -1812,8 +1812,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    }

    @GuardedBy("ImfLock.class")
    @Override
    public boolean isInputShownLocked() {
    private boolean isInputShownLocked() {
        return mVisibilityStateComputer.isInputShown();
    }

@@ -3004,17 +3003,41 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        }
    }

    @GuardedBy("ImfLock.class")
    private void sendResultReceiverFailureLocked(@Nullable ResultReceiver resultReceiver) {
        final boolean isInputShown = mVisibilityStateComputer.isInputShown();
        resultReceiver.send(isInputShown
                ? InputMethodManager.RESULT_UNCHANGED_SHOWN
                : InputMethodManager.RESULT_UNCHANGED_HIDDEN, null);
    }

    @Override
    public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
            @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
            int lastClickToolType, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason) {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
        final int uid = Binder.getCallingUid();
        final int callingUserId = UserHandle.getUserId(uid);
        ImeTracing.getInstance().triggerManagerServiceDump(
                "InputMethodManagerService#showSoftInput", mDumper);
        synchronized (ImfLock.class) {
            final boolean result = showSoftInputLocked(client, windowToken, statsToken, flags,
                    lastClickToolType, resultReceiver, reason);
            // When ZeroJankProxy is enabled, the app has already received "true" as the return
            // value, and expect "resultReceiver" to be notified later. See b/327751155.
            if (!result && Flags.useZeroJankProxy()) {
                sendResultReceiverFailureLocked(resultReceiver);
            }
            return result;  // ignored when ZeroJankProxy is enabled.
        }
    }

    @GuardedBy("ImfLock.class")
    private boolean showSoftInputLocked(IInputMethodClient client, IBinder windowToken,
            @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
            int lastClickToolType, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason) {
        final int uid = Binder.getCallingUid();
        final int callingUserId = UserHandle.getUserId(uid);
        final int userId = resolveImeUserIdLocked(callingUserId);
        if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken,
                userId)) {
@@ -3051,7 +3074,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
    }

    // TODO(b/353463205) check callers to see if we can make statsToken @NonNull
    boolean showCurrentInputInternal(IBinder windowToken, @Nullable ImeTracker.Token statsToken) {
@@ -3444,11 +3466,26 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
            @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
        final int uid = Binder.getCallingUid();
        final int callingUserId = UserHandle.getUserId(uid);
        ImeTracing.getInstance().triggerManagerServiceDump(
                "InputMethodManagerService#hideSoftInput", mDumper);
        synchronized (ImfLock.class) {
            final boolean result = hideSoftInputLocked(client, windowToken, statsToken, flags,
                    resultReceiver, reason);
            // When ZeroJankProxy is enabled, the app has already received "true" as the return
            // value, and expect "resultReceiver" to be notified later. See b/327751155.
            if (!result && Flags.useZeroJankProxy()) {
                sendResultReceiverFailureLocked(resultReceiver);
            }
            return result;  // ignored when ZeroJankProxy is enabled.
        }
    }

    @GuardedBy("ImfLock.class")
    private boolean hideSoftInputLocked(IInputMethodClient client, IBinder windowToken,
            @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
        final int uid = Binder.getCallingUid();
        final int callingUserId = UserHandle.getUserId(uid);
        final int userId = resolveImeUserIdLocked(callingUserId);
        if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken, userId)) {
            if (isInputShownLocked()) {
@@ -3481,15 +3518,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                }
                return false;
            } else {
                    return InputMethodManagerService.this.hideCurrentInputLocked(windowToken,
                            statsToken, flags, resultReceiver, reason, userId);
                return InputMethodManagerService.this.hideCurrentInputLocked(
                        windowToken, statsToken, flags, resultReceiver, reason, userId);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
    }

    @Override
    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
+4 −36
Original line number Diff line number Diff line
@@ -86,8 +86,6 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback {
    interface Callback extends IInputMethodManagerImpl.Callback {
        @GuardedBy("ImfLock.class")
        ClientState getClientStateLocked(IInputMethodClient client);
        @GuardedBy("ImfLock.class")
        boolean isInputShownLocked();
    }

    private final Callback mInner;
@@ -178,19 +176,8 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback {
            @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
            @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason) {
        offload(
                () -> {
                    if (!mInner.showSoftInput(
                            client,
                            windowToken,
                            statsToken,
                            flags,
                            lastClickToolType,
                            resultReceiver,
                            reason)) {
                        sendResultReceiverFailure(resultReceiver);
                    }
                });
        offload(() -> mInner.showSoftInput(
                client, windowToken, statsToken, flags, lastClickToolType, resultReceiver, reason));
        return true;
    }

@@ -198,30 +185,11 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback {
    public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
            @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
        offload(
                () -> {
                    if (!mInner.hideSoftInput(
                            client, windowToken, statsToken, flags, resultReceiver, reason)) {
                        sendResultReceiverFailure(resultReceiver);
                    }
                });
        offload(() -> mInner.hideSoftInput(
                client, windowToken, statsToken, flags, resultReceiver, reason));
        return true;
    }

    private void sendResultReceiverFailure(@Nullable ResultReceiver resultReceiver) {
        if (resultReceiver == null) {
            return;
        }
        final boolean isInputShown;
        synchronized (ImfLock.class) {
            isInputShown = mInner.isInputShownLocked();
        }
        resultReceiver.send(isInputShown
                        ? InputMethodManager.RESULT_UNCHANGED_SHOWN
                        : InputMethodManager.RESULT_UNCHANGED_HIDDEN,
                null);
    }

    @Override
    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
    public void hideSoftInputFromServerForTest() {