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

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

Hook up major per-user call flows in IMMS

This is a kind of gigantic change that aims to hook up most of
remaining per-user call flows without breaking at least single-user
IME mode.

Most of changes are mechanical, including moving the following
@MultiUserUnawareField fields into UserData.

 * mBoundToMethod
 * mBoundToAccessibility
 * mImeBindingState
 * mCurClient
 * mInFullscreenMode
 * mCurInputConnection
 * mCurImeDispatcher
 * mCurRemoteAccessibilityInputConnection
 * mCurEditorInfo
 * mCurStatsToken
 * mEnabledSession
 * mEnabledAccessibilitySessions

So far all the end-to-end tests are passing and hopefully there is no
observable behavior change in the single user IME mode.

Bug: 305849394
Fix: 325515685
Fix: 349444857
Test: presubmit
Flag: EXEMPT refactor
Change-Id: I9d4615e6da979204c21555e040a687163c1460ab
parent fbeeb934
Loading
Loading
Loading
Loading
+22 −16
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
            @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason, @UserIdInt int userId) {
        final var bindingController = mService.getInputMethodBindingController(userId);
        final var userData = mService.getUserData(userId);
        final IInputMethodInvoker curMethod = bindingController.getCurMethod();
        if (curMethod != null) {
            if (DEBUG) {
@@ -93,10 +94,10 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
                if (DEBUG_IME_VISIBILITY) {
                    EventLog.writeEvent(IMF_SHOW_IME,
                            statsToken != null ? statsToken.getTag() : ImeTracker.TOKEN_NONE,
                            Objects.toString(mService.mImeBindingState.mFocusedWindow),
                            Objects.toString(userData.mImeBindingState.mFocusedWindow),
                            InputMethodDebug.softInputDisplayReasonToString(reason),
                            InputMethodDebug.softInputModeToString(
                                    mService.mImeBindingState.mFocusedWindowSoftInputMode));
                                    userData.mImeBindingState.mFocusedWindowSoftInputMode));
                }
                mService.onShowHideSoftInputRequested(true /* show */, showInputToken, reason,
                        statsToken, userId);
@@ -111,6 +112,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
            @UserIdInt int userId) {
        final var bindingController = mService.getInputMethodBindingController(userId);
        final IInputMethodInvoker curMethod = bindingController.getCurMethod();
        final var userData = mService.getUserData(userId);
        if (curMethod != null) {
            // 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
@@ -126,10 +128,10 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
                if (DEBUG_IME_VISIBILITY) {
                    EventLog.writeEvent(IMF_HIDE_IME,
                            statsToken != null ? statsToken.getTag() : ImeTracker.TOKEN_NONE,
                            Objects.toString(mService.mImeBindingState.mFocusedWindow),
                            Objects.toString(userData.mImeBindingState.mFocusedWindow),
                            InputMethodDebug.softInputDisplayReasonToString(reason),
                            InputMethodDebug.softInputModeToString(
                                    mService.mImeBindingState.mFocusedWindowSoftInputMode));
                                    userData.mImeBindingState.mFocusedWindowSoftInputMode));
                }
                mService.onShowHideSoftInputRequested(false /* show */, hideInputToken, reason,
                        statsToken, userId);
@@ -179,29 +181,30 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
                break;
            case STATE_HIDE_IME_EXPLICIT:
                if (Flags.refactorInsetsController()) {
                    setImeVisibilityOnFocusedWindowClient(false);
                    setImeVisibilityOnFocusedWindowClient(false, userId);
                } else {
                    mService.hideCurrentInputLocked(windowToken, statsToken,
                            0 /* flags */, null /* resultReceiver */, reason);
                            0 /* flags */, null /* resultReceiver */, reason, userId);
                }
                break;
            case STATE_HIDE_IME_NOT_ALWAYS:
                if (Flags.refactorInsetsController()) {
                    setImeVisibilityOnFocusedWindowClient(false);
                    setImeVisibilityOnFocusedWindowClient(false, userId);
                } else {
                    mService.hideCurrentInputLocked(windowToken, statsToken,
                            InputMethodManager.HIDE_NOT_ALWAYS, null /* resultReceiver */, reason);
                            InputMethodManager.HIDE_NOT_ALWAYS, null /* resultReceiver */, reason,
                            userId);
                }
                break;
            case STATE_SHOW_IME_IMPLICIT:
                if (Flags.refactorInsetsController()) {
                    // This can be triggered by IMMS#startInputOrWindowGainedFocus. We need to
                    // set the requestedVisibleTypes in InsetsController first, before applying it.
                    setImeVisibilityOnFocusedWindowClient(true);
                    setImeVisibilityOnFocusedWindowClient(true, userId);
                } else {
                    mService.showCurrentInputLocked(windowToken, statsToken,
                            InputMethodManager.SHOW_IMPLICIT, MotionEvent.TOOL_TYPE_UNKNOWN,
                            null /* resultReceiver */, reason);
                            null /* resultReceiver */, reason, userId);
                }
                break;
            case STATE_SHOW_IME_SNAPSHOT:
@@ -230,20 +233,23 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
    @GuardedBy("ImfLock.class")
    @Override
    public boolean removeImeScreenshot(int displayId, @UserIdInt int userId) {
        final var userData = mService.getUserData(userId);
        if (mImeTargetVisibilityPolicy.removeImeScreenshot(displayId)) {
            mService.onShowHideSoftInputRequested(false /* show */,
                    mService.mImeBindingState.mFocusedWindow,
                    userData.mImeBindingState.mFocusedWindow,
                    REMOVE_IME_SCREENSHOT_FROM_IMMS, null /* statsToken */, userId);
            return true;
        }
        return false;
    }

    private void setImeVisibilityOnFocusedWindowClient(boolean visibility) {
        if (mService.mImeBindingState != null
                && mService.mImeBindingState.mFocusedWindowClient != null
                && mService.mImeBindingState.mFocusedWindowClient.mClient != null) {
            mService.mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(visibility);
    @GuardedBy("ImfLock.class")
    private void setImeVisibilityOnFocusedWindowClient(boolean visibility, @UserIdInt int userId) {
        final var userData = mService.getUserData(userId);
        if (userData.mImeBindingState != null
                && userData.mImeBindingState.mFocusedWindowClient != null
                && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
            userData.mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(visibility);
        } else {
            // TODO(b/329229469): ImeTracker?
        }
+6 −2
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import static com.android.server.inputmethod.InputMethodManagerService.computeIm
import android.accessibilityservice.AccessibilityService;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.IBinder;
@@ -52,6 +53,7 @@ import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodManager;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.server.LocalServices;
@@ -553,15 +555,17 @@ public final class ImeVisibilityStateComputer {
        return null;
    }

    IBinder getWindowTokenFrom(IBinder requestImeToken) {
    @GuardedBy("ImfLock.class")
    IBinder getWindowTokenFrom(IBinder requestImeToken, @UserIdInt int userId) {
        for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
            final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
            if (state.getRequestImeToken() == requestImeToken) {
                return windowToken;
            }
        }
        final var userData = mService.getUserData(userId);
        // Fallback to the focused window for some edge cases (e.g. relaunching the activity)
        return mService.mImeBindingState.mFocusedWindow;
        return userData.mImeBindingState.mFocusedWindow;
    }

    IBinder getWindowTokenFrom(ImeTargetWindowState windowState) {
+4 −4
Original line number Diff line number Diff line
@@ -382,9 +382,9 @@ final class InputMethodBindingController {
                        InputMethodManager
                                .invalidateLocalConnectionlessStylusHandwritingAvailabilityCaches();
                    }
                    mService.initializeImeLocked(mCurMethod, mCurToken);
                    mService.initializeImeLocked(mCurMethod, mCurToken, mUserId);
                    mService.scheduleNotifyImeUidToAudioService(mCurMethodUid);
                    mService.reRequestCurrentClientSessionLocked();
                    mService.reRequestCurrentClientSessionLocked(mUserId);
                    mAutofillController.performOnCreateInlineSuggestionsRequest();
                }

@@ -437,7 +437,7 @@ final class InputMethodBindingController {
                    mLastBindTime = SystemClock.uptimeMillis();
                    clearCurMethodAndSessions();
                    mService.clearInputShownLocked();
                    mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME);
                    mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME, mUserId);
                }
            }
        }
@@ -483,7 +483,7 @@ final class InputMethodBindingController {

    @GuardedBy("ImfLock.class")
    private void clearCurMethodAndSessions() {
        mService.clearClientSessionsLocked();
        mService.clearClientSessionsLocked(this);
        mCurMethod = null;
        mCurMethodUid = Process.INVALID_UID;
    }
+615 −544

File changed.

Preview size limit exceeded, changes collapsed.

+4 −3
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ final class InputMethodMenuController {
        if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);

        final int userId = mService.getCurrentImeUserIdLocked();
        final var bindingController = mService.getInputMethodBindingController(userId);

        hideInputMethodMenuLocked();

@@ -86,9 +87,9 @@ final class InputMethodMenuController {
            final InputMethodSubtype currentSubtype =
                    mService.getCurrentInputMethodSubtypeLocked();
            if (currentSubtype != null) {
                final String curMethodId = mService.getSelectedMethodIdLocked();
                final String curMethodId = bindingController.getSelectedMethodId();
                final InputMethodInfo currentImi =
                        mService.queryInputMethodForCurrentUserLocked(curMethodId);
                        InputMethodSettingsRepository.get(userId).getMethodMap().get(curMethodId);
                preferredInputMethodSubtypeId = SubtypeUtils.getSubtypeIdFromHashCode(
                        currentImi, currentSubtype.hashCode());
            }
@@ -179,7 +180,7 @@ final class InputMethodMenuController {
                    if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) {
                        subtypeId = NOT_A_SUBTYPE_ID;
                    }
                    mService.setInputMethodLocked(im.getId(), subtypeId);
                    mService.setInputMethodLocked(im.getId(), subtypeId, userId);
                }
                hideInputMethodMenuLocked();
            }
Loading