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

Commit deca4f9f authored by Antonio Kantek's avatar Antonio Kantek
Browse files

Make ImeVisibiltyApplier show/hide IME per user

Add `userId` parameter to ImeVisibilityApplier methods (except
updateImeLayeringByTarget), so it can apply the logic against the target
user.

This is a pre-requisite change to make InputMethodBindingController per
user.

This change shouldn't introduce any observable behavior break
when running on single user mode.

Bug: 325515685
Test: atest FrameworksInputMethodSystemServerTests
Test: atest CtsInputMethodTestCases
Test: atest FrameworksServicesTests
Test: atest --host FrameworksInputMethodSystemServerTestsRavenwood
Flag: EXEMPT refactor

Change-Id: I2d263efe0b26212e3d4b593db7ccc973972fca39
parent b1f17462
Loading
Loading
Loading
Loading
+18 −15
Original line number Original line Diff line number Diff line
@@ -69,7 +69,6 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
    @NonNull
    @NonNull
    private final ImeTargetVisibilityPolicy mImeTargetVisibilityPolicy;
    private final ImeTargetVisibilityPolicy mImeTargetVisibilityPolicy;



    DefaultImeVisibilityApplier(InputMethodManagerService service) {
    DefaultImeVisibilityApplier(InputMethodManagerService service) {
        mService = service;
        mService = service;
        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
@@ -80,8 +79,9 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
    @Override
    @Override
    public void performShowIme(IBinder showInputToken, @NonNull ImeTracker.Token statsToken,
    public void performShowIme(IBinder showInputToken, @NonNull ImeTracker.Token statsToken,
            @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
            @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason) {
            @SoftInputShowHideReason int reason, @UserIdInt int userId) {
        final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
        final var bindingController = mService.getInputMethodBindingController(userId);
        final IInputMethodInvoker curMethod = bindingController.getCurMethod();
        if (curMethod != null) {
        if (curMethod != null) {
            if (DEBUG) {
            if (DEBUG) {
                Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
                Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
@@ -99,7 +99,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
                                    mService.mImeBindingState.mFocusedWindowSoftInputMode));
                                    mService.mImeBindingState.mFocusedWindowSoftInputMode));
                }
                }
                mService.onShowHideSoftInputRequested(true /* show */, showInputToken, reason,
                mService.onShowHideSoftInputRequested(true /* show */, showInputToken, reason,
                        statsToken);
                        statsToken, userId);
            }
            }
        }
        }
    }
    }
@@ -107,8 +107,10 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
    @Override
    @Override
    public void performHideIme(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken,
    public void performHideIme(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken,
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason,
        final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
            @UserIdInt int userId) {
        final var bindingController = mService.getInputMethodBindingController(userId);
        final IInputMethodInvoker curMethod = bindingController.getCurMethod();
        if (curMethod != null) {
        if (curMethod != null) {
            // The IME will report its visible state again after the following message finally
            // The IME will report its visible state again after the following message finally
            // delivered to the IME process as an IPC.  Hence the inconsistency between
            // delivered to the IME process as an IPC.  Hence the inconsistency between
@@ -130,7 +132,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
                                    mService.mImeBindingState.mFocusedWindowSoftInputMode));
                                    mService.mImeBindingState.mFocusedWindowSoftInputMode));
                }
                }
                mService.onShowHideSoftInputRequested(false /* show */, hideInputToken, reason,
                mService.onShowHideSoftInputRequested(false /* show */, hideInputToken, reason,
                        statsToken);
                        statsToken, userId);
            }
            }
        }
        }
    }
    }
@@ -203,10 +205,10 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
                }
                }
                break;
                break;
            case STATE_SHOW_IME_SNAPSHOT:
            case STATE_SHOW_IME_SNAPSHOT:
                showImeScreenshot(windowToken, displayIdToShowIme);
                showImeScreenshot(windowToken, displayIdToShowIme, userId);
                break;
                break;
            case STATE_REMOVE_IME_SNAPSHOT:
            case STATE_REMOVE_IME_SNAPSHOT:
                removeImeScreenshot(displayIdToShowIme);
                removeImeScreenshot(displayIdToShowIme, userId);
                break;
                break;
            default:
            default:
                throw new IllegalArgumentException("Invalid IME visibility state: " + state);
                throw new IllegalArgumentException("Invalid IME visibility state: " + state);
@@ -215,10 +217,11 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {


    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
    @Override
    @Override
    public boolean showImeScreenshot(@NonNull IBinder imeTarget, int displayId) {
    public boolean showImeScreenshot(@NonNull IBinder imeTarget, int displayId,
            @UserIdInt int userId) {
        if (mImeTargetVisibilityPolicy.showImeScreenshot(imeTarget, displayId)) {
        if (mImeTargetVisibilityPolicy.showImeScreenshot(imeTarget, displayId)) {
            mService.onShowHideSoftInputRequested(false /* show */, imeTarget,
            mService.onShowHideSoftInputRequested(false /* show */, imeTarget,
                    SHOW_IME_SCREENSHOT_FROM_IMMS, null /* statsToken */);
                    SHOW_IME_SCREENSHOT_FROM_IMMS, null /* statsToken */, userId);
            return true;
            return true;
        }
        }
        return false;
        return false;
@@ -226,11 +229,11 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {


    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
    @Override
    @Override
    public boolean removeImeScreenshot(int displayId) {
    public boolean removeImeScreenshot(int displayId, @UserIdInt int userId) {
        if (mImeTargetVisibilityPolicy.removeImeScreenshot(displayId)) {
        if (mImeTargetVisibilityPolicy.removeImeScreenshot(displayId)) {
            mService.onShowHideSoftInputRequested(false /* show */,
            mService.onShowHideSoftInputRequested(false /* show */,
                    mService.mImeBindingState.mFocusedWindow,
                    mService.mImeBindingState.mFocusedWindow,
                    REMOVE_IME_SCREENSHOT_FROM_IMMS, null /* statsToken */);
                    REMOVE_IME_SCREENSHOT_FROM_IMMS, null /* statsToken */, userId);
            return true;
            return true;
        }
        }
        return false;
        return false;
+34 −24
Original line number Original line Diff line number Diff line
@@ -33,38 +33,45 @@ interface ImeVisibilityApplier {
    /**
    /**
     * Performs showing IME on top of the given window.
     * Performs showing IME on top of the given window.
     *
     *
     * @param showInputToken A token that represents the requester to show IME.
     * @param showInputToken a token that represents the requester to show IME
     * @param statsToken     The token tracking the current IME request.
     * @param statsToken     the token tracking the current IME request
     * @param resultReceiver If non-null, this will be called back to the caller when
     * @param resultReceiver if non-null, this will be called back to the caller when
     *                       it has processed request to tell what it has done.
     *                       it has processed request to tell what it has done
     * @param reason         The reason for requesting to show IME.
     * @param reason         yhe reason for requesting to show IME
     * @param userId         the target user when performing show IME
     */
     */
    default void performShowIme(IBinder showInputToken, @NonNull ImeTracker.Token statsToken,
    default void performShowIme(IBinder showInputToken, @NonNull ImeTracker.Token statsToken,
            @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
            @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason) {}
            @SoftInputShowHideReason int reason, @UserIdInt int userId) {
    }


    /**
    /**
     * Performs hiding IME to the given window
     * Performs hiding IME to the given window
     *
     *
     * @param hideInputToken A token that represents the requester to hide IME.
     * @param hideInputToken a token that represents the requester to hide IME
     * @param statsToken     The token tracking the current IME request.
     * @param statsToken     the token tracking the current IME request
     * @param resultReceiver If non-null, this will be called back to the caller when
     * @param resultReceiver if non-null, this will be called back to the caller when
     *                       it has processed request to tell what it has done.
     *                       it has processed request to tell what it has done
     * @param reason         The reason for requesting to hide IME.
     * @param reason         the reason for requesting to hide IME
     * @param userId         the target user when performing hide IME
     */
     */
    default void performHideIme(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken,
    default void performHideIme(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken,
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason,
            @UserIdInt int userId) {
    }


    /**
    /**
     * Applies the IME visibility from {@link android.inputmethodservice.InputMethodService} with
     * Applies the IME visibility from {@link android.inputmethodservice.InputMethodService} with
     * according to the given visibility state.
     * according to the given visibility state.
     *
     *
     * @param windowToken The token of a window for applying the IME visibility
     * @param windowToken the token of a window for applying the IME visibility
     * @param statsToken  The token tracking the current IME request.
     * @param statsToken  the token tracking the current IME request
     * @param state       The new IME visibility state for the applier to handle
     * @param state       the new IME visibility state for the applier to handle
     * @param userId      the target user when applying the IME visibility state
     */
     */
    default void applyImeVisibility(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
    default void applyImeVisibility(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
            @ImeVisibilityStateComputer.VisibilityState int state, @UserIdInt int userId) {}
            @ImeVisibilityStateComputer.VisibilityState int state, @UserIdInt int userId) {
    }


    /**
    /**
     * Updates the IME Z-ordering relative to the given window.
     * Updates the IME Z-ordering relative to the given window.
@@ -72,7 +79,7 @@ interface ImeVisibilityApplier {
     * This used to adjust the IME relative layer of the window during
     * This used to adjust the IME relative layer of the window during
     * {@link InputMethodManagerService} is in switching IME clients.
     * {@link InputMethodManagerService} is in switching IME clients.
     *
     *
     * @param windowToken The token of a window to update the Z-ordering relative to the IME.
     * @param windowToken the token of a window to update the Z-ordering relative to the IME
     */
     */
    default void updateImeLayeringByTarget(IBinder windowToken) {
    default void updateImeLayeringByTarget(IBinder windowToken) {
        // TODO: add a method in WindowManagerInternal to call DC#updateImeInputAndControlTarget
        // TODO: add a method in WindowManagerInternal to call DC#updateImeInputAndControlTarget
@@ -82,21 +89,24 @@ interface ImeVisibilityApplier {
    /**
    /**
     * Shows the IME screenshot and attach it to the given IME target window.
     * Shows the IME screenshot and attach it to the given IME target window.
     *
     *
     * @param windowToken The token of a window to show the IME screenshot.
     * @param windowToken the token of a window to show the IME screenshot
     * @param displayId The unique id to identify the display
     * @param displayId   the unique id to identify the display
     * @return {@code true} if success, {@code false} otherwise.
     * @param userId      the target user when when showing the IME screenshot
     * @return {@code true} if success, {@code false} otherwise
     */
     */
    default boolean showImeScreenshot(@NonNull IBinder windowToken, int displayId) {
    default boolean showImeScreenshot(@NonNull IBinder windowToken, int displayId,
            @UserIdInt int userId) {
        return false;
        return false;
    }
    }


    /**
    /**
     * Removes the IME screenshot on the given display.
     * Removes the IME screenshot on the given display.
     *
     *
     * @param displayId The target display of showing IME screenshot.
     * @param displayId the target display of showing IME screenshot
     * @return {@code true} if success, {@code false} otherwise.
     * @param userId    the target user of showing IME screenshot
     * @return {@code true} if success, {@code false} otherwise
     */
     */
    default boolean removeImeScreenshot(int displayId) {
    default boolean removeImeScreenshot(int displayId, @UserIdInt int userId) {
        return false;
        return false;
    }
    }
}
}
+13 −8
Original line number Original line Diff line number Diff line
@@ -3519,10 +3519,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.


        mVisibilityStateComputer.requestImeVisibility(windowToken, true);
        mVisibilityStateComputer.requestImeVisibility(windowToken, true);


        final int userId = mCurrentUserId;
        // Ensure binding the connection when IME is going to show.
        // Ensure binding the connection when IME is going to show.
        final var bindingController = getInputMethodBindingController(mCurrentUserId);
        final var bindingController = getInputMethodBindingController(userId);
        bindingController.setCurrentMethodVisible();
        bindingController.setCurrentMethodVisible();
        final IInputMethodInvoker curMethod = getCurMethodLocked();
        final IInputMethodInvoker curMethod = bindingController.getCurMethod();
        ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
        ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
        final boolean readyToDispatchToIme;
        final boolean readyToDispatchToIme;
        if (Flags.deferShowSoftInputUntilSessionCreation()) {
        if (Flags.deferShowSoftInputUntilSessionCreation()) {
@@ -3542,7 +3543,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            }
            }
            mVisibilityApplier.performShowIme(windowToken, statsToken,
            mVisibilityApplier.performShowIme(windowToken, statsToken,
                    mVisibilityStateComputer.getShowFlagsForInputMethodServiceOnly(),
                    mVisibilityStateComputer.getShowFlagsForInputMethodServiceOnly(),
                    resultReceiver, reason);
                    resultReceiver, reason, userId);
            mVisibilityStateComputer.setInputShown(true);
            mVisibilityStateComputer.setInputShown(true);
            return true;
            return true;
        } else {
        } else {
@@ -3654,7 +3655,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        // since Android Eclair.  That's why we need to accept IMM#hideSoftInput() even when only
        // since Android Eclair.  That's why we need to accept IMM#hideSoftInput() even when only
        // IMMS#InputShown indicates that the software keyboard is shown.
        // IMMS#InputShown indicates that the software keyboard is shown.
        // TODO(b/246309664): Clean up IMMS#mImeWindowVis
        // TODO(b/246309664): Clean up IMMS#mImeWindowVis
        IInputMethodInvoker curMethod = getCurMethodLocked();
        final int userId = mCurrentUserId;
        final var bindingController = getInputMethodBindingController(userId);
        IInputMethodInvoker curMethod = bindingController.getCurMethod();
        final boolean shouldHideSoftInput = curMethod != null
        final boolean shouldHideSoftInput = curMethod != null
                && (isInputShownLocked() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
                && (isInputShownLocked() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);


@@ -3665,11 +3668,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
            // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
            // the final state.
            // the final state.
            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
            mVisibilityApplier.performHideIme(windowToken, statsToken, resultReceiver, reason);
            mVisibilityApplier.performHideIme(windowToken, statsToken, resultReceiver, reason,
                    userId);
        } else {
        } else {
            ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
            ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
        }
        }
        final var bindingController = getInputMethodBindingController(mCurrentUserId);
        bindingController.setCurrentMethodNotVisible();
        bindingController.setCurrentMethodNotVisible();
        mVisibilityStateComputer.clearImeShowFlags();
        mVisibilityStateComputer.clearImeShowFlags();
        // Cancel existing statsToken for show IME as we got a hide request.
        // Cancel existing statsToken for show IME as we got a hide request.
@@ -4735,12 +4738,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
     */
     */
    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
    void onShowHideSoftInputRequested(boolean show, IBinder requestImeToken,
    void onShowHideSoftInputRequested(boolean show, IBinder requestImeToken,
            @SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken) {
            @SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken,
            @UserIdInt int userId) {
        final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(requestImeToken);
        final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(requestImeToken);
        final var bindingController = getInputMethodBindingController(userId);
        final WindowManagerInternal.ImeTargetInfo info =
        final WindowManagerInternal.ImeTargetInfo info =
                mWindowManagerInternal.onToggleImeRequested(
                mWindowManagerInternal.onToggleImeRequested(
                        show, mImeBindingState.mFocusedWindow, requestToken,
                        show, mImeBindingState.mFocusedWindow, requestToken,
                        getCurTokenDisplayIdLocked());
                        bindingController.getCurTokenDisplayId());
        mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry(
        mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry(
                mImeBindingState.mFocusedWindowClient, mImeBindingState.mFocusedWindowEditorInfo,
                mImeBindingState.mFocusedWindowClient, mImeBindingState.mFocusedWindowEditorInfo,
                info.focusedWindowName, mImeBindingState.mFocusedWindowSoftInputMode, reason,
                info.focusedWindowName, mImeBindingState.mFocusedWindowSoftInputMode, reason,
+4 −4
Original line number Original line Diff line number Diff line
@@ -87,7 +87,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            mVisibilityApplier.performShowIme(new Binder() /* showInputToken */,
            mVisibilityApplier.performShowIme(new Binder() /* showInputToken */,
                    ImeTracker.Token.empty(), 0 /* showFlags */, null /* resultReceiver */,
                    ImeTracker.Token.empty(), 0 /* showFlags */, null /* resultReceiver */,
                    SHOW_SOFT_INPUT);
                    SHOW_SOFT_INPUT, mUserId);
        }
        }
        verifyShowSoftInput(false, true, 0 /* showFlags */);
        verifyShowSoftInput(false, true, 0 /* showFlags */);
    }
    }
@@ -96,7 +96,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
    public void testPerformHideIme() throws Exception {
    public void testPerformHideIme() throws Exception {
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            mVisibilityApplier.performHideIme(new Binder() /* hideInputToken */,
            mVisibilityApplier.performHideIme(new Binder() /* hideInputToken */,
                    ImeTracker.Token.empty(), null /* resultReceiver */, HIDE_SOFT_INPUT);
                    ImeTracker.Token.empty(), null /* resultReceiver */, HIDE_SOFT_INPUT, mUserId);
        }
        }
        verifyHideSoftInput(false, true);
        verifyHideSoftInput(false, true);
    }
    }
@@ -186,7 +186,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
    @Test
    @Test
    public void testShowImeScreenshot() {
    public void testShowImeScreenshot() {
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            mVisibilityApplier.showImeScreenshot(mWindowToken, Display.DEFAULT_DISPLAY);
            mVisibilityApplier.showImeScreenshot(mWindowToken, Display.DEFAULT_DISPLAY, mUserId);
        }
        }


        verify(mMockImeTargetVisibilityPolicy).showImeScreenshot(eq(mWindowToken),
        verify(mMockImeTargetVisibilityPolicy).showImeScreenshot(eq(mWindowToken),
@@ -196,7 +196,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
    @Test
    @Test
    public void testRemoveImeScreenshot() {
    public void testRemoveImeScreenshot() {
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            mVisibilityApplier.removeImeScreenshot(Display.DEFAULT_DISPLAY);
            mVisibilityApplier.removeImeScreenshot(Display.DEFAULT_DISPLAY, mUserId);
        }
        }


        verify(mMockImeTargetVisibilityPolicy).removeImeScreenshot(eq(Display.DEFAULT_DISPLAY));
        verify(mMockImeTargetVisibilityPolicy).removeImeScreenshot(eq(Display.DEFAULT_DISPLAY));