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

Commit 0209732a authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Add @GuardedBy to ImeVisibilityStateComputer

As a preparation before making ImeVisibilityStateComputer multi-user
aware, this CL adds missing @GuardedBy to ImeVisibilityStateComputer
as well as fixing up some missing synchronized blocks.

The core logic remain unchanged.

Bug: 349904272
Test: presubmit
Test: atest FrameworksInputMethodSystemServerTests:ImeVisibilityStateComputerTest
Flag: EXEMPT refactor
Change-Id: I15c2176c27cde06a54ea078322a653ad69440c5e
parent 22bba40d
Loading
Loading
Loading
Loading
+69 −12
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_IME_
import static com.android.server.inputmethod.InputMethodManagerService.computeImeDisplayIdForTarget;

import android.accessibilityservice.AccessibilityService;
import android.annotation.AnyThread;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -83,6 +84,7 @@ public final class ImeVisibilityStateComputer {
     * A map used to track the requested IME target window and its state. The key represents the
     * token of the window and the value is the corresponding IME window state.
     */
    @GuardedBy("ImfLock.class")
    private final WeakHashMap<IBinder, ImeTargetWindowState> mRequestWindowStateMap =
            new WeakHashMap<>();

@@ -93,6 +95,7 @@ public final class ImeVisibilityStateComputer {
     * @see InputMethodManager#HIDE_IMPLICIT_ONLY that system will not hide IME when the value is
     * {@code true}.
     */
    @GuardedBy("ImfLock.class")
    boolean mRequestedShowExplicitly;

    /**
@@ -101,23 +104,28 @@ public final class ImeVisibilityStateComputer {
     * @see InputMethodManager#SHOW_FORCED
     * @see InputMethodManager#HIDE_NOT_ALWAYS
     */
    @GuardedBy("ImfLock.class")
    boolean mShowForced;

    /**
     * Set if we last told the input method to show itself.
     */
    @GuardedBy("ImfLock.class")
    private boolean mInputShown;

    /**
     * Set if we called
     * {@link com.android.server.wm.ImeTargetVisibilityPolicy#showImeScreenshot(IBinder, int)}.
     */
    @GuardedBy("ImfLock.class")
    private boolean mRequestedImeScreenshot;

    /** The window token of the current visible IME layering target overlay. */
    @GuardedBy("ImfLock.class")
    private IBinder mCurVisibleImeLayeringOverlay;

    /** The window token of the current visible IME input target. */
    @GuardedBy("ImfLock.class")
    private IBinder mCurVisibleImeInputTarget;

    /** Represent the invalid IME visibility state */
@@ -203,25 +211,32 @@ public final class ImeVisibilityStateComputer {
            public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken,
                    @WindowManager.LayoutParams.WindowType int windowType, boolean visible,
                    boolean removed) {
                mCurVisibleImeLayeringOverlay =
                // Ignoring the starting window since it's ok to cover the IME target
                // window in temporary without affecting the IME visibility.
                        (visible && !removed && windowType != TYPE_APPLICATION_STARTING)
                final var overlay = (visible && !removed && windowType != TYPE_APPLICATION_STARTING)
                                ? overlayWindowToken : null;
                synchronized (ImfLock.class) {
                    mCurVisibleImeLayeringOverlay = overlay;

                }
            }

            @Override
            public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
                    boolean visibleRequested, boolean removed) {
                if (mCurVisibleImeInputTarget == imeInputTarget && (!visibleRequested || removed)
                synchronized (ImfLock.class) {
                    if (mCurVisibleImeInputTarget == imeInputTarget && (!visibleRequested
                            || removed)
                            && mCurVisibleImeLayeringOverlay != null) {
                        final int reason = SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE;
                        final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
                                ImeTracker.ORIGIN_SERVER, reason, false /* fromUser */);
                    mService.onApplyImeVisibilityFromComputer(imeInputTarget, statsToken,
                        mService.onApplyImeVisibilityFromComputerLocked(imeInputTarget, statsToken,
                                new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT, reason));
                    }
                mCurVisibleImeInputTarget = (visibleRequested && !removed) ? imeInputTarget : null;
                    mCurVisibleImeInputTarget =
                            (visibleRequested && !removed) ? imeInputTarget : null;
                }
            }
        });
    }
@@ -232,6 +247,7 @@ public final class ImeVisibilityStateComputer {
     * @param statsToken The token tracking the current IME request.
     * @return {@code true} when the show request can proceed.
     */
    @GuardedBy("ImfLock.class")
    boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken,
            @InputMethodManager.ShowFlags int showFlags) {
        if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
@@ -258,6 +274,7 @@ public final class ImeVisibilityStateComputer {
     * @param statsToken The token tracking the current IME request.
     * @return {@code true} when the hide request can proceed.
     */
    @GuardedBy("ImfLock.class")
    boolean canHideIme(@NonNull ImeTracker.Token statsToken,
            @InputMethodManager.HideFlags int hideFlags) {
        if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
@@ -279,6 +296,7 @@ public final class ImeVisibilityStateComputer {
     * Returns the show flags for IME. This translates from {@link InputMethodManager.ShowFlags}
     * to {@link InputMethod.ShowFlags}.
     */
    @GuardedBy("ImfLock.class")
    @InputMethod.ShowFlags
    int getShowFlagsForInputMethodServiceOnly() {
        int flags = 0;
@@ -294,6 +312,7 @@ public final class ImeVisibilityStateComputer {
     * Returns the show flags for IMM. This translates from {@link InputMethod.ShowFlags}
     * to {@link InputMethodManager.ShowFlags}.
     */
    @GuardedBy("ImfLock.class")
    @InputMethodManager.ShowFlags
    int getShowFlags() {
        int flags = 0;
@@ -305,12 +324,14 @@ public final class ImeVisibilityStateComputer {
        return flags;
    }

    @GuardedBy("ImfLock.class")
    void clearImeShowFlags() {
        mRequestedShowExplicitly = false;
        mShowForced = false;
        mInputShown = false;
    }

    @GuardedBy("ImfLock.class")
    int computeImeDisplayId(@NonNull ImeTargetWindowState state, int displayId) {
        final int displayToShowIme = computeImeDisplayIdForTarget(displayId, mImeDisplayValidator);
        state.setImeDisplayId(displayToShowIme);
@@ -328,6 +349,7 @@ public final class ImeVisibilityStateComputer {
     *                            visibility state, it could be {@link #STATE_SHOW_IME} or
     *                            {@link #STATE_HIDE_IME}.
     */
    @GuardedBy("ImfLock.class")
    void requestImeVisibility(IBinder windowToken, boolean showIme) {
        ImeTargetWindowState state = getOrCreateWindowState(windowToken);
        if (!mPolicy.mPendingA11yRequestingHideKeyboard) {
@@ -343,6 +365,7 @@ public final class ImeVisibilityStateComputer {
        setWindowStateInner(windowToken, state);
    }

    @GuardedBy("ImfLock.class")
    ImeTargetWindowState getOrCreateWindowState(IBinder windowToken) {
        ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
        if (state == null) {
@@ -351,11 +374,13 @@ public final class ImeVisibilityStateComputer {
        return state;
    }

    @GuardedBy("ImfLock.class")
    ImeTargetWindowState getWindowStateOrNull(IBinder windowToken) {
        ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
        return state;
    }

    @GuardedBy("ImfLock.class")
    void setWindowState(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
        final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
        if (state != null && newState.hasEditorFocused()
@@ -367,6 +392,7 @@ public final class ImeVisibilityStateComputer {
        setWindowStateInner(windowToken, newState);
    }

    @GuardedBy("ImfLock.class")
    private void setWindowStateInner(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
        if (DEBUG) Slog.d(TAG, "setWindowStateInner, windowToken=" + windowToken
                + ", state=" + newState);
@@ -391,6 +417,7 @@ public final class ImeVisibilityStateComputer {
        }
    }

    @GuardedBy("ImfLock.class")
    ImeVisibilityResult computeState(ImeTargetWindowState state, boolean allowVisible) {
        // TODO: Output the request IME visibility state according to the requested window state
        final int softInputVisibility = state.mSoftInputModeState & SOFT_INPUT_MASK_STATE;
@@ -540,6 +567,7 @@ public final class ImeVisibilityStateComputer {
        return null;
    }

    @GuardedBy("ImfLock.class")
    @VisibleForTesting
    ImeVisibilityResult onInteractiveChanged(IBinder windowToken, boolean interactive) {
        final ImeTargetWindowState state = getWindowStateOrNull(windowToken);
@@ -568,6 +596,7 @@ public final class ImeVisibilityStateComputer {
        return userData.mImeBindingState.mFocusedWindow;
    }

    @GuardedBy("ImfLock.class")
    IBinder getWindowTokenFrom(ImeTargetWindowState windowState) {
        for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
            final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
@@ -578,6 +607,7 @@ public final class ImeVisibilityStateComputer {
        return null;
    }

    @GuardedBy("ImfLock.class")
    boolean shouldRestoreImeVisibility(@NonNull ImeTargetWindowState state) {
        final int softInputMode = state.getSoftInputModeState();
        switch (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
@@ -591,14 +621,17 @@ public final class ImeVisibilityStateComputer {
        return mWindowManagerInternal.shouldRestoreImeVisibility(getWindowTokenFrom(state));
    }

    @GuardedBy("ImfLock.class")
    boolean isInputShown() {
        return mInputShown;
    }

    @GuardedBy("ImfLock.class")
    void setInputShown(boolean inputShown) {
        mInputShown = inputShown;
    }

    @GuardedBy("ImfLock.class")
    void dumpDebug(ProtoOutputStream proto, long fieldId) {
        proto.write(SHOW_EXPLICITLY_REQUESTED, mRequestedShowExplicitly);
        proto.write(SHOW_FORCED, mShowForced);
@@ -607,6 +640,7 @@ public final class ImeVisibilityStateComputer {
        proto.write(INPUT_SHOWN, mInputShown);
    }

    @GuardedBy("ImfLock.class")
    void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
        final Printer p = new PrintWriterPrinter(pw);
        p.println(prefix + "mRequestedShowExplicitly=" + mRequestedShowExplicitly
@@ -629,12 +663,14 @@ public final class ImeVisibilityStateComputer {
         *
         * This prevents the IME from showing when it otherwise may have shown.
         */
        @GuardedBy("ImfLock.class")
        private boolean mImeHiddenByDisplayPolicy;

        /**
         * Set when the accessibility service requests to hide IME by
         * {@link AccessibilityService.SoftKeyboardController#setShowMode}
         */
        @GuardedBy("ImfLock.class")
        private boolean mA11yRequestingNoSoftKeyboard;

        /**
@@ -643,16 +679,20 @@ public final class ImeVisibilityStateComputer {
         * {@link android.provider.Settings.Secure#ACCESSIBILITY_SOFT_KEYBOARD_MODE} without
         * changing the requested IME visible state.
         */
        @GuardedBy("ImfLock.class")
        private boolean mPendingA11yRequestingHideKeyboard;

        @GuardedBy("ImfLock.class")
        void setImeHiddenByDisplayPolicy(boolean hideIme) {
            mImeHiddenByDisplayPolicy = hideIme;
        }

        @GuardedBy("ImfLock.class")
        boolean isImeHiddenByDisplayPolicy() {
            return mImeHiddenByDisplayPolicy;
        }

        @GuardedBy("ImfLock.class")
        void setA11yRequestNoSoftKeyboard(int keyboardShowMode) {
            mA11yRequestingNoSoftKeyboard =
                    (keyboardShowMode & AccessibilityService.SHOW_MODE_MASK) == SHOW_MODE_HIDDEN;
@@ -661,11 +701,13 @@ public final class ImeVisibilityStateComputer {
            }
        }

        @GuardedBy("ImfLock.class")
        boolean isA11yRequestNoSoftKeyboard() {
            return mA11yRequestingNoSoftKeyboard;
        }
    }

    @GuardedBy("ImfLock.class")
    ImeVisibilityPolicy getImePolicy() {
        return mPolicy;
    }
@@ -721,63 +763,78 @@ public final class ImeVisibilityStateComputer {
        /**
         * Set if the client has asked for the input method to be shown.
         */
        @GuardedBy("ImfLock.class")
        private boolean mRequestedImeVisible;

        /**
         * A identifier for knowing the requester of {@link InputMethodManager#showSoftInput} or
         * {@link InputMethodManager#hideSoftInputFromWindow}.
         */
        @GuardedBy("ImfLock.class")
        private IBinder mRequestImeToken;

        /**
         * The IME target display id for which the latest startInput was called.
         */
        @GuardedBy("ImfLock.class")
        private int mImeDisplayId = DEFAULT_DISPLAY;

        @AnyThread
        boolean hasImeFocusChanged() {
            return mImeFocusChanged;
        }

        @AnyThread
        boolean hasEditorFocused() {
            return mHasFocusedEditor;
        }

        @AnyThread
        boolean isStartInputByGainFocus() {
            return mIsStartInputByGainFocus;
        }

        @AnyThread
        int getSoftInputModeState() {
            return mSoftInputModeState;
        }

        @AnyThread
        int getWindowFlags() {
            return mWindowFlags;
        }

        @AnyThread
        int getToolType() {
            return mToolType;
        }

        @GuardedBy("ImfLock.class")
        private void setImeDisplayId(int imeDisplayId) {
            mImeDisplayId = imeDisplayId;
        }

        @GuardedBy("ImfLock.class")
        int getImeDisplayId() {
            return mImeDisplayId;
        }

        @GuardedBy("ImfLock.class")
        private void setRequestedImeVisible(boolean requestedImeVisible) {
            mRequestedImeVisible = requestedImeVisible;
        }

        @GuardedBy("ImfLock.class")
        boolean isRequestedImeVisible() {
            return mRequestedImeVisible;
        }

        @GuardedBy("ImfLock.class")
        void setRequestImeToken(IBinder token) {
            mRequestImeToken = token;
        }

        @GuardedBy("ImfLock.class")
        IBinder getRequestImeToken() {
            return mRequestImeToken;
        }
+7 −8
Original line number Diff line number Diff line
@@ -4916,15 +4916,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        return mVisibilityApplier;
    }

    void onApplyImeVisibilityFromComputer(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
            @NonNull ImeVisibilityResult result) {
        synchronized (ImfLock.class) {
    @GuardedBy("ImfLock.class")
    void onApplyImeVisibilityFromComputerLocked(IBinder windowToken,
            @NonNull ImeTracker.Token statsToken, @NonNull ImeVisibilityResult result) {
        // TODO(b/305849394): Infer userId from windowToken
        final int userId = mCurrentUserId;
        mVisibilityApplier.applyImeVisibility(windowToken, statsToken, result.getState(),
                result.getReason(), userId);
    }
    }

    @GuardedBy("ImfLock.class")
    void setEnabledSessionLocked(SessionState session, @NonNull UserData userData) {
+183 −155
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.view.inputmethod.InputMethodManager;

import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.internal.annotations.GuardedBy;
import com.android.server.wm.ImeTargetChangeListener;
import com.android.server.wm.WindowManagerInternal;

@@ -93,6 +94,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes

    @Test
    public void testRequestImeVisibility_showImplicit() {
        synchronized (ImfLock.class) {
            initImeTargetWindowState(mWindowToken);
            boolean res = mComputer.onImeShowFlags(ImeTracker.Token.empty(),
                    InputMethodManager.SHOW_IMPLICIT);
@@ -106,9 +108,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes

            assertThat(mComputer.mRequestedShowExplicitly).isFalse();
        }
    }

    @Test
    public void testRequestImeVisibility_showExplicit() {
        synchronized (ImfLock.class) {
            initImeTargetWindowState(mWindowToken);
            boolean res = mComputer.onImeShowFlags(ImeTracker.Token.empty(), 0 /* showFlags */);
            mComputer.requestImeVisibility(mWindowToken, res);
@@ -121,6 +125,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes

            assertThat(mComputer.mRequestedShowExplicitly).isTrue();
        }
    }

    /**
     * This checks that the state after an explicit show request does not get reset during
@@ -128,6 +133,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
     */
    @Test
    public void testRequestImeVisibility_showExplicit_thenShowImplicit() {
        synchronized (ImfLock.class) {
            initImeTargetWindowState(mWindowToken);
            mComputer.onImeShowFlags(ImeTracker.Token.empty(), 0 /* showFlags */);
            assertThat(mComputer.mRequestedShowExplicitly).isTrue();
@@ -135,6 +141,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            mComputer.onImeShowFlags(null, InputMethodManager.SHOW_IMPLICIT);
            assertThat(mComputer.mRequestedShowExplicitly).isTrue();
        }
    }

    /**
     * This checks that the state after a forced show request does not get reset during
@@ -142,6 +149,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
     */
    @Test
    public void testRequestImeVisibility_showForced_thenShowExplicit() {
        synchronized (ImfLock.class) {
            initImeTargetWindowState(mWindowToken);
            mComputer.onImeShowFlags(ImeTracker.Token.empty(), InputMethodManager.SHOW_FORCED);
            assertThat(mComputer.mShowForced).isTrue();
@@ -149,9 +157,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            mComputer.onImeShowFlags(ImeTracker.Token.empty(), 0 /* showFlags */);
            assertThat(mComputer.mShowForced).isTrue();
        }
    }

    @Test
    public void testRequestImeVisibility_showImplicit_a11yNoImePolicy() {
        synchronized (ImfLock.class) {
            // Precondition: set AccessibilityService#SHOW_MODE_HIDDEN policy
            mComputer.getImePolicy().setA11yRequestNoSoftKeyboard(SHOW_MODE_HIDDEN);

@@ -168,9 +178,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes

            assertThat(mComputer.mRequestedShowExplicitly).isFalse();
        }
    }

    @Test
    public void testRequestImeVisibility_showImplicit_imeHiddenPolicy() {
        synchronized (ImfLock.class) {
            // Precondition: set IME hidden display policy before calling showSoftInput
            mComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);

@@ -187,9 +199,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes

            assertThat(mComputer.mRequestedShowExplicitly).isFalse();
        }
    }

    @Test
    public void testRequestImeVisibility_hideNotAlways() {
        synchronized (ImfLock.class) {
            // Precondition: ensure IME has shown before hiding request.
            mComputer.setInputShown(true);

@@ -204,9 +218,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            assertThat(state.getSoftInputModeState()).isEqualTo(SOFT_INPUT_STATE_UNCHANGED);
            assertThat(state.isRequestedImeVisible()).isFalse();
        }
    }

    @Test
    public void testComputeImeDisplayId() {
        synchronized (ImfLock.class) {
            final ImeTargetWindowState state = mComputer.getOrCreateWindowState(mWindowToken);

            mImeDisplayPolicy = DISPLAY_IME_POLICY_LOCAL;
@@ -228,9 +244,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            assertThat(mComputer.getImePolicy().isImeHiddenByDisplayPolicy()).isFalse();
            assertThat(state.getImeDisplayId()).isEqualTo(FALLBACK_DISPLAY_ID);
        }
    }

    @Test
    public void testComputeState_lastImeRequestedVisible_preserved_When_StateUnChanged() {
        synchronized (ImfLock.class) {
            // Assume the last IME targeted window has requested IME visible
            final IBinder lastImeTargetWindowToken = new Binder();
            mInputMethodManagerService.mLastImeTargetWindow = lastImeTargetWindowToken;
@@ -241,14 +259,17 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes

            // Verify when focusing the next window with STATE_UNCHANGED flag, the last IME
            // visibility state will be preserved to the current window state.
        final ImeTargetWindowState stateWithUnChangedFlag = initImeTargetWindowState(mWindowToken);
            final ImeTargetWindowState stateWithUnChangedFlag = initImeTargetWindowState(
                    mWindowToken);
            mComputer.computeState(stateWithUnChangedFlag, true /* allowVisible */);
            assertThat(stateWithUnChangedFlag.isRequestedImeVisible()).isEqualTo(
                    lastState.isRequestedImeVisible());
        }
    }

    @Test
    public void testOnInteractiveChanged() {
        synchronized (ImfLock.class) {
            mComputer.getOrCreateWindowState(mWindowToken);
            // Precondition: ensure IME has shown before hiding request.
            mComputer.requestImeVisibility(mWindowToken, true);
@@ -259,7 +280,8 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
                    mWindowToken, true /* interactive */);
            assertThat(result).isNull();

        // Show the IME screenshot to capture the last IME visible state when the device inactive.
            // Show the IME screenshot to capture the last IME visible state when the device
            // inactive.
            result = mComputer.onInteractiveChanged(mWindowToken, false /* interactive */);
            assertThat(result).isNotNull();
            assertThat(result.getState()).isEqualTo(STATE_SHOW_IME_SNAPSHOT);
@@ -271,9 +293,11 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            assertThat(result.getState()).isEqualTo(STATE_REMOVE_IME_SNAPSHOT);
            assertThat(result.getReason()).isEqualTo(REMOVE_IME_SCREENSHOT_FROM_IMMS);
        }
    }

    @Test
    public void testOnApplyImeVisibilityFromComputer() {
        synchronized (ImfLock.class) {
            final IBinder testImeTargetOverlay = new Binder();
            final IBinder testImeInputTarget = new Binder();

@@ -287,8 +311,10 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            final ArgumentCaptor<IBinder> targetCaptor = ArgumentCaptor.forClass(IBinder.class);
            final ArgumentCaptor<ImeVisibilityResult> resultCaptor = ArgumentCaptor.forClass(
                    ImeVisibilityResult.class);
        verify(mInputMethodManagerService).onApplyImeVisibilityFromComputer(targetCaptor.capture(),
                notNull() /* statsToken */, resultCaptor.capture());
            synchronized (ImfLock.class) {
                verify(mInputMethodManagerService).onApplyImeVisibilityFromComputerLocked(
                        targetCaptor.capture(), notNull() /* statsToken */, resultCaptor.capture());
            }
            final IBinder imeInputTarget = targetCaptor.getValue();
            final ImeVisibilityResult result = resultCaptor.getValue();

@@ -297,7 +323,9 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
            assertThat(result.getState()).isEqualTo(STATE_HIDE_IME_EXPLICIT);
            assertThat(result.getReason()).isEqualTo(HIDE_WHEN_INPUT_TARGET_INVISIBLE);
        }
    }

    @GuardedBy("ImfLock.class")
    private ImeTargetWindowState initImeTargetWindowState(IBinder windowToken) {
        final ImeTargetWindowState state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNCHANGED,
                0, true, true, true);