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

Commit 1b299b59 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move mImeWindowVis and mBackDisposition to binding controller" into main

parents 2cbb144c 65b8a795
Loading
Loading
Loading
Loading
+47 −1
Original line number Original line Diff line number Diff line
@@ -96,6 +96,32 @@ final class InputMethodBindingController {
    @GuardedBy("ImfLock.class") private int mDisplayIdToShowIme = INVALID_DISPLAY;
    @GuardedBy("ImfLock.class") private int mDisplayIdToShowIme = INVALID_DISPLAY;
    @GuardedBy("ImfLock.class") private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT;
    @GuardedBy("ImfLock.class") private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT;


    /**
     * A set of status bits regarding the active IME.
     *
     * <p>This value is a combination of following two bits:</p>
     * <dl>
     * <dt>{@link InputMethodService#IME_ACTIVE}</dt>
     * <dd>
     *   If this bit is ON, connected IME is ready to accept touch/key events.
     * </dd>
     * <dt>{@link InputMethodService#IME_VISIBLE}</dt>
     * <dd>
     *   If this bit is ON, some of IME view, e.g. software input, candidate view, is visible.
     * </dd>
     * <dt>{@link InputMethodService#IME_INVISIBLE}</dt>
     * <dd> If this bit is ON, IME is ready with views from last EditorInfo but is
     *    currently invisible.
     * </dd>
     * </dl>
     * <em>Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and
     * {@link InputMethodBindingController#unbindCurrentMethod()}.</em>
     */
    @GuardedBy("ImfLock.class") private int mImeWindowVis;

    @GuardedBy("ImfLock.class")
    private int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;

    @Nullable private CountDownLatch mLatchForTesting;
    @Nullable private CountDownLatch mLatchForTesting;


    /**
    /**
@@ -473,7 +499,7 @@ final class InputMethodBindingController {


        if (getCurToken() != null) {
        if (getCurToken() != null) {
            removeCurrentToken();
            removeCurrentToken();
            mService.resetSystemUiLocked();
            mService.resetSystemUiLocked(this);
            mAutofillController.onResetSystemUi();
            mAutofillController.onResetSystemUi();
        }
        }


@@ -662,4 +688,24 @@ final class InputMethodBindingController {
    int getUserId() {
    int getUserId() {
        return mUserId;
        return mUserId;
    }
    }

    @GuardedBy("ImfLock.class")
    void setImeWindowVis(int imeWindowVis) {
        mImeWindowVis = imeWindowVis;
    }

    @GuardedBy("ImfLock.class")
    int getImeWindowVis() {
        return mImeWindowVis;
    }

    @GuardedBy("ImfLock.class")
    int getBackDisposition() {
        return mBackDisposition;
    }

    @GuardedBy("ImfLock.class")
    void setBackDisposition(int backDisposition) {
        mBackDisposition = backDisposition;
    }
}
}
+47 −61
Original line number Original line Diff line number Diff line
@@ -552,33 +552,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    @MultiUserUnawareField
    @MultiUserUnawareField
    boolean mIsInteractive = true;
    boolean mIsInteractive = true;


    @MultiUserUnawareField
    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;

    /**
     * A set of status bits regarding the active IME.
     *
     * <p>This value is a combination of following two bits:</p>
     * <dl>
     * <dt>{@link InputMethodService#IME_ACTIVE}</dt>
     * <dd>
     *   If this bit is ON, connected IME is ready to accept touch/key events.
     * </dd>
     * <dt>{@link InputMethodService#IME_VISIBLE}</dt>
     * <dd>
     *   If this bit is ON, some of IME view, e.g. software input, candidate view, is visible.
     * </dd>
     * <dt>{@link InputMethodService#IME_INVISIBLE}</dt>
     * <dd> If this bit is ON, IME is ready with views from last EditorInfo but is
     *    currently invisible.
     * </dd>
     * </dl>
     * <em>Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and
     * {@link InputMethodBindingController#unbindCurrentMethod()}.</em>
     */
    @MultiUserUnawareField
    int mImeWindowVis;

    @SharedByAllUsersField
    @SharedByAllUsersField
    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();


@@ -936,7 +909,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                            // Uh oh, current input method is no longer around!
                            // Uh oh, current input method is no longer around!
                            // Pick another one...
                            // Pick another one...
                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
                            updateSystemUiLocked(0 /* vis */, mBackDisposition);
                            final var bindingController = getInputMethodBindingController(userId);
                            updateSystemUiLocked(0 /* vis */,
                                    bindingController.getBackDisposition(), userId);
                            if (!chooseNewDefaultIMELocked()) {
                            if (!chooseNewDefaultIMELocked()) {
                                changed = true;
                                changed = true;
                                curIm = null;
                                curIm = null;
@@ -1412,7 +1387,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                mStatusBarManagerInternal =
                mStatusBarManagerInternal =
                        LocalServices.getService(StatusBarManagerInternal.class);
                        LocalServices.getService(StatusBarManagerInternal.class);
                hideStatusBarIconLocked();
                hideStatusBarIconLocked();
                updateSystemUiLocked(mImeWindowVis, mBackDisposition);
                final var bindingController = getInputMethodBindingController(currentUserId);
                updateSystemUiLocked(bindingController.getImeWindowVis(),
                        bindingController.getBackDisposition(), currentUserId);
                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
                        com.android.internal.R.bool.show_ongoing_ime_switcher);
                        com.android.internal.R.bool.show_ongoing_ime_switcher);
                if (mShowOngoingImeSwitcherForPhones) {
                if (mShowOngoingImeSwitcherForPhones) {
@@ -2426,11 +2403,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    }
    }


    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
    void resetSystemUiLocked() {
    void resetSystemUiLocked(InputMethodBindingController bindingController) {
        // Set IME window status as invisible when unbinding current method.
        // Set IME window status as invisible when unbinding current method.
        mImeWindowVis = 0;
        final int imeWindowVis = 0;
        mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
        final int backDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
        updateSystemUiLocked(mImeWindowVis, mBackDisposition);
        bindingController.setImeWindowVis(imeWindowVis);
        bindingController.setBackDisposition(backDisposition);
        updateSystemUiLocked(imeWindowVis, backDisposition, bindingController.getUserId());
    }
    }


    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
@@ -2544,7 +2523,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                    sessionState.mSession.finishSession();
                    sessionState.mSession.finishSession();
                } catch (RemoteException e) {
                } catch (RemoteException e) {
                    Slog.w(TAG, "Session failed to close due to remote exception", e);
                    Slog.w(TAG, "Session failed to close due to remote exception", e);
                    updateSystemUiLocked(0 /* vis */, mBackDisposition);
                    // TODO(b/350386877): Propagate userId from the caller or infer it from
                    //  sessionState
                    final int userId = mCurrentUserId;
                    final var bindingController = getInputMethodBindingController(userId);
                    updateSystemUiLocked(0 /* vis */, bindingController.getBackDisposition(),
                            userId);
                }
                }
                sessionState.mSession = null;
                sessionState.mSession = null;
            }
            }
@@ -2764,8 +2748,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            if (tokenDisplayId != topFocusedDisplayId && tokenDisplayId != FALLBACK_DISPLAY_ID) {
            if (tokenDisplayId != topFocusedDisplayId && tokenDisplayId != FALLBACK_DISPLAY_ID) {
                return;
                return;
            }
            }
            mImeWindowVis = vis;
            bindingController.setImeWindowVis(vis);
            mBackDisposition = backDisposition;
            bindingController.setBackDisposition(backDisposition);
            updateSystemUiLocked(vis, backDisposition, userId);
            updateSystemUiLocked(vis, backDisposition, userId);
        }
        }


@@ -2802,23 +2786,23 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.


    private void updateImeWindowStatus(boolean disableImeIcon) {
    private void updateImeWindowStatus(boolean disableImeIcon) {
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            // TODO(b/350386877): Propagate userId from the caller.
            final int userId = mCurrentUserId;
            if (disableImeIcon) {
            if (disableImeIcon) {
                updateSystemUiLocked(0, mBackDisposition);
                final var bindingController = getInputMethodBindingController(userId);
                updateSystemUiLocked(0, bindingController.getBackDisposition(), userId);
            } else {
            } else {
                updateSystemUiLocked();
                updateSystemUiLocked(userId);
            }
            }
        }
        }
    }
    }


    @GuardedBy("ImfLock.class")
    void updateSystemUiLocked() {
        updateSystemUiLocked(mImeWindowVis, mBackDisposition);
    }

    // Caution! This method is called in this class. Handle multi-user carefully
    // Caution! This method is called in this class. Handle multi-user carefully
    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
    private void updateSystemUiLocked(int vis, int backDisposition) {
    void updateSystemUiLocked(@UserIdInt int userId) {
        updateSystemUiLocked(vis, backDisposition, mCurrentUserId);
        final var bindingController = getInputMethodBindingController(userId);
        updateSystemUiLocked(bindingController.getImeWindowVis(),
                bindingController.getBackDisposition(), userId);
    }
    }


    @GuardedBy("ImfLock.class")
    @GuardedBy("ImfLock.class")
@@ -3068,7 +3052,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true, userId);
                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true, userId);
                IInputMethodInvoker curMethod = bindingController.getCurMethod();
                IInputMethodInvoker curMethod = bindingController.getCurMethod();
                if (curMethod != null) {
                if (curMethod != null) {
                    updateSystemUiLocked(mImeWindowVis, mBackDisposition);
                    updateSystemUiLocked(bindingController.getImeWindowVis(),
                            bindingController.getBackDisposition(), userId);
                    curMethod.changeInputMethodSubtype(newSubtype);
                    curMethod.changeInputMethodSubtype(newSubtype);
                }
                }
            }
            }
@@ -3455,7 +3440,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                    return;
                    return;
                }
                }
                mFocusedWindowPerceptible.put(windowToken, windowPerceptible);
                mFocusedWindowPerceptible.put(windowToken, windowPerceptible);
                updateSystemUiLocked();
                updateSystemUiLocked(mCurrentUserId);
            }
            }
        });
        });
    }
    }
@@ -3621,29 +3606,30 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    boolean hideCurrentInputLocked(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
    boolean hideCurrentInputLocked(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
            @InputMethodManager.HideFlags int flags, @Nullable ResultReceiver resultReceiver,
            @InputMethodManager.HideFlags int flags, @Nullable ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason, @UserIdInt int userId) {
            @SoftInputShowHideReason int reason, @UserIdInt int userId) {
        final var bindingController = getInputMethodBindingController(userId);
        if (!mVisibilityStateComputer.canHideIme(statsToken, flags)) {
        if (!mVisibilityStateComputer.canHideIme(statsToken, flags)) {
            return false;
            return false;
        }
        }


        // There is a chance that IMM#hideSoftInput() is called in a transient state where
        // There is a chance that IMM#hideSoftInput() is called in a transient state where
        // IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting
        // IMMS#InputShown is already updated to be true whereas the user's ImeWindowVis is still
        // to be updated with the new value sent from IME process.  Even in such a transient state
        // waiting to be updated with the new value sent from IME process.  Even in such a transient
        // historically we have accepted an incoming call of IMM#hideSoftInput() from the
        // state historically we have accepted an incoming call of IMM#hideSoftInput() from the
        // application process as a valid request, and have even promised such a behavior with CTS
        // application process as a valid request, and have even promised such a behavior with CTS
        // 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
        final var bindingController = getInputMethodBindingController(userId);
        final var userData = getUserData(userId);
        final var userData = getUserData(userId);
        IInputMethodInvoker curMethod = bindingController.getCurMethod();
        IInputMethodInvoker curMethod = bindingController.getCurMethod();
        final boolean shouldHideSoftInput = curMethod != null
        final boolean shouldHideSoftInput = curMethod != null
                && (isInputShownLocked() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
                && (isInputShownLocked()
                || (bindingController.getImeWindowVis() & InputMethodService.IME_ACTIVE) != 0);


        mVisibilityStateComputer.requestImeVisibility(windowToken, false);
        mVisibilityStateComputer.requestImeVisibility(windowToken, false);
        if (shouldHideSoftInput) {
        if (shouldHideSoftInput) {
            // 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
            // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
            // IMMS#mInputShown and the user's ImeWindowVis 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,
@@ -4633,8 +4619,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
            proto.write(HAVE_CONNECTION, bindingController.hasMainConnection());
            proto.write(HAVE_CONNECTION, bindingController.hasMainConnection());
            proto.write(BOUND_TO_METHOD, userData.mBoundToMethod);
            proto.write(BOUND_TO_METHOD, userData.mBoundToMethod);
            proto.write(IS_INTERACTIVE, mIsInteractive);
            proto.write(IS_INTERACTIVE, mIsInteractive);
            proto.write(BACK_DISPOSITION, mBackDisposition);
            proto.write(BACK_DISPOSITION, bindingController.getBackDisposition());
            proto.write(IME_WINDOW_VISIBILITY, mImeWindowVis);
            proto.write(IME_WINDOW_VISIBILITY, bindingController.getImeWindowVis());
            proto.write(SHOW_IME_WITH_HARD_KEYBOARD, mMenuController.getShowImeWithHardKeyboard());
            proto.write(SHOW_IME_WITH_HARD_KEYBOARD, mMenuController.getShowImeWithHardKeyboard());
            proto.end(token);
            proto.end(token);
        }
        }
@@ -5143,18 +5129,18 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.


    private void handleSetInteractive(final boolean interactive) {
    private void handleSetInteractive(final boolean interactive) {
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            mIsInteractive = interactive;
            updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);

            // TODO(b/305849394): Support multiple IMEs.
            // TODO(b/305849394): Support multiple IMEs.
            final var userId = mCurrentUserId;
            final int userId = mCurrentUserId;
            final var bindingController = getInputMethodBindingController(userId);
            mIsInteractive = interactive;
            updateSystemUiLocked(
                    interactive ? bindingController.getImeWindowVis() : 0,
                    bindingController.getBackDisposition(), userId);
            final var userData = getUserData(userId);
            final var userData = getUserData(userId);
            // Inform the current client of the change in active status
            // Inform the current client of the change in active status
            if (userData.mCurClient == null || userData.mCurClient.mClient == null) {
            if (userData.mCurClient == null || userData.mCurClient.mClient == null) {
                return;
                return;
            }
            }
            // TODO(b/325515685): user data must be retrieved by a userId parameter
            final var bindingController = getInputMethodBindingController(mCurrentUserId);
            if (mImePlatformCompatUtils.shouldUseSetInteractiveProtocol(
            if (mImePlatformCompatUtils.shouldUseSetInteractiveProtocol(
                    bindingController.getCurMethodUid())) {
                    bindingController.getCurMethodUid())) {
                // Handle IME visibility when interactive changed before finishing the input to
                // Handle IME visibility when interactive changed before finishing the input to
+4 −2
Original line number Original line Diff line number Diff line
@@ -201,7 +201,7 @@ final class InputMethodMenuController {
        attrs.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
        attrs.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
        attrs.setTitle("Select input method");
        attrs.setTitle("Select input method");
        w.setAttributes(attrs);
        w.setAttributes(attrs);
        mService.updateSystemUiLocked();
        mService.updateSystemUiLocked(userId);
        mService.sendOnNavButtonFlagsChangedLocked();
        mService.sendOnNavButtonFlagsChangedLocked();
        mSwitchingDialog.show();
        mSwitchingDialog.show();
    }
    }
@@ -239,7 +239,9 @@ final class InputMethodMenuController {
            mSwitchingDialog = null;
            mSwitchingDialog = null;
            mSwitchingDialogTitleView = null;
            mSwitchingDialogTitleView = null;


            mService.updateSystemUiLocked();
            // TODO(b/305849394): Make InputMethodMenuController multi-user aware
            final int userId = mService.getCurrentImeUserIdLocked();
            mService.updateSystemUiLocked(userId);
            mService.sendOnNavButtonFlagsChangedLocked();
            mService.sendOnNavButtonFlagsChangedLocked();
            mDialogBuilder = null;
            mDialogBuilder = null;
            mIms = null;
            mIms = null;
+7 −2
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@ import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNull;


@@ -134,8 +135,10 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe


    @Test
    @Test
    public void testApplyImeVisibility_hideImeExplicit() throws Exception {
    public void testApplyImeVisibility_hideImeExplicit() throws Exception {
        mInputMethodManagerService.mImeWindowVis = IME_ACTIVE;
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            final var bindingController =
                    mInputMethodManagerService.getInputMethodBindingController(mUserId);
            when(bindingController.getImeWindowVis()).thenReturn(IME_ACTIVE);
            mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(),
            mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(),
                    STATE_HIDE_IME_EXPLICIT, eq(SoftInputShowHideReason.NOT_SET), mUserId);
                    STATE_HIDE_IME_EXPLICIT, eq(SoftInputShowHideReason.NOT_SET), mUserId);
        }
        }
@@ -144,8 +147,10 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe


    @Test
    @Test
    public void testApplyImeVisibility_hideNotAlways() throws Exception {
    public void testApplyImeVisibility_hideNotAlways() throws Exception {
        mInputMethodManagerService.mImeWindowVis = IME_ACTIVE;
        synchronized (ImfLock.class) {
        synchronized (ImfLock.class) {
            final var bindingController =
                    mInputMethodManagerService.getInputMethodBindingController(mUserId);
            when(bindingController.getImeWindowVis()).thenReturn(IME_ACTIVE);
            mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(),
            mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(),
                    STATE_HIDE_IME_NOT_ALWAYS, eq(SoftInputShowHideReason.NOT_SET), mUserId);
                    STATE_HIDE_IME_NOT_ALWAYS, eq(SoftInputShowHideReason.NOT_SET), mUserId);
        }
        }