summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java38
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java8
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodBindingController.java8
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java1159
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodMenuController.java7
-rw-r--r--services/core/java/com/android/server/inputmethod/UserDataRepository.java78
-rw-r--r--services/core/java/com/android/server/inputmethod/ZeroJankProxy.java2
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java4
8 files changed, 732 insertions, 572 deletions
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
index b77f47d640e9..aa4b3386e548 100644
--- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -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?
}
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 9d80844ee9eb..7ebf5950de16 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -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) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index 60d647dc710f..afc10290ee02 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -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;
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0c46c5b6222e..3c74b23fc8c2 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -468,12 +468,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
private final ClientController mClientController;
/**
- * Holds the current IME binding state info.
- */
- @MultiUserUnawareField
- ImeBindingState mImeBindingState;
-
- /**
* Set once the system is ready to run third party code.
*/
@SharedByAllUsersField
@@ -492,25 +486,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
- /**
- * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method.
- * This is to be synchronized with the secure settings keyed with
- * {@link Settings.Secure#DEFAULT_INPUT_METHOD}.
- *
- * <p>This can be transiently {@code null} when the system is re-initializing input method
- * settings, e.g., the system locale is just changed.</p>
- *
- * <p>Note that {@link InputMethodBindingController#getCurId()} is used to track which IME
- * is being connected to {@link InputMethodManagerService}.</p>
- *
- * @see InputMethodBindingController#getCurId()
- */
- @GuardedBy("ImfLock.class")
- @Nullable
- String getSelectedMethodIdLocked() {
- return getInputMethodBindingController(mCurrentUserId).getSelectedMethodId();
- }
-
@GuardedBy("ImfLock.class")
@Nullable
InputMethodInfo queryInputMethodForCurrentUserLocked(@NonNull String imeId) {
@@ -518,13 +493,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
/**
- * The client that is currently bound to an input method.
- */
- @MultiUserUnawareField
- @Nullable
- private ClientState mCurClient;
-
- /**
* The last window token that we confirmed that IME started talking to. This is always updated
* upon reports from the input method. If the window state is already changed before the report
* is handled, this field just keeps the last value.
@@ -533,33 +501,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
IBinder mLastImeTargetWindow;
/**
- * The {@link IRemoteInputConnection} last provided by the current client.
- */
- @MultiUserUnawareField
- IRemoteInputConnection mCurInputConnection;
-
- /**
- * The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
- * receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
- */
- @MultiUserUnawareField
- ImeOnBackInvokedDispatcher mCurImeDispatcher;
-
- /**
- * The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
- */
- @MultiUserUnawareField
- @Nullable
- IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;
-
- /**
- * The {@link EditorInfo} last provided by the current client.
- */
- @MultiUserUnawareField
- @Nullable
- EditorInfo mCurEditorInfo;
-
- /**
* Map of window perceptible states indexed by their associated window tokens.
*
* The value {@code true} indicates that IME has not been mostly hidden via
@@ -570,20 +511,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
private final WeakHashMap<IBinder, Boolean> mFocusedWindowPerceptible = new WeakHashMap<>();
/**
- * The token tracking the current IME show request that is waiting for a connection to an IME,
- * otherwise {@code null}.
- */
- @Nullable
- @MultiUserUnawareField
- private ImeTracker.Token mCurStatsToken;
-
- /**
- * {@code true} if the current input method is in fullscreen mode.
- */
- @MultiUserUnawareField
- boolean mInFullscreenMode;
-
- /**
* The token we have made for the currently active input method, to
* identify it in the future.
*/
@@ -618,27 +545,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
/**
- * Have we called mCurMethod.bindInput()?
- */
- @MultiUserUnawareField
- boolean mBoundToMethod;
-
- /**
- * Have we called bindInput() for accessibility services?
- */
- @MultiUserUnawareField
- boolean mBoundToAccessibility;
-
- /**
- * Currently enabled session.
- */
- @GuardedBy("ImfLock.class")
- @MultiUserUnawareField
- SessionState mEnabledSession;
- @MultiUserUnawareField
- SparseArray<AccessibilitySessionState> mEnabledAccessibilitySessions = new SparseArray<>();
-
- /**
* True if the device is currently interactive with user. The value is true initially.
*/
@MultiUserUnawareField
@@ -763,13 +669,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, mUserId);
mVisibilityStateComputer.getImePolicy().setA11yRequestNoSoftKeyboard(
accessibilitySoftKeyboardSetting);
+ final var userData = getUserData(mUserId);
if (mVisibilityStateComputer.getImePolicy().isA11yRequestNoSoftKeyboard()) {
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE);
- } else if (isShowRequestedForCurrentWindow()) {
- showCurrentInputLocked(mImeBindingState.mFocusedWindow,
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow,
+ 0 /* flags */, SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE,
+ mUserId);
+ } else if (isShowRequestedForCurrentWindow(mUserId)) {
+ showCurrentInputLocked(userData.mImeBindingState.mFocusedWindow,
InputMethodManager.SHOW_IMPLICIT,
- SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE);
+ SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE, mUserId);
}
} else if (stylusHandwritingEnabledUri.equals(uri)) {
InputMethodManager.invalidateLocalStylusHandwritingAvailabilityCaches();
@@ -777,13 +685,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
.invalidateLocalConnectionlessStylusHandwritingAvailabilityCaches();
} else {
boolean enabledChanged = false;
- String newEnabled = InputMethodSettingsRepository.get(mCurrentUserId)
+ String newEnabled = InputMethodSettingsRepository.get(mUserId)
.getEnabledInputMethodsStr();
if (!mLastEnabled.equals(newEnabled)) {
mLastEnabled = newEnabled;
enabledChanged = true;
}
- updateInputMethodsFromSettingsLocked(enabledChanged);
+ updateInputMethodsFromSettingsLocked(enabledChanged, mUserId);
}
}
}
@@ -846,10 +754,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
DirectBootAwareness.AUTO);
InputMethodSettingsRepository.put(userId, settings);
}
- postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */);
+ // TODO(b/305849394): Dispatch this to non-current users.
+ final int userId = mCurrentUserId;
+ postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */, userId);
// If the locale is changed, needs to reset the default ime
- resetDefaultImeLocked(mContext);
- updateFromSettingsLocked(true);
+ resetDefaultImeLocked(mContext, userId);
+ updateFromSettingsLocked(true, userId);
}
}
@@ -1004,7 +914,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
if (!isCurrentUser) {
return;
}
- postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
+ postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */, userId);
boolean changed = false;
@@ -1046,7 +956,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
if (changed) {
- updateFromSettingsLocked(false);
+ updateFromSettingsLocked(false, userId);
}
}
}
@@ -1188,8 +1098,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
InputMethodSettingsRepository.put(userId, newSettings);
if (mCurrentUserId == userId) {
// We need to rebuild IMEs.
- postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
- updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
+ postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */, userId);
+ updateInputMethodsFromSettingsLocked(true /* enabledChanged */, userId);
} else if (mExperimentalConcurrentMultiUserModeEnabled) {
experimentalInitializeVisibleBackgroundUserLocked(userId);
}
@@ -1208,8 +1118,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
// Hide soft input before user switch task since switch task may block main handler a while
// and delayed the hideCurrentInputLocked().
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_SWITCH_USER);
+ final var userData = getUserData(userId);
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
+ SoftInputShowHideReason.HIDE_SWITCH_USER, userId);
final UserSwitchHandlerTask task = new UserSwitchHandlerTask(this, userId,
clientToBeReset);
mUserSwitchHandlerTask = task;
@@ -1301,7 +1212,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
mClientController = new ClientController(mPackageManagerInternal);
mClientController.addClientControllerCallback(c -> onClientRemoved(c));
- mImeBindingState = ImeBindingState.newEmptyState();
mPreventImeStartupUnlessTextEditor = mRes.getBoolean(
com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor);
@@ -1350,10 +1260,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- private void resetDefaultImeLocked(Context context) {
+ private void resetDefaultImeLocked(Context context, @UserIdInt int userId) {
+ final var bindingController = getInputMethodBindingController(userId);
// Do not reset the default (current) IME when it is a 3rd-party IME
- String selectedMethodId = getSelectedMethodIdLocked();
- final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+ String selectedMethodId = bindingController.getSelectedMethodId();
+ final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
if (selectedMethodId != null
&& !settings.getMethodMap().get(selectedMethodId).isSystem()) {
return;
@@ -1368,7 +1279,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
if (DEBUG) {
Slog.i(TAG, "Default found, using " + defIm.getId());
}
- setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
+ setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false, userId);
}
@GuardedBy("ImfLock.class")
@@ -1413,22 +1324,23 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private void switchUserOnHandlerLocked(@UserIdInt int newUserId,
IInputMethodClientInvoker clientToBeReset) {
+ final int prevUserId = mCurrentUserId;
if (DEBUG) {
Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
- + " currentUserId=" + mCurrentUserId);
+ + " prevUserId=" + prevUserId);
}
// Clean up stuff for mCurrentUserId, which soon becomes the previous user.
// TODO(b/338461930): Check if this is still necessary or not.
- onUnbindCurrentMethodByReset();
+ onUnbindCurrentMethodByReset(prevUserId);
// Note that in b/197848765 we want to see if we can keep the binding alive for better
// profile switching.
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ final var bindingController = getInputMethodBindingController(prevUserId);
bindingController.unbindCurrentMethod();
- unbindCurrentClientLocked(UnbindReason.SWITCH_USER);
+ unbindCurrentClientLocked(UnbindReason.SWITCH_USER, prevUserId);
// Hereafter we start initializing things for "newUserId".
@@ -1438,6 +1350,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
mSettingsObserver.registerContentObserverLocked(newUserId);
mCurrentUserId = newUserId;
+ final var newUserData = getUserData(newUserId);
final String defaultImiId = SecureSettingsWrapper.getString(
Settings.Secure.DEFAULT_INPUT_METHOD, null, newUserId);
@@ -1454,13 +1367,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
final InputMethodSettings newSettings = InputMethodSettingsRepository.get(newUserId);
- postInputMethodSettingUpdatedLocked(initialUserSwitch /* resetDefaultEnabledIme */);
+ postInputMethodSettingUpdatedLocked(initialUserSwitch /* resetDefaultEnabledIme */,
+ newUserId);
if (TextUtils.isEmpty(newSettings.getSelectedInputMethod())) {
// This is the first time of the user switch and
// set the current ime to the proper one.
- resetDefaultImeLocked(mContext);
+ resetDefaultImeLocked(mContext, newUserId);
}
- updateFromSettingsLocked(true);
+ updateFromSettingsLocked(true, newUserId);
if (initialUserSwitch) {
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
@@ -1479,7 +1393,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// The client is already gone.
return;
}
- cs.mClient.scheduleStartInputIfNecessary(mInFullscreenMode);
+ cs.mClient.scheduleStartInputIfNecessary(newUserData.mInFullscreenMode);
}
}
@@ -1541,8 +1455,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
DirectBootAwareness.AUTO);
InputMethodSettingsRepository.put(currentUserId, newSettings);
postInputMethodSettingUpdatedLocked(
- !imeSelectedOnBoot /* resetDefaultEnabledIme */);
- updateFromSettingsLocked(true);
+ !imeSelectedOnBoot /* resetDefaultEnabledIme */, currentUserId);
+ updateFromSettingsLocked(true, currentUserId);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
getPackageManagerForUser(mContext, currentUserId),
newSettings.getEnabledInputMethodList());
@@ -1859,20 +1773,31 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
}
+ @GuardedBy("ImfLock.class")
+ private void onClientRemoved(ClientState client) {
+ clearClientSessionLocked(client);
+ clearClientSessionForAccessibilityLocked(client);
+ // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
+ @SuppressWarnings("GuardedBy") Consumer<UserDataRepository.UserData> clientRemovedForUser =
+ userData -> onClientRemovedInternalLocked(client, userData);
+ mUserDataRepository.forAllUserData(clientRemovedForUser);
+ }
+
/**
* Hide the IME if the removed user is the current user.
*/
// TODO(b/325515685): Move this method to InputMethodBindingController
@GuardedBy("ImfLock.class")
- private void onClientRemoved(ClientState client) {
- clearClientSessionLocked(client);
- clearClientSessionForAccessibilityLocked(client);
- if (mCurClient == client) {
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_REMOVE_CLIENT);
- if (mBoundToMethod) {
- mBoundToMethod = false;
- IInputMethodInvoker curMethod = getCurMethodLocked();
+ private void onClientRemovedInternalLocked(ClientState client,
+ @NonNull UserDataRepository.UserData userData) {
+ final int userId = userData.mUserId;
+ if (userData.mCurClient == client) {
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
+ SoftInputShowHideReason.HIDE_REMOVE_CLIENT, userId);
+ if (userData.mBoundToMethod) {
+ userData.mBoundToMethod = false;
+ final var userBindingController = getInputMethodBindingController(userId);
+ IInputMethodInvoker curMethod = userBindingController.getCurMethod();
if (curMethod != null) {
// When we unbind input, we are unbinding the client, so we always
// unbind ime and a11y together.
@@ -1880,10 +1805,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
AccessibilityManagerInternal.get().unbindInput();
}
}
- mBoundToAccessibility = false;
- mCurClient = null;
- if (mImeBindingState.mFocusedWindowClient == client) {
- mImeBindingState = ImeBindingState.newEmptyState();
+ userData.mBoundToAccessibility = false;
+ userData.mCurClient = null;
+ if (userData.mImeBindingState.mFocusedWindowClient == client) {
+ userData.mImeBindingState = ImeBindingState.newEmptyState();
}
}
}
@@ -1896,49 +1821,51 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void unbindCurrentClientLocked(@UnbindReason int unbindClientReason) {
- if (mCurClient != null) {
+ void unbindCurrentClientLocked(@UnbindReason int unbindClientReason, @UserIdInt int userId) {
+ final var userData = getUserData(userId);
+ if (userData.mCurClient != null) {
if (DEBUG) {
- Slog.v(TAG, "unbindCurrentInputLocked: client=" + mCurClient.mClient.asBinder());
+ Slog.v(TAG, "unbindCurrentInputLocked: client="
+ + userData.mCurClient.mClient.asBinder());
}
- if (mBoundToMethod) {
- mBoundToMethod = false;
- IInputMethodInvoker curMethod = getCurMethodLocked();
+ final var bindingController = getInputMethodBindingController(userId);
+ if (userData.mBoundToMethod) {
+ userData.mBoundToMethod = false;
+ IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod != null) {
curMethod.unbindInput();
}
}
- mBoundToAccessibility = false;
+ userData.mBoundToAccessibility = false;
// Since we set active false to current client and set mCurClient to null, let's unbind
// all accessibility too. That means, when input method get disconnected (including
// switching ime), we also unbind accessibility
- mCurClient.mClient.setActive(false /* active */, false /* fullscreen */);
+ userData.mCurClient.mClient.setActive(false /* active */, false /* fullscreen */);
- // TODO(b/325515685): make binding controller user independent. Before this change, the
- // following dependencies also need to be user independent: mCurClient, mBoundToMethod,
- // getCurMethodLocked(), and mMenuController.
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
- mCurClient.mClient.onUnbindMethod(bindingController.getSequenceNumber(),
+ userData.mCurClient.mClient.onUnbindMethod(bindingController.getSequenceNumber(),
unbindClientReason);
- mCurClient.mSessionRequested = false;
- mCurClient.mSessionRequestedForAccessibility = false;
- mCurClient = null;
- ImeTracker.forLogging().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
- mCurStatsToken = null;
+ userData.mCurClient.mSessionRequested = false;
+ userData.mCurClient.mSessionRequestedForAccessibility = false;
+ userData.mCurClient = null;
+ ImeTracker.forLogging().onFailed(userData.mCurStatsToken,
+ ImeTracker.PHASE_SERVER_WAIT_IME);
+ userData.mCurStatsToken = null;
+ // TODO: Make mMenuController multi-user aware
mMenuController.hideInputMethodMenuLocked();
}
}
/**
* TODO(b/338404383) Remove
- * Called when {@link #resetCurrentMethodAndClientLocked(int)} invoked for clean-up states
+ * Called when {@link #resetCurrentMethodAndClientLocked(int, int)} invoked for clean-up states
* before unbinding the current method.
*/
@GuardedBy("ImfLock.class")
- void onUnbindCurrentMethodByReset() {
+ void onUnbindCurrentMethodByReset(@UserIdInt int userId) {
+ final var userData = getUserData(userId);
final ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
- mImeBindingState.mFocusedWindow);
+ userData.mImeBindingState.mFocusedWindow);
if (winState != null && !winState.isRequestedImeVisible()
&& !mVisibilityStateComputer.isInputShown()) {
// Normally, the focus window will apply the IME visibility state to
@@ -1949,9 +1876,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// As a result, we have to notify WM to apply IME visibility before clearing the
// binding states in the first place.
final var statsToken = createStatsTokenForFocusedClient(false /* show */,
- SoftInputShowHideReason.UNBIND_CURRENT_METHOD);
- mVisibilityApplier.applyImeVisibility(mImeBindingState.mFocusedWindow, statsToken,
- STATE_HIDE_IME, mCurrentUserId);
+ SoftInputShowHideReason.UNBIND_CURRENT_METHOD, userId);
+ mVisibilityApplier.applyImeVisibility(userData.mImeBindingState.mFocusedWindow,
+ statsToken, STATE_HIDE_IME, userId);
}
}
@@ -1961,13 +1888,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
*/
@GuardedBy("ImfLock.class")
boolean hasAttachedClient() {
- return mCurClient != null;
+ return getUserData(mCurrentUserId).mCurClient != null;
}
@VisibleForTesting
void setAttachedClientForTesting(@NonNull ClientState cs) {
synchronized (ImfLock.class) {
- mCurClient = cs;
+ getUserData(mCurrentUserId).mCurClient = cs;
}
}
@@ -1983,20 +1910,23 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- private boolean isShowRequestedForCurrentWindow() {
+ private boolean isShowRequestedForCurrentWindow(@UserIdInt int userId) {
+ final var userData = getUserData(userId);
+ // TODO(b/349904272): Make mVisibilityStateComputer multi-user aware
final ImeTargetWindowState state = mVisibilityStateComputer.getWindowStateOrNull(
- mImeBindingState.mFocusedWindow);
+ userData.mImeBindingState.mFocusedWindow);
return state != null && state.isRequestedImeVisible();
}
@GuardedBy("ImfLock.class")
@NonNull
- InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
- final int userId = mCurrentUserId;
+ InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial,
+ @UserIdInt int userId) {
final var bindingController = getInputMethodBindingController(userId);
- if (!mBoundToMethod) {
- bindingController.getCurMethod().bindInput(mCurClient.mBinding);
- mBoundToMethod = true;
+ final var userData = getUserData(userId);
+ if (!userData.mBoundToMethod) {
+ bindingController.getCurMethod().bindInput(userData.mCurClient.mBinding);
+ userData.mBoundToMethod = true;
}
final boolean restarting = !initial;
@@ -2004,11 +1934,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final StartInputInfo info = new StartInputInfo(mCurrentUserId,
bindingController.getCurToken(), bindingController.getCurTokenDisplayId(),
bindingController.getCurId(), startInputReason,
- restarting, UserHandle.getUserId(mCurClient.mUid),
- mCurClient.mSelfReportedDisplayId, mImeBindingState.mFocusedWindow, mCurEditorInfo,
- mImeBindingState.mFocusedWindowSoftInputMode,
+ restarting, UserHandle.getUserId(userData.mCurClient.mUid),
+ userData.mCurClient.mSelfReportedDisplayId,
+ userData.mImeBindingState.mFocusedWindow, userData.mCurEditorInfo,
+ userData.mImeBindingState.mFocusedWindowSoftInputMode,
bindingController.getSequenceNumber());
- mImeTargetWindowMap.put(startInputToken, mImeBindingState.mFocusedWindow);
+ mImeTargetWindowMap.put(startInputToken, userData.mImeBindingState.mFocusedWindow);
mStartInputHistory.addEntry(info);
// Seems that PackageManagerInternal#grantImplicitAccess() doesn't handle cross-user
@@ -2016,33 +1947,34 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// same-user scenarios.
// That said ignoring cross-user scenario will never affect IMEs that do not have
// INTERACT_ACROSS_USERS(_FULL) permissions, which is actually almost always the case.
- if (userId == UserHandle.getUserId(mCurClient.mUid)) {
+ if (userId == UserHandle.getUserId(userData.mCurClient.mUid)) {
mPackageManagerInternal.grantImplicitAccess(userId, null /* intent */,
UserHandle.getAppId(bindingController.getCurMethodUid()),
- mCurClient.mUid, true /* direct */);
+ userData.mCurClient.mUid, true /* direct */);
}
@InputMethodNavButtonFlags final int navButtonFlags = getInputMethodNavButtonFlagsLocked();
- final SessionState session = mCurClient.mCurSession;
- setEnabledSessionLocked(session);
- session.mMethod.startInput(startInputToken, mCurInputConnection, mCurEditorInfo, restarting,
- navButtonFlags, mCurImeDispatcher);
+ final SessionState session = userData.mCurClient.mCurSession;
+ setEnabledSessionLocked(session, userData);
+ session.mMethod.startInput(startInputToken, userData.mCurInputConnection,
+ userData.mCurEditorInfo, restarting, navButtonFlags, userData.mCurImeDispatcher);
if (Flags.refactorInsetsController()) {
- if (isShowRequestedForCurrentWindow() && mImeBindingState != null
- && mImeBindingState.mFocusedWindow != null) {
- showSoftInputInternal(mImeBindingState.mFocusedWindow);
+ if (isShowRequestedForCurrentWindow(userId) && userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindow != null) {
+ showSoftInputInternal(userData.mImeBindingState.mFocusedWindow);
}
} else {
- if (isShowRequestedForCurrentWindow()) {
+ if (isShowRequestedForCurrentWindow(userId)) {
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
// Re-use current statsToken, if it exists.
- final var statsToken = mCurStatsToken != null ? mCurStatsToken
+ final var statsToken = userData.mCurStatsToken != null ? userData.mCurStatsToken
: createStatsTokenForFocusedClient(true /* show */,
- SoftInputShowHideReason.ATTACH_NEW_INPUT);
- mCurStatsToken = null;
- showCurrentInputLocked(mImeBindingState.mFocusedWindow, statsToken,
+ SoftInputShowHideReason.ATTACH_NEW_INPUT, userId);
+ userData.mCurStatsToken = null;
+ showCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, statsToken,
mVisibilityStateComputer.getShowFlags(), MotionEvent.TOOL_TYPE_UNKNOWN,
- null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT);
+ null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT,
+ userId);
}
}
@@ -2052,7 +1984,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final boolean suppressesSpellChecker =
curInputMethodInfo != null && curInputMethodInfo.suppressesSpellChecker();
final SparseArray<IAccessibilityInputMethodSession> accessibilityInputMethodSessions =
- createAccessibilityInputMethodSessions(mCurClient.mAccessibilitySessions);
+ createAccessibilityInputMethodSessions(
+ userData.mCurClient.mAccessibilitySessions);
if (bindingController.supportsStylusHandwriting() && hasSupportedStylusLocked()) {
mHwController.setInkWindowInitializer(new InkWindowInitializer());
}
@@ -2064,10 +1997,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private void attachNewAccessibilityLocked(@StartInputReason int startInputReason,
- boolean initial) {
- if (!mBoundToAccessibility) {
+ boolean initial, @UserIdInt int userId) {
+ final var userData = getUserData(userId);
+
+ if (!userData.mBoundToAccessibility) {
AccessibilityManagerInternal.get().bindInput();
- mBoundToAccessibility = true;
+ userData.mBoundToAccessibility = true;
}
// TODO(b/187453053): grantImplicitAccess to accessibility services access? if so, need to
@@ -2076,9 +2011,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// We don't start input when session for a11y is created. We start input when
// input method start input, a11y manager service is always on.
if (startInputReason != StartInputReason.SESSION_CREATED_BY_ACCESSIBILITY) {
- setEnabledSessionForAccessibilityLocked(mCurClient.mAccessibilitySessions);
- AccessibilityManagerInternal.get().startInput(mCurRemoteAccessibilityInputConnection,
- mCurEditorInfo, !initial /* restarting */);
+ setEnabledSessionForAccessibilityLocked(userData.mCurClient.mAccessibilitySessions,
+ userData);
+ AccessibilityManagerInternal.get().startInput(
+ userData.mCurRemoteAccessibilityInputConnection,
+ userData.mCurEditorInfo, !initial /* restarting */);
}
}
@@ -2114,10 +2051,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@NonNull ImeOnBackInvokedDispatcher imeDispatcher,
@NonNull InputMethodBindingController bindingController) {
+ final int userId = bindingController.mUserId;
+ final var userData = getUserData(userId);
+
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
// session & other conditions.
ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
- mImeBindingState.mFocusedWindow);
+ userData.mImeBindingState.mFocusedWindow);
if (winState == null) {
return InputBindResult.NOT_IME_TARGET_WINDOW;
}
@@ -2134,13 +2074,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
mVisibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);
} else if (!Objects.equals(deviceMethodId, selectedMethodId)) {
setInputMethodLocked(deviceMethodId, NOT_A_SUBTYPE_ID,
- bindingController.getDeviceIdToShowIme());
+ bindingController.getDeviceIdToShowIme(), userId);
selectedMethodId = deviceMethodId;
}
if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) {
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE);
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
+ SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE, userId);
return InputBindResult.NO_IME;
}
@@ -2149,19 +2089,19 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return InputBindResult.NO_IME;
}
- if (mCurClient != cs) {
- prepareClientSwitchLocked(cs);
+ if (userData.mCurClient != cs) {
+ prepareClientSwitchLocked(cs, userId);
}
- final boolean connectionWasActive = mCurInputConnection != null;
+ final boolean connectionWasActive = userData.mCurInputConnection != null;
// Bump up the sequence for this client and attach it.
bindingController.advanceSequenceNumber();
- mCurClient = cs;
- mCurInputConnection = inputConnection;
- mCurRemoteAccessibilityInputConnection = remoteAccessibilityInputConnection;
- mCurImeDispatcher = imeDispatcher;
+ userData.mCurClient = cs;
+ userData.mCurInputConnection = inputConnection;
+ userData.mCurRemoteAccessibilityInputConnection = remoteAccessibilityInputConnection;
+ userData.mCurImeDispatcher = imeDispatcher;
// Override the locale hints if the app is running on a virtual device.
if (mVdmInternal == null) {
mVdmInternal = LocalServices.getService(VirtualDeviceManagerInternal.class);
@@ -2172,17 +2112,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
editorInfo.hintLocales = hintsFromVirtualDevice;
}
}
- mCurEditorInfo = editorInfo;
+ userData.mCurEditorInfo = editorInfo;
// Notify input manager if the connection state changes.
- final boolean connectionIsActive = mCurInputConnection != null;
+ final boolean connectionIsActive = userData.mCurInputConnection != null;
if (connectionIsActive != connectionWasActive) {
mInputManagerInternal.notifyInputMethodConnectionActive(connectionIsActive);
}
// If configured, we want to avoid starting up the IME if it is not supposed to be showing
if (shouldPreventImeStartupLocked(selectedMethodId, startInputFlags,
- unverifiedTargetSdkVersion)) {
+ unverifiedTargetSdkVersion, userId)) {
if (DEBUG) {
Slog.d(TAG, "Avoiding IME startup and unbinding current input method.");
}
@@ -2197,7 +2137,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final String curId = bindingController.getCurId();
final int displayIdToShowIme = bindingController.getDisplayIdToShowIme();
if (curId != null && curId.equals(bindingController.getSelectedMethodId())
- && displayIdToShowIme == getCurTokenDisplayIdLocked()) {
+ && displayIdToShowIme == bindingController.getCurTokenDisplayId()) {
if (cs.mCurSession != null) {
// Fast case: if we are already connected to the input method,
// then just return it.
@@ -2211,12 +2151,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// we can always attach to accessibility because AccessibilityManagerService is
// always on.
attachNewAccessibilityLocked(startInputReason,
- (startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0);
+ (startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0, userId);
return attachNewInputLocked(startInputReason,
- (startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0);
+ (startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0, userId);
}
- InputBindResult bindResult = tryReuseConnectionLocked(bindingController, cs);
+ InputBindResult bindResult = tryReuseConnectionLocked(bindingController, cs, userId);
if (bindResult != null) {
return bindResult;
}
@@ -2293,18 +2233,19 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
private boolean shouldPreventImeStartupLocked(
@NonNull String selectedMethodId,
@StartInputFlags int startInputFlags,
- int unverifiedTargetSdkVersion) {
+ int unverifiedTargetSdkVersion,
+ @UserIdInt int userId) {
// Fast-path for the majority of cases
if (!mPreventImeStartupUnlessTextEditor) {
return false;
}
- if (isShowRequestedForCurrentWindow()) {
+ if (isShowRequestedForCurrentWindow(userId)) {
return false;
}
if (isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags)) {
return false;
}
- final InputMethodInfo imi = InputMethodSettingsRepository.get(mCurrentUserId)
+ final InputMethodInfo imi = InputMethodSettingsRepository.get(userId)
.getMethodMap().get(selectedMethodId);
if (imi == null) {
return false;
@@ -2316,10 +2257,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- private void prepareClientSwitchLocked(ClientState cs) {
+ private void prepareClientSwitchLocked(ClientState cs, @UserIdInt int userId) {
// If the client is changing, we need to switch over to the new
// one.
- unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT);
+ unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT, userId);
// If the screen is on, inform the new client it is active
if (mIsInteractive) {
cs.mClient.setActive(true /* active */, false /* fullscreen */);
@@ -2329,13 +2270,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
@Nullable
private InputBindResult tryReuseConnectionLocked(
- @NonNull InputMethodBindingController bindingController, @NonNull ClientState cs) {
+ @NonNull InputMethodBindingController bindingController, @NonNull ClientState cs,
+ @UserIdInt int userId) {
if (bindingController.hasMainConnection()) {
- if (getCurMethodLocked() != null) {
+ if (bindingController.getCurMethod() != null) {
if (!Flags.useZeroJankProxy()) {
// Return to client, and we will get back with it when
// we have had a session made for it.
- requestClientSessionLocked(cs);
+ requestClientSessionLocked(cs, userId);
requestClientSessionForAccessibilityLocked(cs);
}
return new InputBindResult(
@@ -2361,7 +2303,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
bindingController.getSequenceNumber(), false);
} else {
EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
- getSelectedMethodIdLocked(), bindingDuration, 0);
+ bindingController.getSelectedMethodId(), bindingDuration, 0);
}
}
}
@@ -2402,12 +2344,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void initializeImeLocked(@NonNull IInputMethodInvoker inputMethod, @NonNull IBinder token) {
+ void initializeImeLocked(@NonNull IInputMethodInvoker inputMethod, @NonNull IBinder token,
+ @UserIdInt int userId) {
if (DEBUG) {
Slog.v(TAG, "Sending attach of token: " + token + " for display: "
- + getCurTokenDisplayIdLocked());
+ + getInputMethodBindingController(userId).getCurTokenDisplayId());
}
- inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token),
+ inputMethod.initializeInternal(token,
+ new InputMethodPrivilegedOperationsImpl(this, token, userId),
+ // TODO(b/345519864): Make getInputMethodNavButtonFlagsLocked() multi-user aware
getInputMethodNavButtonFlagsLocked());
}
@@ -2438,7 +2383,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
void onSessionCreated(IInputMethodInvoker method, IInputMethodSession session,
- InputChannel channel) {
+ InputChannel channel, @UserIdInt int userId) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onSessionCreated");
try {
synchronized (ImfLock.class) {
@@ -2448,18 +2393,21 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
channel.dispose();
return;
}
- IInputMethodInvoker curMethod = getCurMethodLocked();
+ final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
+ IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod != null && method != null
&& curMethod.asBinder() == method.asBinder()) {
- if (mCurClient != null) {
- clearClientSessionLocked(mCurClient);
- mCurClient.mCurSession = new SessionState(
- mCurClient, method, session, channel);
+ if (userData.mCurClient != null) {
+ clearClientSessionLocked(userData.mCurClient);
+ userData.mCurClient.mCurSession = new SessionState(
+ userData.mCurClient, method, session, channel);
InputBindResult res = attachNewInputLocked(
- StartInputReason.SESSION_CREATED_BY_IME, true);
- attachNewAccessibilityLocked(StartInputReason.SESSION_CREATED_BY_IME, true);
+ StartInputReason.SESSION_CREATED_BY_IME, true, userId);
+ attachNewAccessibilityLocked(StartInputReason.SESSION_CREATED_BY_IME, true,
+ userId);
if (res.method != null) {
- mCurClient.mClient.onBindMethod(res);
+ userData.mCurClient.mClient.onBindMethod(res);
}
return;
}
@@ -2482,29 +2430,31 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason) {
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason,
+ @UserIdInt int userId) {
+ final var bindingController = getInputMethodBindingController(userId);
bindingController.setSelectedMethodId(null);
// Callback before clean-up binding states.
// TODO(b/338461930): Check if this is still necessary or not.
- onUnbindCurrentMethodByReset();
+ onUnbindCurrentMethodByReset(userId);
bindingController.unbindCurrentMethod();
- unbindCurrentClientLocked(unbindClientReason);
+ unbindCurrentClientLocked(unbindClientReason, userId);
}
@GuardedBy("ImfLock.class")
- void reRequestCurrentClientSessionLocked() {
- if (mCurClient != null) {
- clearClientSessionLocked(mCurClient);
- clearClientSessionForAccessibilityLocked(mCurClient);
- requestClientSessionLocked(mCurClient);
- requestClientSessionForAccessibilityLocked(mCurClient);
+ void reRequestCurrentClientSessionLocked(@UserIdInt int userId) {
+ final var userData = getUserData(userId);
+ if (userData.mCurClient != null) {
+ clearClientSessionLocked(userData.mCurClient);
+ clearClientSessionForAccessibilityLocked(userData.mCurClient);
+ requestClientSessionLocked(userData.mCurClient, userId);
+ requestClientSessionForAccessibilityLocked(userData.mCurClient);
}
}
@GuardedBy("ImfLock.class")
- void requestClientSessionLocked(ClientState cs) {
+ void requestClientSessionLocked(ClientState cs, @UserIdInt int userId) {
if (!cs.mSessionRequested) {
if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
final InputChannel serverChannel;
@@ -2517,14 +2467,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
cs.mSessionRequested = true;
- final IInputMethodInvoker curMethod = getCurMethodLocked();
+ final var bindingController = getInputMethodBindingController(userId);
+ final IInputMethodInvoker curMethod = bindingController.getCurMethod();
final IInputMethodSessionCallback.Stub callback =
new IInputMethodSessionCallback.Stub() {
@Override
public void sessionCreated(IInputMethodSession session) {
final long ident = Binder.clearCallingIdentity();
try {
- onSessionCreated(curMethod, session, serverChannel);
+ onSessionCreated(curMethod, session, serverChannel, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2615,25 +2566,34 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void clearClientSessionsLocked() {
- if (getCurMethodLocked() != null) {
+ void clearClientSessionsLocked(@NonNull InputMethodBindingController bindingController) {
+ final int userId = bindingController.mUserId;
+ final var userData = getUserData(userId);
+ if (bindingController.getCurMethod() != null) {
// TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
@SuppressWarnings("GuardedBy") Consumer<ClientState> clearClientSession = c -> {
- clearClientSessionLocked(c);
- clearClientSessionForAccessibilityLocked(c);
+ // TODO(b/305849394): Figure out what we should do for single user IME mode.
+ final boolean shouldClearClientSession =
+ !mExperimentalConcurrentMultiUserModeEnabled
+ || UserHandle.getUserId(c.mUid) == userId;
+ if (shouldClearClientSession) {
+ clearClientSessionLocked(c);
+ clearClientSessionForAccessibilityLocked(c);
+ }
};
mClientController.forAllClients(clearClientSession);
- finishSessionLocked(mEnabledSession);
- for (int i = 0; i < mEnabledAccessibilitySessions.size(); i++) {
- finishSessionForAccessibilityLocked(mEnabledAccessibilitySessions.valueAt(i));
+ finishSessionLocked(userData.mEnabledSession);
+ for (int i = 0; i < userData.mEnabledAccessibilitySessions.size(); i++) {
+ finishSessionForAccessibilityLocked(
+ userData.mEnabledAccessibilitySessions.valueAt(i));
}
- mEnabledSession = null;
- mEnabledAccessibilitySessions.clear();
+ userData.mEnabledSession = null;
+ userData.mEnabledAccessibilitySessions.clear();
scheduleNotifyImeUidToAudioService(Process.INVALID_UID);
}
hideStatusBarIconLocked();
- mInFullscreenMode = false;
+ getUserData(userId).mInFullscreenMode = false;
mWindowManagerInternal.setDismissImeOnBackKeyPressed(false);
}
@@ -2857,6 +2817,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private void updateSystemUiLocked(int vis, int backDisposition, @UserIdInt int userId) {
final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
final var curToken = bindingController.getCurToken();
if (curToken == null) {
return;
@@ -2868,8 +2829,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
+ " inv: " + (vis & InputMethodService.IME_INVISIBLE)
+ " displayId: " + curTokenDisplayId);
}
- final IBinder focusedWindowToken = mImeBindingState != null
- ? mImeBindingState.mFocusedWindow : null;
+ final IBinder focusedWindowToken = userData.mImeBindingState != null
+ ? userData.mImeBindingState.mFocusedWindow : null;
final Boolean windowPerceptible = focusedWindowToken != null
? mFocusedWindowPerceptible.get(focusedWindowToken) : null;
@@ -2904,8 +2865,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void updateFromSettingsLocked(boolean enabledMayChange) {
- updateInputMethodsFromSettingsLocked(enabledMayChange);
+ void updateFromSettingsLocked(boolean enabledMayChange, @UserIdInt int userId) {
+ updateInputMethodsFromSettingsLocked(enabledMayChange, userId);
mMenuController.updateKeyboardFromSettingsLocked();
}
@@ -2915,7 +2876,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
*
* <p>Never assume what this method is doing is officially supported. For the canonical and
* desired behaviors always refer to single-user code paths such as
- * {@link #updateInputMethodsFromSettingsLocked(boolean)}.</p>
+ * {@link #updateInputMethodsFromSettingsLocked(boolean, int)}.</p>
*
* <p>Here are examples of missing features.</p>
* <ul>
@@ -2964,8 +2925,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
- final int userId = mCurrentUserId;
+ void updateInputMethodsFromSettingsLocked(boolean enabledMayChange, @UserIdInt int userId) {
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
if (enabledMayChange) {
final PackageManager userAwarePackageManager = getPackageManagerForUser(mContext,
@@ -2996,7 +2956,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
}
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ final var bindingController = getInputMethodBindingController(userId);
if (bindingController.getDeviceIdToShowIme() == DEVICE_ID_DEFAULT) {
String ime = SecureSettingsWrapper.getString(
Settings.Secure.DEFAULT_INPUT_METHOD, null, userId);
@@ -3026,14 +2986,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
if (!TextUtils.isEmpty(id)) {
try {
- setInputMethodLocked(id, settings.getSelectedInputMethodSubtypeId(id));
+ setInputMethodLocked(id, settings.getSelectedInputMethodSubtypeId(id), userId);
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Unknown input method from prefs: " + id, e);
- resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_IME_FAILED);
+ resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_IME_FAILED, userId);
}
} else {
// There is no longer an input method set, so stop any current one.
- resetCurrentMethodAndClientLocked(UnbindReason.NO_IME);
+ resetCurrentMethodAndClientLocked(UnbindReason.NO_IME, userId);
}
final var userData = getUserData(userId);
@@ -3055,13 +3015,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void setInputMethodLocked(String id, int subtypeId) {
- setInputMethodLocked(id, subtypeId, DEVICE_ID_DEFAULT);
+ void setInputMethodLocked(String id, int subtypeId, @UserIdInt int userId) {
+ setInputMethodLocked(id, subtypeId, DEVICE_ID_DEFAULT, userId);
}
@GuardedBy("ImfLock.class")
- void setInputMethodLocked(String id, int subtypeId, int deviceId) {
- final int userId = mCurrentUserId;
+ void setInputMethodLocked(String id, int subtypeId, int deviceId, @UserIdInt int userId) {
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
InputMethodInfo info = settings.getMethodMap().get(id);
if (info == null) {
@@ -3096,8 +3055,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
}
if (!Objects.equals(newSubtype, oldSubtype)) {
- setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
- IInputMethodInvoker curMethod = getCurMethodLocked();
+ setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true, userId);
+ IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod != null) {
updateSystemUiLocked(mImeWindowVis, mBackDisposition);
curMethod.changeInputMethodSubtype(newSubtype);
@@ -3116,7 +3075,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
settings.putSelectedDefaultDeviceInputMethod(id);
return;
}
- IInputMethodInvoker curMethod = getCurMethodLocked();
+ IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod != null) {
curMethod.removeStylusHandwritingWindow();
}
@@ -3124,7 +3083,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
try {
// Set a subtype to this input method.
// subtypeId the name of a subtype which will be set.
- setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
+ setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false, userId);
// mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
// because mCurMethodId is stored as a history in
// setSelectedInputMethodAndSubtypeLocked().
@@ -3136,7 +3095,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
intent.putExtra("input_method_id", id);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
- unbindCurrentClientLocked(UnbindReason.SWITCH_IME);
+ unbindCurrentClientLocked(UnbindReason.SWITCH_IME, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3158,14 +3117,20 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return false;
}
+ // TODO(b/305849394): Create a utility method for the following policy.
+ final int userId = mExperimentalConcurrentMultiUserModeEnabled
+ ? UserHandle.getCallingUserId() : mCurrentUserId;
final long ident = Binder.clearCallingIdentity();
+ final var userData = getUserData(userId);
try {
if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
if (Flags.refactorInsetsController()) {
boolean wasVisible = isInputShownLocked();
- if (mImeBindingState != null && mImeBindingState.mFocusedWindowClient != null
- && mImeBindingState.mFocusedWindowClient.mClient != null) {
- mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(true);
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(true);
if (resultReceiver != null) {
resultReceiver.send(
wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN
@@ -3176,7 +3141,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return false;
} else {
return showCurrentInputLocked(windowToken, statsToken, flags, lastClickToolType,
- resultReceiver, reason);
+ resultReceiver, reason, userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -3190,12 +3155,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#showSoftInput", mDumper);
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Infer userId from windowToken
+ final int userId = mCurrentUserId;
final long ident = Binder.clearCallingIdentity();
try {
if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
return showCurrentInputLocked(windowToken, null /* statsToken */, 0 /* flags */,
0 /* lastClickTooType */, null /* resultReceiver */,
- SoftInputShowHideReason.SHOW_SOFT_INPUT);
+ SoftInputShowHideReason.SHOW_SOFT_INPUT, userId);
} finally {
Binder.restoreCallingIdentity(ident);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -3208,11 +3175,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#hideSoftInput", mDumper);
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Infer userId from windowToken
+ final int userId = mCurrentUserId;
final long ident = Binder.clearCallingIdentity();
try {
if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
return hideCurrentInputLocked(windowToken, null /* statsToken */, 0 /* flags */,
- null /* resultReceiver */, SoftInputShowHideReason.HIDE_SOFT_INPUT);
+ null /* resultReceiver */, SoftInputShowHideReason.HIDE_SOFT_INPUT,
+ userId);
} finally {
Binder.restoreCallingIdentity(ident);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -3342,7 +3312,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return false;
}
if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started");
- final IInputMethodInvoker curMethod = getCurMethodLocked();
+ final IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod != null) {
curMethod.canStartStylusHandwriting(requestId.getAsInt(),
connectionlessCallback, cursorAnchorInfo,
@@ -3414,8 +3384,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return false;
}
synchronized (ImfLock.class) {
+ final var bindingController = getInputMethodBindingController(userId);
if (mHwController.isDelegationUsingConnectionlessFlow()) {
- final IInputMethodInvoker curMethod = getCurMethodLocked();
+ final IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod == null) {
return false;
}
@@ -3465,7 +3436,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
Objects.requireNonNull(windowToken, "windowToken must not be null");
synchronized (ImfLock.class) {
Boolean windowPerceptible = mFocusedWindowPerceptible.get(windowToken);
- if (mImeBindingState.mFocusedWindow != windowToken
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
+ if (userData.mImeBindingState.mFocusedWindow != windowToken
|| (windowPerceptible != null && windowPerceptible == perceptible)) {
return;
}
@@ -3477,17 +3450,18 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private boolean showCurrentInputLocked(IBinder windowToken,
- @InputMethodManager.ShowFlags int flags, @SoftInputShowHideReason int reason) {
- final var statsToken = createStatsTokenForFocusedClient(true /* show */, reason);
+ @InputMethodManager.ShowFlags int flags, @SoftInputShowHideReason int reason,
+ @UserIdInt int userId) {
+ final var statsToken = createStatsTokenForFocusedClient(true /* show */, reason, userId);
return showCurrentInputLocked(windowToken, statsToken, flags,
- MotionEvent.TOOL_TYPE_UNKNOWN, null /* resultReceiver */, reason);
+ MotionEvent.TOOL_TYPE_UNKNOWN, null /* resultReceiver */, reason, userId);
}
@GuardedBy("ImfLock.class")
boolean showCurrentInputLocked(IBinder windowToken,
@NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
@MotionEvent.ToolType int lastClickToolType, @Nullable ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ @SoftInputShowHideReason int reason, @UserIdInt int userId) {
if (!mVisibilityStateComputer.onImeShowFlags(statsToken, flags)) {
return false;
}
@@ -3500,22 +3474,24 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
mVisibilityStateComputer.requestImeVisibility(windowToken, true);
- final int userId = mCurrentUserId;
// Ensure binding the connection when IME is going to show.
final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
bindingController.setCurrentMethodVisible();
final IInputMethodInvoker curMethod = bindingController.getCurMethod();
- ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.forLogging().onCancelled(userData.mCurStatsToken,
+ ImeTracker.PHASE_SERVER_WAIT_IME);
final boolean readyToDispatchToIme;
if (Flags.deferShowSoftInputUntilSessionCreation()) {
readyToDispatchToIme =
- curMethod != null && mCurClient != null && mCurClient.mCurSession != null;
+ curMethod != null && userData.mCurClient != null
+ && userData.mCurClient.mCurSession != null;
} else {
readyToDispatchToIme = curMethod != null;
}
if (readyToDispatchToIme) {
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
- mCurStatsToken = null;
+ userData.mCurStatsToken = null;
if (Flags.useHandwritingListenerForTooltype()) {
maybeReportToolType();
@@ -3529,7 +3505,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return true;
} else {
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
- mCurStatsToken = statsToken;
+ userData.mCurStatsToken = statsToken;
}
return false;
}
@@ -3575,16 +3551,22 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
return false;
}
+ // TODO(b/305849394): Create a utility method for the following policy.
+ final int userId = mExperimentalConcurrentMultiUserModeEnabled
+ ? UserHandle.getCallingUserId() : mCurrentUserId;
final long ident = Binder.clearCallingIdentity();
+ final var userData = getUserData(userId);
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
if (Flags.refactorInsetsController()) {
- if (mImeBindingState != null && mImeBindingState.mFocusedWindowClient != null
- && mImeBindingState.mFocusedWindowClient.mClient != null) {
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
boolean wasVisible = isInputShownLocked();
// TODO add windowToken to interface
- mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(false);
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(false);
if (resultReceiver != null) {
resultReceiver.send(wasVisible ? InputMethodManager.RESULT_HIDDEN
: InputMethodManager.RESULT_UNCHANGED_HIDDEN, null);
@@ -3594,7 +3576,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return false;
} else {
return InputMethodManagerService.this.hideCurrentInputLocked(windowToken,
- statsToken, flags, resultReceiver, reason);
+ statsToken, flags, resultReceiver, reason, userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -3607,23 +3589,27 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
public void hideSoftInputFromServerForTest() {
synchronized (ImfLock.class) {
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_SOFT_INPUT);
+ // TODO(b/305849394): Get userId from caller.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
+ SoftInputShowHideReason.HIDE_SOFT_INPUT, userId);
}
}
@GuardedBy("ImfLock.class")
private boolean hideCurrentInputLocked(IBinder windowToken,
- @InputMethodManager.HideFlags int flags, @SoftInputShowHideReason int reason) {
- final var statsToken = createStatsTokenForFocusedClient(false /* show */, reason);
+ @InputMethodManager.HideFlags int flags, @SoftInputShowHideReason int reason,
+ @UserIdInt int userId) {
+ final var statsToken = createStatsTokenForFocusedClient(false /* show */, reason, userId);
return hideCurrentInputLocked(windowToken, statsToken, flags, null /* resultReceiver */,
- reason);
+ reason, userId);
}
@GuardedBy("ImfLock.class")
boolean hideCurrentInputLocked(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
@InputMethodManager.HideFlags int flags, @Nullable ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ @SoftInputShowHideReason int reason, @UserIdInt int userId) {
if (!mVisibilityStateComputer.canHideIme(statsToken, flags)) {
return false;
}
@@ -3636,8 +3622,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only
// IMMS#InputShown indicates that the software keyboard is shown.
// TODO(b/246309664): Clean up IMMS#mImeWindowVis
- final int userId = mCurrentUserId;
final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
IInputMethodInvoker curMethod = bindingController.getCurMethod();
final boolean shouldHideSoftInput = curMethod != null
&& (isInputShownLocked() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
@@ -3657,8 +3643,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
bindingController.setCurrentMethodNotVisible();
mVisibilityStateComputer.clearImeShowFlags();
// Cancel existing statsToken for show IME as we got a hide request.
- ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
- mCurStatsToken = null;
+ ImeTracker.forLogging().onCancelled(userData.mCurStatsToken,
+ ImeTracker.PHASE_SERVER_WAIT_IME);
+ userData.mCurStatsToken = null;
return shouldHideSoftInput;
}
@@ -3728,7 +3715,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return new InputBindResult(
InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY,
null /* method */, null /* accessibilitySessions */, null /* channel */,
- getSelectedMethodIdLocked(),
+ bindingController.getSelectedMethodId(),
bindingController.getSequenceNumber(),
false /* isInputMethodSuppressingSpellChecker */);
}
@@ -3788,7 +3775,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final boolean shouldClearFlag =
mImePlatformCompatUtils.shouldClearShowForcedFlag(cs.mUid);
final boolean showForced = mVisibilityStateComputer.mShowForced;
- if (mImeBindingState.mFocusedWindow != windowToken
+ final var userData = getUserData(userId);
+ if (userData.mImeBindingState.mFocusedWindow != windowToken
&& showForced && shouldClearFlag) {
mVisibilityStateComputer.mShowForced = false;
}
@@ -3807,8 +3795,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
Slog.w(TAG, "If you need to impersonate a foreground user/profile from"
+ " a background user, use EditorInfo.targetInputMethodUser with"
+ " INTERACT_ACROSS_USERS_FULL permission.");
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_INVALID_USER);
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow,
+ 0 /* flags */, SoftInputShowHideReason.HIDE_INVALID_USER, userId);
return InputBindResult.INVALID_USER;
}
@@ -3868,7 +3856,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
+ " cs=" + cs);
}
- final boolean sameWindowFocused = mImeBindingState.mFocusedWindow == windowToken;
+ final int userId = bindingController.mUserId;
+ final var userData = getUserData(userId);
+ final boolean sameWindowFocused = userData.mImeBindingState.mFocusedWindow == windowToken;
final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
final boolean startInputByWinGainedFocus =
(startInputFlags & StartInputFlags.WINDOW_GAINED_FOCUS) != 0;
@@ -3900,7 +3890,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
null, null, null, null, -1, false);
}
- mImeBindingState = new ImeBindingState(bindingController.mUserId, windowToken,
+ userData.mImeBindingState = new ImeBindingState(bindingController.mUserId, windowToken,
softInputMode, cs, editorInfo);
mFocusedWindowPerceptible.put(windowToken, true);
@@ -3931,16 +3921,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
break;
}
- final var statsToken = createStatsTokenForFocusedClient(isShow, imeVisRes.getReason());
- mVisibilityApplier.applyImeVisibility(mImeBindingState.mFocusedWindow, statsToken,
- imeVisRes.getState(), imeVisRes.getReason(), bindingController.mUserId);
+ final var statsToken = createStatsTokenForFocusedClient(isShow, imeVisRes.getReason(),
+ userId);
+ mVisibilityApplier.applyImeVisibility(userData.mImeBindingState.mFocusedWindow,
+ statsToken, imeVisRes.getState(), imeVisRes.getReason(), userId);
if (imeVisRes.getReason() == SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW) {
// If focused display changed, we should unbind current method
// to make app window in previous display relayout after Ime
// window token removed.
// Note that we can trust client's display ID as long as it matches
// to the display ID obtained from the window.
- if (cs.mSelfReportedDisplayId != getCurTokenDisplayIdLocked()) {
+ if (cs.mSelfReportedDisplayId != bindingController.getCurTokenDisplayId()) {
bindingController.unbindCurrentMethod();
}
}
@@ -3961,8 +3952,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private boolean canInteractWithImeLocked(int uid, IInputMethodClient client, String methodName,
@Nullable ImeTracker.Token statsToken) {
- if (mCurClient == null || client == null
- || mCurClient.mClient.asBinder() != client.asBinder()) {
+ // TODO(b/305849394): Get userId from callers.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
+ if (userData.mCurClient == null || client == null
+ || userData.mCurClient.mClient.asBinder() != client.asBinder()) {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
@@ -3972,7 +3966,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
throw new IllegalArgumentException("unknown client " + client.asBinder());
}
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
- if (!isImeClientFocused(mImeBindingState.mFocusedWindow, cs)) {
+ if (!isImeClientFocused(userData.mImeBindingState.mFocusedWindow, cs)) {
Slog.w(TAG, String.format("Ignoring %s of uid %d : %s", methodName, uid, client));
return false;
}
@@ -3984,14 +3978,18 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
final int uid = Binder.getCallingUid();
- if (mImeBindingState.mFocusedWindowClient != null && client != null
- && mImeBindingState.mFocusedWindowClient.mClient.asBinder() == client.asBinder()) {
+ // TODO(b/305849394): Get userId from callers.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
+ if (userData.mImeBindingState.mFocusedWindowClient != null && client != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient.asBinder()
+ == client.asBinder()) {
return true;
}
- if (mCurrentUserId != UserHandle.getUserId(uid)) {
+ if (userId != UserHandle.getUserId(uid)) {
return false;
}
- final var curIntent = getInputMethodBindingController(mCurrentUserId).getCurIntent();
+ final var curIntent = getInputMethodBindingController(userId).getCurIntent();
if (curIntent != null && InputMethodUtils.checkIfPackageBelongsToUid(
mPackageManagerInternal, uid, curIntent.getComponent().getPackageName())) {
return true;
@@ -4008,11 +4006,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
+ Binder.getCallingUid() + ": " + client);
return;
}
-
+ // TODO(b/305849394): Create a utility method for the following policy.
+ final int userId = mExperimentalConcurrentMultiUserModeEnabled
+ ? UserHandle.getCallingUserId() : mCurrentUserId;
+ final var userData = getUserData(userId);
// Always call subtype picker, because subtype picker is a superset of input method
// picker.
- final int displayId =
- (mCurClient != null) ? mCurClient.mSelfReportedDisplayId : DEFAULT_DISPLAY;
+ final int displayId = (userData.mCurClient != null)
+ ? userData.mCurClient.mSelfReportedDisplayId : DEFAULT_DISPLAY;
mHandler.obtainMessage(MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId)
.sendToTarget();
}
@@ -4044,9 +4045,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@BinderThread
- private void setInputMethod(@NonNull IBinder token, String id) {
+ private void setInputMethod(@NonNull IBinder token, String id, @UserIdInt int userId) {
final int callingUid = Binder.getCallingUid();
- final int userId = UserHandle.getUserId(callingUid);
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
return;
@@ -4057,15 +4057,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
imi.getPackageName(), callingUid, userId, settings)) {
throw getExceptionForUnknownImeId(id);
}
- setInputMethodWithSubtypeIdLocked(token, id, NOT_A_SUBTYPE_ID);
+ setInputMethodWithSubtypeIdLocked(token, id, NOT_A_SUBTYPE_ID, userId);
}
}
@BinderThread
private void setInputMethodAndSubtype(@NonNull IBinder token, String id,
- InputMethodSubtype subtype) {
+ InputMethodSubtype subtype, @UserIdInt int userId) {
final int callingUid = Binder.getCallingUid();
- final int userId = UserHandle.getUserId(callingUid);
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
return;
@@ -4078,20 +4077,19 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
if (subtype != null) {
setInputMethodWithSubtypeIdLocked(token, id,
- SubtypeUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode()));
+ SubtypeUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode()), userId);
} else {
- setInputMethod(token, id);
+ setInputMethod(token, id, userId);
}
}
}
@BinderThread
- private boolean switchToPreviousInputMethod(@NonNull IBinder token) {
+ private boolean switchToPreviousInputMethod(@NonNull IBinder token, @UserIdInt int userId) {
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
return false;
}
- final int userId = mCurrentUserId;
final var bindingController = getInputMethodBindingController(userId);
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
final Pair<String, String> lastIme = settings.getLastInputMethodAndSubtype();
@@ -4156,9 +4154,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
if (!TextUtils.isEmpty(targetLastImiId)) {
if (DEBUG) {
Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
- + ", from: " + getSelectedMethodIdLocked() + ", " + subtypeId);
+ + ", from: " + bindingController.getSelectedMethodId() + ", "
+ + subtypeId);
}
- setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
+ setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId, userId);
return true;
} else {
return false;
@@ -4167,18 +4166,19 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@BinderThread
- private boolean switchToNextInputMethod(@NonNull IBinder token, boolean onlyCurrentIme) {
+ private boolean switchToNextInputMethod(@NonNull IBinder token, boolean onlyCurrentIme,
+ @UserIdInt int userId) {
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
return false;
}
- return switchToNextInputMethodLocked(token, onlyCurrentIme);
+ return switchToNextInputMethodLocked(token, onlyCurrentIme, userId);
}
}
@GuardedBy("ImfLock.class")
- private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme) {
- final int userId = mCurrentUserId;
+ private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme,
+ @UserIdInt int userId) {
final var bindingController = getInputMethodBindingController(userId);
final var currentImi = bindingController.getSelectedMethod();
final ImeSubtypeListItem nextSubtype = getUserData(userId).mSwitchingController
@@ -4188,17 +4188,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return false;
}
setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
- nextSubtype.mSubtypeId);
+ nextSubtype.mSubtypeId, userId);
return true;
}
@BinderThread
- private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token) {
+ private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token,
+ @UserIdInt int userId) {
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
return false;
}
- final int userId = mCurrentUserId;
final var bindingController = getInputMethodBindingController(userId);
final var currentImi = bindingController.getSelectedMethod();
final ImeSubtypeListItem nextSubtype = getUserData(userId).mSwitchingController
@@ -4260,7 +4260,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
DirectBootAwareness.AUTO);
InputMethodSettingsRepository.put(userId, newSettings);
if (isCurrentUser) {
- postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
+ postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */,
+ userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -4299,7 +4300,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
if (mSettingsObserver != null) {
mSettingsObserver.mLastEnabled = settings.getEnabledInputMethodsStr();
}
- updateInputMethodsFromSettingsLocked(false /* enabledChanged */);
+ updateInputMethodsFromSettingsLocked(false /* enabledChanged */, userId);
}
}
} finally {
@@ -4318,7 +4319,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@Override
@Deprecated
public int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
- int callingUid = Binder.getCallingUid();
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getCallingUserId();
return Binder.withCleanCallingIdentity(() -> {
final int curTokenDisplayId;
synchronized (ImfLock.class) {
@@ -4326,9 +4328,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
"getInputMethodWindowVisibleHeight", null /* statsToken */)) {
return 0;
}
+ // TODO(b/305849394): Create a utility method for the following policy.
+ final int userId = mExperimentalConcurrentMultiUserModeEnabled
+ ? callingUserId : mCurrentUserId;
+ final var bindingController = getInputMethodBindingController(userId);
// This should probably use the caller's display id, but because this is unsupported
// and maintained only for compatibility, there's no point in fixing it.
- curTokenDisplayId = getCurTokenDisplayIdLocked();
+ curTokenDisplayId = bindingController.getCurTokenDisplayId();
}
return mWindowManagerInternal.getInputMethodWindowVisibleHeight(curTokenDisplayId);
});
@@ -4593,27 +4599,29 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
private void dumpDebug(ProtoOutputStream proto, long fieldId) {
synchronized (ImfLock.class) {
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ final int userId = mCurrentUserId;
+ final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
final long token = proto.start(fieldId);
- proto.write(CUR_METHOD_ID, getSelectedMethodIdLocked());
+ proto.write(CUR_METHOD_ID, bindingController.getSelectedMethodId());
proto.write(CUR_SEQ, bindingController.getSequenceNumber());
- proto.write(CUR_CLIENT, Objects.toString(mCurClient));
- mImeBindingState.dumpDebug(proto, mWindowManagerInternal);
+ proto.write(CUR_CLIENT, Objects.toString(userData.mCurClient));
+ userData.mImeBindingState.dumpDebug(proto, mWindowManagerInternal);
proto.write(LAST_IME_TARGET_WINDOW_NAME,
mWindowManagerInternal.getWindowName(mLastImeTargetWindow));
proto.write(CUR_FOCUSED_WINDOW_SOFT_INPUT_MODE, InputMethodDebug.softInputModeToString(
- mImeBindingState.mFocusedWindowSoftInputMode));
- if (mCurEditorInfo != null) {
- mCurEditorInfo.dumpDebug(proto, CUR_ATTRIBUTE);
+ userData.mImeBindingState.mFocusedWindowSoftInputMode));
+ if (userData.mCurEditorInfo != null) {
+ userData.mCurEditorInfo.dumpDebug(proto, CUR_ATTRIBUTE);
}
proto.write(CUR_ID, bindingController.getCurId());
mVisibilityStateComputer.dumpDebug(proto, fieldId);
- proto.write(IN_FULLSCREEN_MODE, mInFullscreenMode);
- proto.write(CUR_TOKEN, Objects.toString(getCurTokenLocked()));
- proto.write(CUR_TOKEN_DISPLAY_ID, getCurTokenDisplayIdLocked());
+ proto.write(IN_FULLSCREEN_MODE, userData.mInFullscreenMode);
+ proto.write(CUR_TOKEN, Objects.toString(bindingController.getCurToken()));
+ proto.write(CUR_TOKEN_DISPLAY_ID, bindingController.getCurTokenDisplayId());
proto.write(SYSTEM_READY, mSystemReady);
proto.write(HAVE_CONNECTION, bindingController.hasMainConnection());
- proto.write(BOUND_TO_METHOD, mBoundToMethod);
+ proto.write(BOUND_TO_METHOD, userData.mBoundToMethod);
proto.write(IS_INTERACTIVE, mIsInteractive);
proto.write(BACK_DISPOSITION, mBackDisposition);
proto.write(IME_WINDOW_VISIBILITY, mImeWindowVis);
@@ -4623,20 +4631,19 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@BinderThread
- private void notifyUserAction(@NonNull IBinder token) {
+ private void notifyUserAction(@NonNull IBinder token, @UserIdInt int userId) {
if (DEBUG) {
Slog.d(TAG, "Got the notification of a user action.");
}
synchronized (ImfLock.class) {
- if (getCurTokenLocked() != token) {
+ final var bindingController = getInputMethodBindingController(userId);
+ if (bindingController.getCurToken() != token) {
if (DEBUG) {
Slog.d(TAG, "Ignoring the user action notification from IMEs that are no longer"
+ " active.");
}
return;
}
- final int userId = mCurrentUserId;
- final var bindingController = getInputMethodBindingController(userId);
final InputMethodInfo imi = bindingController.getSelectedMethod();
if (imi != null) {
getUserData(userId).mSwitchingController.onUserActionLocked(imi,
@@ -4647,7 +4654,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
private void applyImeVisibility(IBinder token, IBinder windowToken, boolean setVisible,
- @NonNull ImeTracker.Token statsToken) {
+ @NonNull ImeTracker.Token statsToken, @UserIdInt int userId) {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
synchronized (ImfLock.class) {
@@ -4659,10 +4666,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(
- windowToken);
+ windowToken, userId);
mVisibilityApplier.applyImeVisibility(requestToken, statsToken,
setVisible ? ImeVisibilityStateComputer.STATE_SHOW_IME
- : ImeVisibilityStateComputer.STATE_HIDE_IME, mCurrentUserId);
+ : ImeVisibilityStateComputer.STATE_HIDE_IME, userId);
}
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -4683,7 +4690,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
+ private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId,
+ @UserIdInt int userId) {
+ final var bindingController = getInputMethodBindingController(userId);
if (token == null) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS)
@@ -4692,7 +4701,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
"Using null token requires permission "
+ android.Manifest.permission.WRITE_SECURE_SETTINGS);
}
- } else if (getCurTokenLocked() != token) {
+ } else if (bindingController.getCurToken() != token) {
Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
+ " token: " + token);
return;
@@ -4708,7 +4717,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final long ident = Binder.clearCallingIdentity();
try {
- setInputMethodLocked(id, subtypeId);
+ setInputMethodLocked(id, subtypeId, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -4721,17 +4730,20 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
void onShowHideSoftInputRequested(boolean show, IBinder requestImeToken,
@SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken,
@UserIdInt int userId) {
- final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(requestImeToken);
+ final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(requestImeToken,
+ userId);
final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
final WindowManagerInternal.ImeTargetInfo info =
mWindowManagerInternal.onToggleImeRequested(
- show, mImeBindingState.mFocusedWindow, requestToken,
+ show, userData.mImeBindingState.mFocusedWindow, requestToken,
bindingController.getCurTokenDisplayId());
mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry(
- mImeBindingState.mFocusedWindowClient, mImeBindingState.mFocusedWindowEditorInfo,
- info.focusedWindowName, mImeBindingState.mFocusedWindowSoftInputMode, reason,
- mInFullscreenMode, info.requestWindowName, info.imeControlTargetName,
- info.imeLayerTargetName, info.imeSurfaceParentName));
+ userData.mImeBindingState.mFocusedWindowClient,
+ userData.mImeBindingState.mFocusedWindowEditorInfo,
+ info.focusedWindowName, userData.mImeBindingState.mFocusedWindowSoftInputMode,
+ reason, userData.mInFullscreenMode, info.requestWindowName,
+ info.imeControlTargetName, info.imeLayerTargetName, info.imeSurfaceParentName));
if (statsToken != null) {
mImeTrackerService.onImmsUpdate(statsToken, info.requestWindowName);
@@ -4740,7 +4752,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
private void hideMySoftInput(@NonNull IBinder token, @NonNull ImeTracker.Token statsToken,
- @InputMethodManager.HideFlags int flags, @SoftInputShowHideReason int reason) {
+ @InputMethodManager.HideFlags int flags, @SoftInputShowHideReason int reason,
+ @UserIdInt int userId) {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
synchronized (ImfLock.class) {
@@ -4749,21 +4762,23 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
return;
}
+ final var userData = getUserData(userId);
ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
final long ident = Binder.clearCallingIdentity();
try {
if (Flags.refactorInsetsController()) {
- mCurClient.mClient.setImeVisibility(false);
+ userData.mCurClient.mClient.setImeVisibility(false);
// TODO we will loose the flags here
- if (mImeBindingState != null
- && mImeBindingState.mFocusedWindowClient != null
- && mImeBindingState.mFocusedWindowClient.mClient != null) {
- mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(false);
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(false);
}
} else {
hideCurrentInputLocked(mLastImeTargetWindow, statsToken, flags,
- null /* resultReceiver */, reason);
+ null /* resultReceiver */, reason, userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -4776,7 +4791,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
private void showMySoftInput(@NonNull IBinder token, @NonNull ImeTracker.Token statsToken,
- @InputMethodManager.ShowFlags int flags, @SoftInputShowHideReason int reason) {
+ @InputMethodManager.ShowFlags int flags, @SoftInputShowHideReason int reason,
+ @UserIdInt int userId) {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
synchronized (ImfLock.class) {
@@ -4785,21 +4801,24 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
return;
}
+ final var userData = getUserData(userId);
ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
final long ident = Binder.clearCallingIdentity();
try {
if (Flags.refactorInsetsController()) {
- mCurClient.mClient.setImeVisibility(false);
+ userData.mCurClient.mClient.setImeVisibility(false);
// TODO we will loose the flags here
- if (mImeBindingState != null
- && mImeBindingState.mFocusedWindowClient != null
- && mImeBindingState.mFocusedWindowClient.mClient != null) {
- mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(true);
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(true);
}
} else {
showCurrentInputLocked(mLastImeTargetWindow, statsToken, flags,
- MotionEvent.TOOL_TYPE_UNKNOWN, null /* resultReceiver */, reason);
+ MotionEvent.TOOL_TYPE_UNKNOWN, null /* resultReceiver */, reason,
+ userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -4820,36 +4839,43 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
void onApplyImeVisibilityFromComputer(IBinder windowToken, @NonNull ImeTracker.Token statsToken,
@NonNull ImeVisibilityResult result) {
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Infer userId from windowToken
+ final int userId = mCurrentUserId;
mVisibilityApplier.applyImeVisibility(windowToken, statsToken, result.getState(),
- result.getReason(), mCurrentUserId);
+ result.getReason(), userId);
}
}
@GuardedBy("ImfLock.class")
- void setEnabledSessionLocked(SessionState session) {
- if (mEnabledSession != session) {
- if (mEnabledSession != null && mEnabledSession.mSession != null) {
- if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
- mEnabledSession.mMethod.setSessionEnabled(mEnabledSession.mSession, false);
+ void setEnabledSessionLocked(SessionState session,
+ @NonNull UserDataRepository.UserData userData) {
+ if (userData.mEnabledSession != session) {
+ if (userData.mEnabledSession != null && userData.mEnabledSession.mSession != null) {
+ if (DEBUG) Slog.v(TAG, "Disabling: " + userData.mEnabledSession);
+ userData.mEnabledSession.mMethod.setSessionEnabled(
+ userData.mEnabledSession.mSession, false);
}
- mEnabledSession = session;
- if (mEnabledSession != null && mEnabledSession.mSession != null) {
- if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
- mEnabledSession.mMethod.setSessionEnabled(mEnabledSession.mSession, true);
+ userData.mEnabledSession = session;
+ if (userData.mEnabledSession != null && userData.mEnabledSession.mSession != null) {
+ if (DEBUG) Slog.v(TAG, "Enabling: " + userData.mEnabledSession);
+ userData.mEnabledSession.mMethod.setSessionEnabled(
+ userData.mEnabledSession.mSession, true);
}
}
}
@GuardedBy("ImfLock.class")
void setEnabledSessionForAccessibilityLocked(
- SparseArray<AccessibilitySessionState> accessibilitySessions) {
+ SparseArray<AccessibilitySessionState> accessibilitySessions,
+ @NonNull UserDataRepository.UserData userData) {
// mEnabledAccessibilitySessions could the same object as accessibilitySessions.
SparseArray<IAccessibilityInputMethodSession> disabledSessions = new SparseArray<>();
- for (int i = 0; i < mEnabledAccessibilitySessions.size(); i++) {
- if (!accessibilitySessions.contains(mEnabledAccessibilitySessions.keyAt(i))) {
- AccessibilitySessionState sessionState = mEnabledAccessibilitySessions.valueAt(i);
+ for (int i = 0; i < userData.mEnabledAccessibilitySessions.size(); i++) {
+ if (!accessibilitySessions.contains(userData.mEnabledAccessibilitySessions.keyAt(i))) {
+ AccessibilitySessionState sessionState =
+ userData.mEnabledAccessibilitySessions.valueAt(i);
if (sessionState != null) {
- disabledSessions.append(mEnabledAccessibilitySessions.keyAt(i),
+ disabledSessions.append(userData.mEnabledAccessibilitySessions.keyAt(i),
sessionState.mSession);
}
}
@@ -4860,7 +4886,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
SparseArray<IAccessibilityInputMethodSession> enabledSessions = new SparseArray<>();
for (int i = 0; i < accessibilitySessions.size(); i++) {
- if (!mEnabledAccessibilitySessions.contains(accessibilitySessions.keyAt(i))) {
+ if (!userData.mEnabledAccessibilitySessions.contains(accessibilitySessions.keyAt(i))) {
AccessibilitySessionState sessionState = accessibilitySessions.valueAt(i);
if (sessionState != null) {
enabledSessions.append(accessibilitySessions.keyAt(i), sessionState.mSession);
@@ -4871,7 +4897,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
AccessibilityManagerInternal.get().setImeSessionEnabled(enabledSessions,
true);
}
- mEnabledAccessibilitySessions = accessibilitySessions;
+ userData.mEnabledAccessibilitySessions = accessibilitySessions;
}
@SuppressWarnings("unchecked")
@@ -4931,25 +4957,33 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
case MSG_HIDE_ALL_INPUT_METHODS:
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Needs to figure out what to do where for background users.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
if (Flags.refactorInsetsController()) {
- if (mImeBindingState != null
- && mImeBindingState.mFocusedWindowClient != null
- && mImeBindingState.mFocusedWindowClient.mClient != null) {
- mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(false);
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(false);
}
} else {
@SoftInputShowHideReason final int reason = (int) msg.obj;
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- reason);
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow,
+ 0 /* flags */, reason, userId);
}
}
return true;
case MSG_REMOVE_IME_SURFACE: {
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Needs to figure out what to do where for background users.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
try {
- if (mEnabledSession != null && mEnabledSession.mSession != null
- && !isShowRequestedForCurrentWindow()) {
- mEnabledSession.mSession.removeImeSurface();
+ if (userData.mEnabledSession != null
+ && userData.mEnabledSession.mSession != null
+ && !isShowRequestedForCurrentWindow(userId)) {
+ userData.mEnabledSession.mSession.removeImeSurface();
}
} catch (RemoteException e) {
}
@@ -4959,10 +4993,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
case MSG_REMOVE_IME_SURFACE_FROM_WINDOW: {
IBinder windowToken = (IBinder) msg.obj;
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Infer userId from windowToken.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
try {
- if (windowToken == mImeBindingState.mFocusedWindow
- && mEnabledSession != null && mEnabledSession.mSession != null) {
- mEnabledSession.mSession.removeImeSurface();
+ if (windowToken == userData.mImeBindingState.mFocusedWindow
+ && userData.mEnabledSession != null
+ && userData.mEnabledSession.mSession != null) {
+ userData.mEnabledSession.mSession.removeImeSurface();
}
} catch (RemoteException e) {
}
@@ -5015,9 +5053,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
synchronized (ImfLock.class) {
final var bindingController = getInputMethodBindingController(mCurrentUserId);
if (bindingController.supportsStylusHandwriting()
- && getCurMethodLocked() != null && hasSupportedStylusLocked()) {
+ && bindingController.getCurMethod() != null
+ && hasSupportedStylusLocked()) {
Slog.d(TAG, "Initializing Handwriting Spy");
- mHwController.initializeHandwritingSpy(getCurTokenDisplayIdLocked());
+ mHwController.initializeHandwritingSpy(
+ bindingController.getCurTokenDisplayId());
} else {
mHwController.reset();
}
@@ -5034,18 +5074,21 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
return true;
case MSG_START_HANDWRITING:
+ final var handwritingRequest = (HandwritingRequest) msg.obj;
synchronized (ImfLock.class) {
- IInputMethodInvoker curMethod = getCurMethodLocked();
- if (curMethod == null || mImeBindingState.mFocusedWindow == null) {
+ final int userId = handwritingRequest.userId;
+ final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
+ IInputMethodInvoker curMethod = bindingController.getCurMethod();
+ if (curMethod == null || userData.mImeBindingState.mFocusedWindow == null) {
return true;
}
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
final HandwritingModeController.HandwritingSession session =
mHwController.startHandwritingSession(
- msg.arg1 /*requestId*/,
- msg.arg2 /*pid*/,
+ handwritingRequest.requestId,
+ handwritingRequest.pid,
bindingController.getCurMethodUid(),
- mImeBindingState.mFocusedWindow);
+ userData.mImeBindingState.mFocusedWindow);
if (session == null) {
Slog.e(TAG,
"Failed to start handwriting session for requestId: " + msg.arg1);
@@ -5080,9 +5123,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return false;
}
+ private record HandwritingRequest(int requestId, int pid, @UserIdInt int userId) { }
+
@BinderThread
- private void onStylusHandwritingReady(int requestId, int pid) {
- mHandler.obtainMessage(MSG_START_HANDWRITING, requestId, pid).sendToTarget();
+ private void onStylusHandwritingReady(int requestId, int pid, @UserIdInt int userId) {
+ mHandler.obtainMessage(MSG_START_HANDWRITING,
+ new HandwritingRequest(requestId, pid, userId)).sendToTarget();
}
private void handleSetInteractive(final boolean interactive) {
@@ -5090,8 +5136,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
mIsInteractive = interactive;
updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);
+ // TODO(b/305849394): Support multiple IMEs.
+ final var userId = mCurrentUserId;
+ final var userData = getUserData(userId);
// Inform the current client of the change in active status
- if (mCurClient == null || mCurClient.mClient == null) {
+ if (userData.mCurClient == null || userData.mCurClient.mClient == null) {
return;
}
// TODO(b/325515685): user data must be retrieved by a userId parameter
@@ -5101,18 +5150,19 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// Handle IME visibility when interactive changed before finishing the input to
// ensure we preserve the last state as possible.
final ImeVisibilityResult imeVisRes = mVisibilityStateComputer.onInteractiveChanged(
- mImeBindingState.mFocusedWindow, interactive);
+ userData.mImeBindingState.mFocusedWindow, interactive);
if (imeVisRes != null) {
// Pass in a null statsToken as the IME snapshot is not tracked by ImeTracker.
- mVisibilityApplier.applyImeVisibility(mImeBindingState.mFocusedWindow,
+ mVisibilityApplier.applyImeVisibility(userData.mImeBindingState.mFocusedWindow,
null /* statsToken */, imeVisRes.getState(), imeVisRes.getReason(),
- mCurrentUserId);
+ userId);
}
// Eligible IME processes use new "setInteractive" protocol.
- mCurClient.mClient.setInteractive(mIsInteractive, mInFullscreenMode);
+ userData.mCurClient.mClient.setInteractive(mIsInteractive,
+ userData.mInFullscreenMode);
} else {
// Legacy IME processes continue using legacy "setActive" protocol.
- mCurClient.mClient.setActive(mIsInteractive, mInFullscreenMode);
+ userData.mCurClient.mClient.setActive(mIsInteractive, userData.mInFullscreenMode);
}
}
}
@@ -5229,7 +5279,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- void postInputMethodSettingUpdatedLocked(boolean resetDefaultEnabledIme) {
+ void postInputMethodSettingUpdatedLocked(boolean resetDefaultEnabledIme,
+ @UserIdInt int userId) {
if (DEBUG) {
Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
+ " \n ------ caller=" + Debug.getCallers(10));
@@ -5239,7 +5290,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
return;
}
- final int userId = mCurrentUserId;
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
boolean reenableMinimumNonAuxSystemImes = false;
@@ -5292,7 +5342,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
if (!settings.getMethodMap().containsKey(defaultImiId)) {
Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
if (chooseNewDefaultIMELocked()) {
- updateInputMethodsFromSettingsLocked(true);
+ updateInputMethodsFromSettingsLocked(true, userId);
}
} else {
// Double check that the default IME is certainly enabled.
@@ -5418,11 +5468,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
- boolean setSubtypeOnly) {
- final int userId = mCurrentUserId;
+ boolean setSubtypeOnly, @UserIdInt int userId) {
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
final var bindingController = getInputMethodBindingController(userId);
- settings.saveCurrentInputMethodAndSubtypeToHistory(getSelectedMethodIdLocked(),
+ settings.saveCurrentInputMethodAndSubtypeToHistory(bindingController.getSelectedMethodId(),
bindingController.getCurrentSubtype());
// Set Subtype here
@@ -5456,11 +5505,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@GuardedBy("ImfLock.class")
private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ // TODO(b/305849394): get userId from callers
+ final int userId = mCurrentUserId;
+ final var bindingController = getInputMethodBindingController(userId);
bindingController.setDisplayIdToShowIme(INVALID_DISPLAY);
bindingController.setDeviceIdToShowIme(DEVICE_ID_DEFAULT);
- final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+ final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
settings.putSelectedDefaultDeviceInputMethod(null);
InputMethodInfo imi = settings.getMethodMap().get(newDefaultIme);
@@ -5477,7 +5528,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
}
}
- setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
+ setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false, userId);
}
/**
@@ -5561,7 +5612,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
.contains(settings.getMethodMap().get(imeId))) {
return false; // IME is not found or not enabled.
}
- setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID);
+ setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID, userId);
return true;
}
if (!settings.getMethodMap().containsKey(imeId)
@@ -5603,15 +5654,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@GuardedBy("ImfLock.class")
- private void switchKeyboardLayoutLocked(int direction) {
- final int userId = mCurrentUserId;
+ private void switchKeyboardLayoutLocked(int direction, @UserIdInt int userId) {
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
- final InputMethodInfo currentImi = settings.getMethodMap().get(getSelectedMethodIdLocked());
+ final var bindingController = getInputMethodBindingController(userId);
+ final InputMethodInfo currentImi = settings.getMethodMap().get(
+ bindingController.getSelectedMethodId());
if (currentImi == null) {
return;
}
- final var bindingController = getInputMethodBindingController(userId);
final InputMethodSubtypeHandle currentSubtypeHandle =
InputMethodSubtypeHandle.of(currentImi, bindingController.getCurrentSubtype());
final InputMethodSubtypeHandle nextSubtypeHandle =
@@ -5628,7 +5679,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final int subtypeCount = nextImi.getSubtypeCount();
if (subtypeCount == 0) {
if (nextSubtypeHandle.equals(InputMethodSubtypeHandle.of(nextImi, null))) {
- setInputMethodLocked(nextImi.getId(), NOT_A_SUBTYPE_ID);
+ setInputMethodLocked(nextImi.getId(), NOT_A_SUBTYPE_ID, userId);
}
return;
}
@@ -5636,7 +5687,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
for (int i = 0; i < subtypeCount; ++i) {
if (nextSubtypeHandle.equals(
InputMethodSubtypeHandle.of(nextImi, nextImi.getSubtypeAt(i)))) {
- setInputMethodLocked(nextImi.getId(), i);
+ setInputMethodLocked(nextImi.getId(), i, userId);
return;
}
}
@@ -5753,7 +5804,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
//TODO(b/150843766): Check if Input Token is valid.
final IBinder curHostInputToken;
synchronized (ImfLock.class) {
- if (displayId != getCurTokenDisplayIdLocked()) {
+ final var bindingController = getInputMethodBindingController(userId);
+ if (displayId != bindingController.getCurTokenDisplayId()) {
return false;
}
curHostInputToken = getInputMethodBindingController(userId).getCurHostInputToken();
@@ -5767,7 +5819,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@Override
public void reportImeControl(@Nullable IBinder windowToken) {
synchronized (ImfLock.class) {
- if (mImeBindingState.mFocusedWindow != windowToken) {
+ // TODO(b/305849394): Need to infer userId or get userId from callers.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
+ if (userData.mImeBindingState.mFocusedWindow != windowToken) {
// A perceptible value was set for the focused window, but it is no longer in
// control, so we reset the perceptible for the window passed as argument.
// TODO(b/314149476): Investigate whether this logic is still relevant, if not
@@ -5780,10 +5835,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@Override
public void onImeParentChanged(int displayId) {
synchronized (ImfLock.class) {
+ // TODO(b/305849394): Need to infer userId or get userId from callers.
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
// Hide the IME method menu only when the IME surface parent is changed by the
// input target changed, in case seeing the dialog dismiss flickering during
// the next focused window starting the input connection.
- if (mLastImeTargetWindow != mImeBindingState.mFocusedWindow) {
+ if (mLastImeTargetWindow != userData.mImeBindingState.mFocusedWindow) {
mMenuController.hideInputMethodMenuLocked();
}
}
@@ -5806,33 +5864,36 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
public void onSessionForAccessibilityCreated(int accessibilityConnectionId,
IAccessibilityInputMethodSession session, @UserIdInt int userId) {
synchronized (ImfLock.class) {
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
// TODO(b/305829876): Implement user ID verification
- if (mCurClient != null) {
- clearClientSessionForAccessibilityLocked(mCurClient, accessibilityConnectionId);
- mCurClient.mAccessibilitySessions.put(
+ if (userData.mCurClient != null) {
+ clearClientSessionForAccessibilityLocked(userData.mCurClient,
+ accessibilityConnectionId);
+ userData.mCurClient.mAccessibilitySessions.put(
accessibilityConnectionId,
- new AccessibilitySessionState(mCurClient,
+ new AccessibilitySessionState(userData.mCurClient,
accessibilityConnectionId,
session));
attachNewAccessibilityLocked(StartInputReason.SESSION_CREATED_BY_ACCESSIBILITY,
- true);
+ true, userId);
- final SessionState sessionState = mCurClient.mCurSession;
+ final SessionState sessionState = userData.mCurClient.mCurSession;
final IInputMethodSession imeSession = sessionState == null
? null : sessionState.mSession;
final SparseArray<IAccessibilityInputMethodSession>
accessibilityInputMethodSessions =
createAccessibilityInputMethodSessions(
- mCurClient.mAccessibilitySessions);
+ userData.mCurClient.mAccessibilitySessions);
final InputBindResult res = new InputBindResult(
InputBindResult.ResultCode.SUCCESS_WITH_ACCESSIBILITY_SESSION,
imeSession, accessibilityInputMethodSessions, /* channel= */ null,
bindingController.getCurId(),
bindingController.getSequenceNumber(),
/* isInputMethodSuppressingSpellChecker= */ false);
- mCurClient.mClient.onBindAccessibilityService(res, accessibilityConnectionId);
+ userData.mCurClient.mClient.onBindAccessibilityService(res,
+ accessibilityConnectionId);
}
}
}
@@ -5841,33 +5902,34 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
public void unbindAccessibilityFromCurrentClient(int accessibilityConnectionId,
@UserIdInt int userId) {
synchronized (ImfLock.class) {
- final var bindingController = getInputMethodBindingController(mCurrentUserId);
+ final var bindingController = getInputMethodBindingController(userId);
+ final var userData = getUserData(userId);
// TODO(b/305829876): Implement user ID verification
- if (mCurClient != null) {
+ if (userData.mCurClient != null) {
if (DEBUG) {
Slog.v(TAG, "unbindAccessibilityFromCurrentClientLocked: client="
- + mCurClient.mClient.asBinder());
+ + userData.mCurClient.mClient.asBinder());
}
// A11yManagerService unbinds the disabled accessibility service. We don't need
// to do it here.
- mCurClient.mClient.onUnbindAccessibilityService(
+ userData.mCurClient.mClient.onUnbindAccessibilityService(
bindingController.getSequenceNumber(),
accessibilityConnectionId);
}
// We only have sessions when we bound to an input method. Remove this session
// from all clients.
- if (getCurMethodLocked() != null) {
+ if (bindingController.getCurMethod() != null) {
// TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
@SuppressWarnings("GuardedBy") Consumer<ClientState> clearClientSession =
c -> clearClientSessionForAccessibilityLocked(c,
accessibilityConnectionId);
mClientController.forAllClients(clearClientSession);
- AccessibilitySessionState session = mEnabledAccessibilitySessions.get(
+ AccessibilitySessionState session = userData.mEnabledAccessibilitySessions.get(
accessibilityConnectionId);
if (session != null) {
finishSessionForAccessibilityLocked(session);
- mEnabledAccessibilitySessions.remove(accessibilityConnectionId);
+ userData.mEnabledAccessibilitySessions.remove(accessibilityConnectionId);
}
}
}
@@ -5884,14 +5946,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
public void onSwitchKeyboardLayoutShortcut(int direction, int displayId,
IBinder targetWindowToken) {
synchronized (ImfLock.class) {
- switchKeyboardLayoutLocked(direction);
+ // TODO(b/305849394): Infer userId from displayId
+ switchKeyboardLayoutLocked(direction, mCurrentUserId);
}
}
}
@BinderThread
private IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
- @Nullable Uri contentUri, @Nullable String packageName) {
+ @Nullable Uri contentUri, @Nullable String packageName, @UserIdInt int imeUserId) {
if (token == null) {
throw new NullPointerException("token");
}
@@ -5908,15 +5971,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
synchronized (ImfLock.class) {
final int uid = Binder.getCallingUid();
- final int imeUserId = UserHandle.getUserId(uid);
- if (imeUserId != mCurrentUserId) {
- // Currently concurrent multi-user is not supported here due to the remaining
- // dependency on mCurEditorInfo and mCurClient.
- // TODO(b/341558132): Remove this early-exit once it becomes multi-user ready.
- Slog.i(TAG, "Ignoring createInputContentUriToken due to user ID mismatch."
- + " imeUserId=" + imeUserId + " mCurrentUserId=" + mCurrentUserId);
- return null;
- }
final var bindingController = getInputMethodBindingController(imeUserId);
if (bindingController.getSelectedMethodId() == null) {
return null;
@@ -5929,16 +5983,16 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
// We cannot simply distinguish a bad IME that reports an arbitrary package name from
// an unfortunate IME whose internal state is already obsolete due to the asynchronous
// nature of our system. Let's compare it with our internal record.
- // TODO(b/341558132): Use "imeUserId" to query per-user "curEditorInfo"
- final var curPackageName = mCurEditorInfo != null ? mCurEditorInfo.packageName : null;
+ final var userData = getUserData(imeUserId);
+ final var curPackageName = userData.mCurEditorInfo != null
+ ? userData.mCurEditorInfo.packageName : null;
if (!TextUtils.equals(curPackageName, packageName)) {
Slog.e(TAG, "Ignoring createInputContentUriToken mCurEditorInfo.packageName="
+ curPackageName + " packageName=" + packageName);
return null;
}
// This user ID can never be spoofed.
- // TODO(b/341558132): Use "imeUserId" to query per-user "curClient"
- final int appUserId = UserHandle.getUserId(mCurClient.mUid);
+ final int appUserId = UserHandle.getUserId(userData.mCurClient.mUid);
// This user ID may be invalid if "contentUri" embedded an invalid user ID.
final int contentUriOwnerUserId = ContentProvider.getUserIdFromUri(contentUri,
imeUserId);
@@ -5955,14 +6009,16 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
@BinderThread
- private void reportFullscreenMode(@NonNull IBinder token, boolean fullscreen) {
+ private void reportFullscreenMode(@NonNull IBinder token, boolean fullscreen,
+ @UserIdInt int userId) {
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
return;
}
- if (mCurClient != null && mCurClient.mClient != null) {
- mInFullscreenMode = fullscreen;
- mCurClient.mClient.reportFullscreenMode(fullscreen);
+ final var userData = getUserData(userId);
+ if (userData.mCurClient != null && userData.mCurClient.mClient != null) {
+ userData.mInFullscreenMode = fullscreen;
+ userData.mCurClient.mClient.reportFullscreenMode(fullscreen);
}
}
}
@@ -6055,7 +6111,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final Printer p = new PrintWriterPrinter(pw);
synchronized (ImfLock.class) {
- final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+ final int userId = mCurrentUserId;
+ final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
+ final var userData = getUserData(userId);
p.println("Current Input Method Manager state:");
final List<InputMethodInfo> methodList = settings.getMethodList();
int numImes = methodList.size();
@@ -6085,16 +6143,16 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
mClientController.forAllClients(clientControllerDump);
final var bindingController = getInputMethodBindingController(mCurrentUserId);
p.println(" mCurrentUserId=" + mCurrentUserId);
- p.println(" mCurMethodId=" + getSelectedMethodIdLocked());
- client = mCurClient;
+ p.println(" mCurMethodId=" + bindingController.getSelectedMethodId());
+ client = userData.mCurClient;
p.println(" mCurClient=" + client + " mCurSeq="
+ bindingController.getSequenceNumber());
p.println(" mFocusedWindowPerceptible=" + mFocusedWindowPerceptible);
- mImeBindingState.dump(/* prefix= */ " ", p);
+ userData.mImeBindingState.dump(/* prefix= */ " ", p);
p.println(" mCurId=" + bindingController.getCurId()
+ " mHaveConnection=" + bindingController.hasMainConnection()
- + " mBoundToMethod=" + mBoundToMethod + " mVisibleBound="
+ + " mBoundToMethod=" + userData.mBoundToMethod + " mVisibleBound="
+ bindingController.isVisibleBound());
p.println(" mUserDataRepository=");
@@ -6110,15 +6168,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
};
mUserDataRepository.forAllUserData(userDataDump);
- p.println(" mCurToken=" + getCurTokenLocked());
- p.println(" mCurTokenDisplayId=" + getCurTokenDisplayIdLocked());
+ p.println(" mCurToken=" + bindingController.getCurToken());
+ p.println(" mCurTokenDisplayId=" + bindingController.getCurTokenDisplayId());
p.println(" mCurHostInputToken=" + bindingController.getCurHostInputToken());
p.println(" mCurIntent=" + bindingController.getCurIntent());
- method = getCurMethodLocked();
- p.println(" mCurMethod=" + getCurMethodLocked());
- p.println(" mEnabledSession=" + mEnabledSession);
+ method = bindingController.getCurMethod();
+ p.println(" mCurMethod=" + method);
+ p.println(" mEnabledSession=" + userData.mEnabledSession);
mVisibilityStateComputer.dump(pw, " ");
- p.println(" mInFullscreenMode=" + mInFullscreenMode);
+ p.println(" mInFullscreenMode=" + userData.mInFullscreenMode);
p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
p.println(" mExperimentalConcurrentMultiUserModeEnabled="
+ mExperimentalConcurrentMultiUserModeEnabled);
@@ -6154,20 +6212,24 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
} else {
p.println("No input method client.");
}
-
- if (mImeBindingState.mFocusedWindowClient != null
- && client != mImeBindingState.mFocusedWindowClient) {
- p.println(" ");
- p.println("Warning: Current input method client doesn't match the last focused. "
- + "window.");
- p.println("Dumping input method client in the last focused window just in case.");
- p.println(" ");
- pw.flush();
- try {
- TransferPipe.dumpAsync(
- mImeBindingState.mFocusedWindowClient.mClient.asBinder(), fd, args);
- } catch (IOException | RemoteException e) {
- p.println("Failed to dump input method client in focused window: " + e);
+ synchronized (ImfLock.class) {
+ final int userId = mCurrentUserId;
+ final var userData = getUserData(userId);
+ if (userData.mImeBindingState.mFocusedWindowClient != null
+ && client != userData.mImeBindingState.mFocusedWindowClient) {
+ p.println(" ");
+ p.println("Warning: Current input method client doesn't match the last focused. "
+ + "window.");
+ p.println("Dumping input method client in the last focused window just in case.");
+ p.println(" ");
+ pw.flush();
+ try {
+ TransferPipe.dumpAsync(
+ userData.mImeBindingState.mFocusedWindowClient.mClient.asBinder(), fd,
+ args);
+ } catch (IOException | RemoteException e) {
+ p.println("Failed to dump input method client in focused window: " + e);
+ }
}
}
@@ -6603,18 +6665,21 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
final List<InputMethodInfo> nextEnabledImes;
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
if (userId == mCurrentUserId) {
+ final var userData = getUserData(userId);
if (Flags.refactorInsetsController()) {
- if (mImeBindingState != null
- && mImeBindingState.mFocusedWindowClient != null
- && mImeBindingState.mFocusedWindowClient.mClient != null) {
- mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(
- false);
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient
+ != null) {
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(false);
} else {
// TODO(b329229469): ImeTracker?
}
} else {
- hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
- SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
+ hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow,
+ 0 /* flags */,
+ SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND, userId);
}
final var bindingController = getInputMethodBindingController(userId);
bindingController.unbindCurrentMethod();
@@ -6634,7 +6699,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
if (!chooseNewDefaultIMELocked()) {
resetSelectedInputMethodAndSubtypeLocked(null);
}
- updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
+ updateInputMethodsFromSettingsLocked(true /* enabledMayChange */, userId);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
getPackageManagerForUser(mContext, settings.getUserId()),
settings.getEnabledInputMethodList());
@@ -6743,13 +6808,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
* @param reason the reason why the IME request was created
*/
@NonNull
+ @GuardedBy("ImfLock.class")
private ImeTracker.Token createStatsTokenForFocusedClient(boolean show,
- @SoftInputShowHideReason int reason) {
- final int uid = mImeBindingState.mFocusedWindowClient != null
- ? mImeBindingState.mFocusedWindowClient.mUid
+ @SoftInputShowHideReason int reason, @UserIdInt int userId) {
+ final var userData = getUserData(userId);
+ final int uid = userData.mImeBindingState.mFocusedWindowClient != null
+ ? userData.mImeBindingState.mFocusedWindowClient.mUid
: -1;
- final var packageName = mImeBindingState.mFocusedWindowEditorInfo != null
- ? mImeBindingState.mFocusedWindowEditorInfo.packageName
+ final var packageName = userData.mImeBindingState.mFocusedWindowEditorInfo != null
+ ? userData.mImeBindingState.mFocusedWindowEditorInfo.packageName
: "uid(" + uid + ")";
return ImeTracker.forLogging().onStart(packageName, uid,
@@ -6762,11 +6829,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
private final InputMethodManagerService mImms;
@NonNull
private final IBinder mToken;
+ @UserIdInt
+ private final int mUserId;
InputMethodPrivilegedOperationsImpl(InputMethodManagerService imms,
- @NonNull IBinder token) {
+ @NonNull IBinder token, @UserIdInt int userId) {
mImms = imms;
mToken = token;
+ mUserId = userId;
}
@BinderThread
@@ -6794,7 +6864,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@SuppressWarnings("unchecked") final AndroidFuture<IBinder> typedFuture = future;
try {
typedFuture.complete(mImms.createInputContentUriToken(
- mToken, contentUri, packageName).asBinder());
+ mToken, contentUri, packageName, mUserId).asBinder());
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
}
@@ -6803,7 +6873,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
@Override
public void reportFullscreenModeAsync(boolean fullscreen) {
- mImms.reportFullscreenMode(mToken, fullscreen);
+ mImms.reportFullscreenMode(mToken, fullscreen, mUserId);
}
@BinderThread
@@ -6811,7 +6881,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
public void setInputMethod(String id, AndroidFuture future /* T=Void */) {
@SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
- mImms.setInputMethod(mToken, id);
+ mImms.setInputMethod(mToken, id, mUserId);
typedFuture.complete(null);
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
@@ -6824,7 +6894,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
AndroidFuture future /* T=Void */) {
@SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
- mImms.setInputMethodAndSubtype(mToken, id, subtype);
+ mImms.setInputMethodAndSubtype(mToken, id, subtype, mUserId);
typedFuture.complete(null);
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
@@ -6838,7 +6908,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
AndroidFuture future /* T=Void */) {
@SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
- mImms.hideMySoftInput(mToken, statsToken, flags, reason);
+ mImms.hideMySoftInput(mToken, statsToken, flags, reason, mUserId);
typedFuture.complete(null);
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
@@ -6852,7 +6922,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
AndroidFuture future /* T=Void */) {
@SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
- mImms.showMySoftInput(mToken, statsToken, flags, reason);
+ mImms.showMySoftInput(mToken, statsToken, flags, reason, mUserId);
typedFuture.complete(null);
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
@@ -6870,7 +6940,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
public void switchToPreviousInputMethod(AndroidFuture future /* T=Boolean */) {
@SuppressWarnings("unchecked") final AndroidFuture<Boolean> typedFuture = future;
try {
- typedFuture.complete(mImms.switchToPreviousInputMethod(mToken));
+ typedFuture.complete(mImms.switchToPreviousInputMethod(mToken, mUserId));
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
}
@@ -6882,7 +6952,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
AndroidFuture future /* T=Boolean */) {
@SuppressWarnings("unchecked") final AndroidFuture<Boolean> typedFuture = future;
try {
- typedFuture.complete(mImms.switchToNextInputMethod(mToken, onlyCurrentIme));
+ typedFuture.complete(mImms.switchToNextInputMethod(mToken, onlyCurrentIme,
+ mUserId));
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
}
@@ -6893,7 +6964,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
public void shouldOfferSwitchingToNextInputMethod(AndroidFuture future /* T=Boolean */) {
@SuppressWarnings("unchecked") final AndroidFuture<Boolean> typedFuture = future;
try {
- typedFuture.complete(mImms.shouldOfferSwitchingToNextInputMethod(mToken));
+ typedFuture.complete(mImms.shouldOfferSwitchingToNextInputMethod(mToken, mUserId));
} catch (Throwable e) {
typedFuture.completeExceptionally(e);
}
@@ -6902,20 +6973,20 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
@Override
public void notifyUserActionAsync() {
- mImms.notifyUserAction(mToken);
+ mImms.notifyUserAction(mToken, mUserId);
}
@BinderThread
@Override
public void applyImeVisibilityAsync(IBinder windowToken, boolean setVisible,
@NonNull ImeTracker.Token statsToken) {
- mImms.applyImeVisibility(mToken, windowToken, setVisible, statsToken);
+ mImms.applyImeVisibility(mToken, windowToken, setVisible, statsToken, mUserId);
}
@BinderThread
@Override
public void onStylusHandwritingReady(int requestId, int pid) {
- mImms.onStylusHandwritingReady(requestId, pid);
+ mImms.onStylusHandwritingReady(requestId, pid, mUserId);
}
@BinderThread
@@ -6933,7 +7004,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
}
final long ident = Binder.clearCallingIdentity();
try {
- mImms.switchKeyboardLayoutLocked(direction);
+ mImms.switchKeyboardLayoutLocked(direction, mUserId);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 326ef7e055fa..89a31e7a9a0b 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -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();
}
diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
index 3da4a14b10be..48284fb3163c 100644
--- a/services/core/java/com/android/server/inputmethod/UserDataRepository.java
+++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
@@ -17,12 +17,18 @@
package com.android.server.inputmethod;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.pm.UserInfo;
import android.os.Handler;
import android.util.SparseArray;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ImeTracker;
+import android.window.ImeOnBackInvokedDispatcher;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
+import com.android.internal.inputmethod.IRemoteInputConnection;
import com.android.server.pm.UserManagerInternal;
import java.util.function.Consumer;
@@ -96,6 +102,78 @@ final class UserDataRepository {
final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController;
/**
+ * Have we called mCurMethod.bindInput()?
+ */
+ @GuardedBy("ImfLock.class")
+ boolean mBoundToMethod = false;
+
+ /**
+ * Have we called bindInput() for accessibility services?
+ */
+ @GuardedBy("ImfLock.class")
+ boolean mBoundToAccessibility;
+
+ @GuardedBy("ImfLock.class")
+ @NonNull
+ ImeBindingState mImeBindingState = ImeBindingState.newEmptyState();
+
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ ClientState mCurClient = null;
+
+ @GuardedBy("ImfLock.class")
+ boolean mInFullscreenMode;
+
+ /**
+ * The {@link IRemoteInputConnection} last provided by the current client.
+ */
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ IRemoteInputConnection mCurInputConnection;
+
+ /**
+ * The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
+ * receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
+ */
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ ImeOnBackInvokedDispatcher mCurImeDispatcher;
+
+ /**
+ * The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
+ */
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;
+
+ /**
+ * The {@link EditorInfo} last provided by the current client.
+ */
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ EditorInfo mCurEditorInfo;
+
+ /**
+ * The token tracking the current IME show request that is waiting for a connection to an
+ * IME, otherwise {@code null}.
+ */
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ ImeTracker.Token mCurStatsToken;
+
+ /**
+ * Currently enabled session.
+ */
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ InputMethodManagerService.SessionState mEnabledSession;
+
+ @GuardedBy("ImfLock.class")
+ @Nullable
+ SparseArray<InputMethodManagerService.AccessibilitySessionState>
+ mEnabledAccessibilitySessions = new SparseArray<>();
+
+ /**
* Intended to be instantiated only from this file.
*/
private UserData(@UserIdInt int userId,
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
index 757c07c0b683..41aac32ad08f 100644
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
@@ -254,7 +254,7 @@ final class ZeroJankProxy implements IInputMethodManagerImpl.Callback {
synchronized (ImfLock.class) {
ClientState cs = imms.getClientStateLocked(client);
if (cs != null) {
- imms.requestClientSessionLocked(cs);
+ imms.requestClientSessionLocked(cs, userId);
imms.requestClientSessionForAccessibilityLocked(cs);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index d4adba209cd9..9acebf71ee18 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -217,8 +217,8 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
final int displayIdToShowIme = bindingController.getDisplayIdToShowIme();
mInputMethodManagerService.hideCurrentInputLocked(mWindowToken,
statsToken, 0 /* flags */, null /* resultReceiver */,
- HIDE_SWITCH_USER);
- mInputMethodManagerService.onUnbindCurrentMethodByReset();
+ HIDE_SWITCH_USER, mUserId);
+ mInputMethodManagerService.onUnbindCurrentMethodByReset(mUserId);
// Expects applyImeVisibility() -> hideIme() will be called to notify WM for syncing
// the IME hidden state.