diff options
| author | 2024-03-13 02:06:12 +0000 | |
|---|---|---|
| committer | 2024-03-13 02:06:12 +0000 | |
| commit | 2fd9434406b1d00739bbb36b39b0c338c3f8647c (patch) | |
| tree | d0cb77b6d2655f3f9c9497a6e4ac5ca55b1868e2 | |
| parent | 4c2f77ff68979c777e4e21d0b69efb33e5d608c6 (diff) | |
| parent | 90622cfcc48b115f6ccab469dd23bccc6d01a965 (diff) | |
Merge "Introduce per-user InputMethodSettings cache" into main
3 files changed, 145 insertions, 34 deletions
diff --git a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java index c7b60da2fc51..dd6433d98553 100644 --- a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java +++ b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java @@ -19,11 +19,13 @@ package com.android.server.inputmethod; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.content.Context; import android.content.pm.UserInfo; import android.os.Handler; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; +import com.android.internal.inputmethod.DirectBootAwareness; import com.android.server.LocalServices; import com.android.server.pm.UserManagerInternal; @@ -67,7 +69,7 @@ final class AdditionalSubtypeMapRepository { AdditionalSubtypeUtils.save(map, inputMethodMap, userId); } - static void initialize(@NonNull Handler handler) { + static void initialize(@NonNull Handler handler, @NonNull Context context) { final UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); handler.post(() -> { @@ -79,8 +81,16 @@ final class AdditionalSubtypeMapRepository { handler.post(() -> { synchronized (ImfLock.class) { if (!sPerUserMap.contains(userId)) { - sPerUserMap.put(userId, - AdditionalSubtypeUtils.load(userId)); + final AdditionalSubtypeMap additionalSubtypeMap = + AdditionalSubtypeUtils.load(userId); + sPerUserMap.put(userId, additionalSubtypeMap); + final InputMethodSettings settings = + InputMethodManagerService + .queryInputMethodServicesInternal(context, + userId, + additionalSubtypeMap, + DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(userId, settings); } } }); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 4b06c06827f6..9525ce72b067 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -867,9 +867,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (!mSystemReady) { return; } - mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(), - AdditionalSubtypeMapRepository.get(mSettings.getUserId()), - DirectBootAwareness.AUTO); + for (int userId : mUserManagerInternal.getUserIds()) { + final InputMethodSettings settings = queryInputMethodServicesInternal( + mContext, + userId, + AdditionalSubtypeMapRepository.get(userId), + DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(userId, settings); + if (userId == mSettings.getUserId()) { + mSettings = settings; + } + } postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */); // If the locale is changed, needs to reset the default ime resetDefaultImeLocked(mContext); @@ -1116,12 +1124,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap, settings.getMethodMap()); } - - if (!isCurrentUser) { + if (isCurrentUser + && !(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) { return; } - if (!(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) { + final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext, + userId, newAdditionalSubtypeMap, DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(userId, newSettings); + if (!isCurrentUser) { return; } mSettings = queryInputMethodServicesInternal(mContext, userId, @@ -1278,21 +1289,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub void onUnlockUser(@UserIdInt int userId) { synchronized (ImfLock.class) { - final int currentUserId = mSettings.getUserId(); if (DEBUG) { - Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + currentUserId); - } - if (userId != currentUserId) { - return; + Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + + mSettings.getUserId()); } if (!mSystemReady) { return; } - mSettings = queryInputMethodServicesInternal(mContext, userId, - AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO); - // We need to rebuild IMEs. - postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */); - updateInputMethodsFromSettingsLocked(true /* enabledChanged */); + final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext, + userId, AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(userId, newSettings); + if (mSettings.getUserId() == userId) { + mSettings = newSettings; + // We need to rebuild IMEs. + postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */); + updateInputMethodsFromSettingsLocked(true /* enabledChanged */); + } } } @@ -1356,12 +1368,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mShowOngoingImeSwitcherForPhones = false; - AdditionalSubtypeMapRepository.initialize(mHandler); + // InputMethodSettingsRepository should be initialized before buildInputMethodListLocked + InputMethodSettingsRepository.initialize(mHandler, mContext); + AdditionalSubtypeMapRepository.initialize(mHandler, mContext); final int userId = mActivityManagerInternal.getCurrentUserId(); - // mSettings should be created before buildInputMethodListLocked - mSettings = InputMethodSettings.createEmptyMap(userId); + mSettings = InputMethodSettingsRepository.get(userId); mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(context, @@ -1525,8 +1538,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // and user switch would not happen at that time. resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_USER); - mSettings = queryInputMethodServicesInternal(mContext, newUserId, - AdditionalSubtypeMapRepository.get(newUserId), DirectBootAwareness.AUTO); + final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext, + newUserId, AdditionalSubtypeMapRepository.get(newUserId), DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(newUserId, newSettings); + mSettings = newSettings; postInputMethodSettingUpdatedLocked(initialUserSwitch /* resetDefaultEnabledIme */); if (TextUtils.isEmpty(mSettings.getSelectedInputMethod())) { // This is the first time of the user switch and @@ -1608,9 +1623,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final String defaultImiId = mSettings.getSelectedInputMethod(); final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId); - mSettings = queryInputMethodServicesInternal(mContext, currentUserId, - AdditionalSubtypeMapRepository.get(mSettings.getUserId()), + final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext, + currentUserId, AdditionalSubtypeMapRepository.get(currentUserId), DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(currentUserId, newSettings); + mSettings = newSettings; postInputMethodSettingUpdatedLocked( !imeSelectedOnBoot /* resetDefaultEnabledIme */); updateFromSettingsLocked(true); @@ -4045,22 +4062,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId); final boolean isCurrentUser = (mSettings.getUserId() == userId); - final InputMethodSettings settings = isCurrentUser - ? mSettings - : queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, - DirectBootAwareness.AUTO); + final InputMethodSettings settings = InputMethodSettingsRepository.get(userId); final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap( imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid); if (additionalSubtypeMap != newAdditionalSubtypeMap) { AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap, settings.getMethodMap()); + final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext, + userId, AdditionalSubtypeMapRepository.get(userId), + DirectBootAwareness.AUTO); + InputMethodSettingsRepository.put(userId, newSettings); if (isCurrentUser) { final long ident = Binder.clearCallingIdentity(); try { - mSettings = queryInputMethodServicesInternal(mContext, - mSettings.getUserId(), - AdditionalSubtypeMapRepository.get(mSettings.getUserId()), - DirectBootAwareness.AUTO); + mSettings = newSettings; postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */); } finally { Binder.restoreCallingIdentity(ident); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java b/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java new file mode 100644 index 000000000000..60b9a4cfe840 --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java @@ -0,0 +1,86 @@ +/* + * 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.UserIdInt; +import android.content.Context; +import android.content.pm.UserInfo; +import android.os.Handler; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.inputmethod.DirectBootAwareness; +import com.android.server.LocalServices; +import com.android.server.pm.UserManagerInternal; + +final class InputMethodSettingsRepository { + @GuardedBy("ImfLock.class") + @NonNull + private static final SparseArray<InputMethodSettings> sPerUserMap = new SparseArray<>(); + + /** + * Not intended to be instantiated. + */ + private InputMethodSettingsRepository() { + } + + @NonNull + @GuardedBy("ImfLock.class") + static InputMethodSettings get(@UserIdInt int userId) { + final InputMethodSettings obj = sPerUserMap.get(userId); + if (obj != null) { + return obj; + } + return InputMethodSettings.createEmptyMap(userId); + } + + @GuardedBy("ImfLock.class") + static void put(@UserIdInt int userId, @NonNull InputMethodSettings obj) { + sPerUserMap.put(userId, obj); + } + + static void initialize(@NonNull Handler handler, @NonNull Context context) { + final UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + handler.post(() -> { + userManagerInternal.addUserLifecycleListener( + new UserManagerInternal.UserLifecycleListener() { + @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()) { + final InputMethodSettings settings = + InputMethodManagerService.queryInputMethodServicesInternal( + context, + userId, + AdditionalSubtypeMapRepository.get(userId), + DirectBootAwareness.AUTO); + sPerUserMap.put(userId, settings); + } + } + }); + } +} |