Loading services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java 0 → 100644 +106 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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 com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; import com.android.server.pm.UserManagerInternal; /** * Provides accesses to per-user additional {@link android.view.inputmethod.InputMethodSubtype} * persistent storages. */ final class AdditionalSubtypeMapRepository { @GuardedBy("ImfLock.class") @NonNull private static final SparseArray<AdditionalSubtypeMap> sPerUserMap = new SparseArray<>(); /** * Not intended to be instantiated. */ private AdditionalSubtypeMapRepository() { } @NonNull @GuardedBy("ImfLock.class") static AdditionalSubtypeMap get(@UserIdInt int userId) { final AdditionalSubtypeMap map = sPerUserMap.get(userId); if (map != null) { return map; } final AdditionalSubtypeMap newMap = AdditionalSubtypeUtils.load(userId); sPerUserMap.put(userId, newMap); return newMap; } @GuardedBy("ImfLock.class") static void putAndSave(@UserIdInt int userId, @NonNull AdditionalSubtypeMap map, @NonNull InputMethodMap inputMethodMap) { final AdditionalSubtypeMap previous = sPerUserMap.get(userId); if (previous == map) { return; } sPerUserMap.put(userId, map); // TODO: Offload this to a background thread. // TODO: Skip if the previous data is exactly the same as new one. AdditionalSubtypeUtils.save(map, inputMethodMap, userId); } static void initialize(@NonNull Handler handler) { final UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); handler.post(() -> { userManagerInternal.addUserLifecycleListener( new UserManagerInternal.UserLifecycleListener() { @Override public void onUserCreated(UserInfo user, @Nullable Object token) { final int userId = user.id; handler.post(() -> { synchronized (ImfLock.class) { if (!sPerUserMap.contains(userId)) { sPerUserMap.put(userId, AdditionalSubtypeUtils.load(userId)); } } }); } @Override public void onUserRemoved(UserInfo user) { final int userId = user.id; handler.post(() -> { synchronized (ImfLock.class) { sPerUserMap.remove(userId); } }); } }); synchronized (ImfLock.class) { for (int userId : userManagerInternal.getUserIds()) { sPerUserMap.put(userId, AdditionalSubtypeUtils.load(userId)); } } }); } } services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +46 −61 Original line number Diff line number Diff line Loading @@ -288,9 +288,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final ImePlatformCompatUtils mImePlatformCompatUtils; final InputMethodDeviceConfigs mInputMethodDeviceConfigs; @GuardedBy("ImfLock.class") @NonNull private AdditionalSubtypeMap mAdditionalSubtypeMap = AdditionalSubtypeMap.EMPTY_MAP; private final UserManagerInternal mUserManagerInternal; private final InputMethodMenuController mMenuController; @NonNull private final InputMethodBindingController mBindingController; Loading Loading @@ -1310,13 +1307,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final int userId = getChangingUserId(); synchronized (ImfLock.class) { final boolean isCurrentUser = (userId == mSettings.getUserId()); final AdditionalSubtypeMap additionalSubtypeMap; final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final InputMethodSettings settings; if (isCurrentUser) { additionalSubtypeMap = mAdditionalSubtypeMap; settings = mSettings; } else { additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } Loading @@ -1331,11 +1327,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final AdditionalSubtypeMap newMap = additionalSubtypeMap.cloneWithRemoveOrSelf(changedImes); if (newMap != additionalSubtypeMap) { if (isCurrentUser) { mAdditionalSubtypeMap = newMap; } AdditionalSubtypeUtils.save( newMap, settings.getMethodMap(), settings.getUserId()); AdditionalSubtypeMapRepository.putAndSave(userId, newMap, settings.getMethodMap()); } if (!changedImes.isEmpty()) { mChangedPackages.add(packageName); Loading Loading @@ -1382,13 +1375,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { final int userId = getChangingUserId(); final boolean isCurrentUser = (userId == mSettings.getUserId()); AdditionalSubtypeMap additionalSubtypeMap; AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final InputMethodSettings settings; if (isCurrentUser) { additionalSubtypeMap = mAdditionalSubtypeMap; settings = mSettings; } else { additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } Loading Loading @@ -1419,11 +1411,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub + imi.getComponent()); additionalSubtypeMap = additionalSubtypeMap.cloneWithRemoveOrSelf(imi.getId()); AdditionalSubtypeUtils.save(additionalSubtypeMap, settings.getMethodMap(), userId); if (isCurrentUser) { mAdditionalSubtypeMap = additionalSubtypeMap; } AdditionalSubtypeMapRepository.putAndSave(userId, additionalSubtypeMap, settings.getMethodMap()); } } Loading Loading @@ -1658,12 +1647,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mShowOngoingImeSwitcherForPhones = false; AdditionalSubtypeMapRepository.initialize(mHandler); final int userId = mActivityManagerInternal.getCurrentUserId(); // mSettings should be created before buildInputMethodListLocked mSettings = InputMethodSettings.createEmptyMap(userId); mAdditionalSubtypeMap = AdditionalSubtypeUtils.load(userId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(context, mSettings.getMethodMap(), userId); Loading Loading @@ -1808,8 +1798,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mSettingsObserver.registerContentObserverLocked(newUserId); mSettings = InputMethodSettings.createEmptyMap(newUserId); // Additional subtypes should be reset when the user is changed mAdditionalSubtypeMap = AdditionalSubtypeUtils.load(newUserId); final String defaultImiId = mSettings.getSelectedInputMethod(); if (DEBUG) { Loading Loading @@ -2017,7 +2005,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } //TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList. //TODO(b/210039666): use cache. final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); final InputMethodInfo imi = settings.getMethodMap().get( settings.getSelectedInputMethod()); return imi != null && imi.supportsStylusHandwriting() Loading Loading @@ -2045,7 +2033,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub && directBootAwareness == DirectBootAwareness.AUTO) { settings = mSettings; } else { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, directBootAwareness); } Loading @@ -2066,7 +2055,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub methodList = mSettings.getEnabledInputMethodList(); settings = mSettings; } else { settings = queryMethodMapForUser(userId); settings = queryMethodMapForUserLocked(userId); methodList = settings.getEnabledInputMethodList(); } // filter caller's access to input methods Loading Loading @@ -2141,7 +2130,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mSettings.getEnabledInputMethodSubtypeList( imi, allowsImplicitlyEnabledSubtypes); } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); final InputMethodInfo imi = settings.getMethodMap().get(imiId); if (imi == null) { return Collections.emptyList(); Loading Loading @@ -4307,7 +4296,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mSettings.getLastInputMethodSubtype(); } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); return settings.getLastInputMethodSubtype(); } } Loading Loading @@ -4338,33 +4327,25 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return; } if (mSettings.getUserId() == userId) { final var newAdditionalSubtypeMap = mSettings.getNewAdditionalSubtypeMap( imiId, toBeAdded, mAdditionalSubtypeMap, mPackageManagerInternal, callingUid); if (mAdditionalSubtypeMap == newAdditionalSubtypeMap) { return; } AdditionalSubtypeUtils.save(newAdditionalSubtypeMap, mSettings.getMethodMap(), mSettings.getUserId()); mAdditionalSubtypeMap = newAdditionalSubtypeMap; final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final boolean isCurrentUser = (mSettings.getUserId() == userId); final InputMethodSettings settings = isCurrentUser ? mSettings : queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap( imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid); if (additionalSubtypeMap != newAdditionalSubtypeMap) { AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap, settings.getMethodMap()); if (isCurrentUser) { final long ident = Binder.clearCallingIdentity(); try { buildInputMethodListLocked(false /* resetDefaultEnabledIme */); } finally { Binder.restoreCallingIdentity(ident); } return; } final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); final InputMethodSettings settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap( imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid); if (additionalSubtypeMap != newAdditionalSubtypeMap) { AdditionalSubtypeUtils.save(newAdditionalSubtypeMap, settings.getMethodMap(), settings.getUserId()); } } } Loading @@ -4391,7 +4372,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { final boolean currentUser = (mSettings.getUserId() == userId); final InputMethodSettings settings = currentUser ? mSettings : queryMethodMapForUser(userId); ? mSettings : queryMethodMapForUserLocked(userId); if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) { return; } Loading Loading @@ -5293,7 +5274,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mMyPackageMonitor.clearKnownImePackageNamesLocked(); mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(), mAdditionalSubtypeMap, DirectBootAwareness.AUTO); AdditionalSubtypeMapRepository.get(mSettings.getUserId()), DirectBootAwareness.AUTO); // Construct the set of possible IME packages for onPackageChanged() to avoid false // negatives when the package state remains to be the same but only the component state is Loading Loading @@ -5565,7 +5547,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return getCurrentInputMethodSubtypeLocked(); } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); return settings.getCurrentInputMethodSubtypeForNonCurrentUsers(); } } Loading Loading @@ -5632,15 +5614,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (userId == mSettings.getUserId()) { settings = mSettings; } else { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } return settings.getMethodMap().get(settings.getSelectedInputMethod()); } private InputMethodSettings queryMethodMapForUser(@UserIdInt int userId) { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); @GuardedBy("ImfLock.class") private InputMethodSettings queryMethodMapForUserLocked(@UserIdInt int userId) { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); return queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } Loading @@ -5656,7 +5641,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID); return true; } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); if (!settings.getMethodMap().containsKey(imeId) || !settings.getEnabledInputMethodList().contains( settings.getMethodMap().get(imeId))) { Loading Loading @@ -5796,7 +5781,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub setInputMethodEnabledLocked(imeId, enabled); return true; } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); if (!settings.getMethodMap().containsKey(imeId)) { return false; // IME is not found. } Loading Loading @@ -6550,7 +6535,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub previouslyEnabled = setInputMethodEnabledLocked(imeId, enabled); } } else { final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); if (enabled) { if (!settings.getMethodMap().containsKey(imeId)) { failedToEnableUnknownIme = true; Loading Loading @@ -6685,7 +6670,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub nextEnabledImes = mSettings.getEnabledInputMethodList(); } else { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); AdditionalSubtypeMapRepository.get(userId); final InputMethodSettings settings = queryInputMethodServicesInternal( mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); Loading services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java +1 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,7 @@ public class InputMethodManagerServiceTestBase { when(mMockUserManagerInternal.isUserRunning(anyInt())).thenReturn(true); when(mMockUserManagerInternal.getProfileIds(anyInt(), anyBoolean())) .thenReturn(new int[] {0}); when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[] {0}); when(mMockActivityManagerInternal.isSystemReady()).thenReturn(true); when(mMockPackageManagerInternal.getPackageUid(anyString(), anyLong(), anyInt())) .thenReturn(Binder.getCallingUid()); Loading Loading
services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java 0 → 100644 +106 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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 com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; import com.android.server.pm.UserManagerInternal; /** * Provides accesses to per-user additional {@link android.view.inputmethod.InputMethodSubtype} * persistent storages. */ final class AdditionalSubtypeMapRepository { @GuardedBy("ImfLock.class") @NonNull private static final SparseArray<AdditionalSubtypeMap> sPerUserMap = new SparseArray<>(); /** * Not intended to be instantiated. */ private AdditionalSubtypeMapRepository() { } @NonNull @GuardedBy("ImfLock.class") static AdditionalSubtypeMap get(@UserIdInt int userId) { final AdditionalSubtypeMap map = sPerUserMap.get(userId); if (map != null) { return map; } final AdditionalSubtypeMap newMap = AdditionalSubtypeUtils.load(userId); sPerUserMap.put(userId, newMap); return newMap; } @GuardedBy("ImfLock.class") static void putAndSave(@UserIdInt int userId, @NonNull AdditionalSubtypeMap map, @NonNull InputMethodMap inputMethodMap) { final AdditionalSubtypeMap previous = sPerUserMap.get(userId); if (previous == map) { return; } sPerUserMap.put(userId, map); // TODO: Offload this to a background thread. // TODO: Skip if the previous data is exactly the same as new one. AdditionalSubtypeUtils.save(map, inputMethodMap, userId); } static void initialize(@NonNull Handler handler) { final UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); handler.post(() -> { userManagerInternal.addUserLifecycleListener( new UserManagerInternal.UserLifecycleListener() { @Override public void onUserCreated(UserInfo user, @Nullable Object token) { final int userId = user.id; handler.post(() -> { synchronized (ImfLock.class) { if (!sPerUserMap.contains(userId)) { sPerUserMap.put(userId, AdditionalSubtypeUtils.load(userId)); } } }); } @Override public void onUserRemoved(UserInfo user) { final int userId = user.id; handler.post(() -> { synchronized (ImfLock.class) { sPerUserMap.remove(userId); } }); } }); synchronized (ImfLock.class) { for (int userId : userManagerInternal.getUserIds()) { sPerUserMap.put(userId, AdditionalSubtypeUtils.load(userId)); } } }); } }
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +46 −61 Original line number Diff line number Diff line Loading @@ -288,9 +288,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final ImePlatformCompatUtils mImePlatformCompatUtils; final InputMethodDeviceConfigs mInputMethodDeviceConfigs; @GuardedBy("ImfLock.class") @NonNull private AdditionalSubtypeMap mAdditionalSubtypeMap = AdditionalSubtypeMap.EMPTY_MAP; private final UserManagerInternal mUserManagerInternal; private final InputMethodMenuController mMenuController; @NonNull private final InputMethodBindingController mBindingController; Loading Loading @@ -1310,13 +1307,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final int userId = getChangingUserId(); synchronized (ImfLock.class) { final boolean isCurrentUser = (userId == mSettings.getUserId()); final AdditionalSubtypeMap additionalSubtypeMap; final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final InputMethodSettings settings; if (isCurrentUser) { additionalSubtypeMap = mAdditionalSubtypeMap; settings = mSettings; } else { additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } Loading @@ -1331,11 +1327,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final AdditionalSubtypeMap newMap = additionalSubtypeMap.cloneWithRemoveOrSelf(changedImes); if (newMap != additionalSubtypeMap) { if (isCurrentUser) { mAdditionalSubtypeMap = newMap; } AdditionalSubtypeUtils.save( newMap, settings.getMethodMap(), settings.getUserId()); AdditionalSubtypeMapRepository.putAndSave(userId, newMap, settings.getMethodMap()); } if (!changedImes.isEmpty()) { mChangedPackages.add(packageName); Loading Loading @@ -1382,13 +1375,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { final int userId = getChangingUserId(); final boolean isCurrentUser = (userId == mSettings.getUserId()); AdditionalSubtypeMap additionalSubtypeMap; AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final InputMethodSettings settings; if (isCurrentUser) { additionalSubtypeMap = mAdditionalSubtypeMap; settings = mSettings; } else { additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } Loading Loading @@ -1419,11 +1411,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub + imi.getComponent()); additionalSubtypeMap = additionalSubtypeMap.cloneWithRemoveOrSelf(imi.getId()); AdditionalSubtypeUtils.save(additionalSubtypeMap, settings.getMethodMap(), userId); if (isCurrentUser) { mAdditionalSubtypeMap = additionalSubtypeMap; } AdditionalSubtypeMapRepository.putAndSave(userId, additionalSubtypeMap, settings.getMethodMap()); } } Loading Loading @@ -1658,12 +1647,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mShowOngoingImeSwitcherForPhones = false; AdditionalSubtypeMapRepository.initialize(mHandler); final int userId = mActivityManagerInternal.getCurrentUserId(); // mSettings should be created before buildInputMethodListLocked mSettings = InputMethodSettings.createEmptyMap(userId); mAdditionalSubtypeMap = AdditionalSubtypeUtils.load(userId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(context, mSettings.getMethodMap(), userId); Loading Loading @@ -1808,8 +1798,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mSettingsObserver.registerContentObserverLocked(newUserId); mSettings = InputMethodSettings.createEmptyMap(newUserId); // Additional subtypes should be reset when the user is changed mAdditionalSubtypeMap = AdditionalSubtypeUtils.load(newUserId); final String defaultImiId = mSettings.getSelectedInputMethod(); if (DEBUG) { Loading Loading @@ -2017,7 +2005,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } //TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList. //TODO(b/210039666): use cache. final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); final InputMethodInfo imi = settings.getMethodMap().get( settings.getSelectedInputMethod()); return imi != null && imi.supportsStylusHandwriting() Loading Loading @@ -2045,7 +2033,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub && directBootAwareness == DirectBootAwareness.AUTO) { settings = mSettings; } else { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, directBootAwareness); } Loading @@ -2066,7 +2055,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub methodList = mSettings.getEnabledInputMethodList(); settings = mSettings; } else { settings = queryMethodMapForUser(userId); settings = queryMethodMapForUserLocked(userId); methodList = settings.getEnabledInputMethodList(); } // filter caller's access to input methods Loading Loading @@ -2141,7 +2130,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mSettings.getEnabledInputMethodSubtypeList( imi, allowsImplicitlyEnabledSubtypes); } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); final InputMethodInfo imi = settings.getMethodMap().get(imiId); if (imi == null) { return Collections.emptyList(); Loading Loading @@ -4307,7 +4296,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return mSettings.getLastInputMethodSubtype(); } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); return settings.getLastInputMethodSubtype(); } } Loading Loading @@ -4338,33 +4327,25 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return; } if (mSettings.getUserId() == userId) { final var newAdditionalSubtypeMap = mSettings.getNewAdditionalSubtypeMap( imiId, toBeAdded, mAdditionalSubtypeMap, mPackageManagerInternal, callingUid); if (mAdditionalSubtypeMap == newAdditionalSubtypeMap) { return; } AdditionalSubtypeUtils.save(newAdditionalSubtypeMap, mSettings.getMethodMap(), mSettings.getUserId()); mAdditionalSubtypeMap = newAdditionalSubtypeMap; final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final boolean isCurrentUser = (mSettings.getUserId() == userId); final InputMethodSettings settings = isCurrentUser ? mSettings : queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap( imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid); if (additionalSubtypeMap != newAdditionalSubtypeMap) { AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap, settings.getMethodMap()); if (isCurrentUser) { final long ident = Binder.clearCallingIdentity(); try { buildInputMethodListLocked(false /* resetDefaultEnabledIme */); } finally { Binder.restoreCallingIdentity(ident); } return; } final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); final InputMethodSettings settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap( imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid); if (additionalSubtypeMap != newAdditionalSubtypeMap) { AdditionalSubtypeUtils.save(newAdditionalSubtypeMap, settings.getMethodMap(), settings.getUserId()); } } } Loading @@ -4391,7 +4372,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { final boolean currentUser = (mSettings.getUserId() == userId); final InputMethodSettings settings = currentUser ? mSettings : queryMethodMapForUser(userId); ? mSettings : queryMethodMapForUserLocked(userId); if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) { return; } Loading Loading @@ -5293,7 +5274,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mMyPackageMonitor.clearKnownImePackageNamesLocked(); mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(), mAdditionalSubtypeMap, DirectBootAwareness.AUTO); AdditionalSubtypeMapRepository.get(mSettings.getUserId()), DirectBootAwareness.AUTO); // Construct the set of possible IME packages for onPackageChanged() to avoid false // negatives when the package state remains to be the same but only the component state is Loading Loading @@ -5565,7 +5547,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return getCurrentInputMethodSubtypeLocked(); } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); return settings.getCurrentInputMethodSubtypeForNonCurrentUsers(); } } Loading Loading @@ -5632,15 +5614,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (userId == mSettings.getUserId()) { settings = mSettings; } else { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } return settings.getMethodMap().get(settings.getSelectedInputMethod()); } private InputMethodSettings queryMethodMapForUser(@UserIdInt int userId) { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); @GuardedBy("ImfLock.class") private InputMethodSettings queryMethodMapForUserLocked(@UserIdInt int userId) { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); return queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); } Loading @@ -5656,7 +5641,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID); return true; } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); if (!settings.getMethodMap().containsKey(imeId) || !settings.getEnabledInputMethodList().contains( settings.getMethodMap().get(imeId))) { Loading Loading @@ -5796,7 +5781,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub setInputMethodEnabledLocked(imeId, enabled); return true; } final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); if (!settings.getMethodMap().containsKey(imeId)) { return false; // IME is not found. } Loading Loading @@ -6550,7 +6535,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub previouslyEnabled = setInputMethodEnabledLocked(imeId, enabled); } } else { final InputMethodSettings settings = queryMethodMapForUser(userId); final InputMethodSettings settings = queryMethodMapForUserLocked(userId); if (enabled) { if (!settings.getMethodMap().containsKey(imeId)) { failedToEnableUnknownIme = true; Loading Loading @@ -6685,7 +6670,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub nextEnabledImes = mSettings.getEnabledInputMethodList(); } else { final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId); AdditionalSubtypeMapRepository.get(userId); final InputMethodSettings settings = queryInputMethodServicesInternal( mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); Loading
services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java +1 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,7 @@ public class InputMethodManagerServiceTestBase { when(mMockUserManagerInternal.isUserRunning(anyInt())).thenReturn(true); when(mMockUserManagerInternal.getProfileIds(anyInt(), anyBoolean())) .thenReturn(new int[] {0}); when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[] {0}); when(mMockActivityManagerInternal.isSystemReady()).thenReturn(true); when(mMockPackageManagerInternal.getPackageUid(anyString(), anyLong(), anyInt())) .thenReturn(Binder.getCallingUid()); Loading