Loading services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java +13 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(() -> { Loading @@ -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); } } }); Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +46 −31 Original line number Diff line number Diff line Loading @@ -869,9 +869,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (!mSystemReady) { return; } mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(), AdditionalSubtypeMapRepository.get(mSettings.getUserId()), 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); Loading Loading @@ -1118,12 +1126,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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, Loading Loading @@ -1281,23 +1292,24 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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); 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 */); } } } @GuardedBy("ImfLock.class") void scheduleSwitchUserTaskLocked(@UserIdInt int userId, Loading Loading @@ -1361,12 +1373,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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, Loading Loading @@ -1529,8 +1542,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. // 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 Loading Loading @@ -1612,9 +1627,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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); Loading Loading @@ -4076,22 +4093,20 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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); Loading services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java 0 → 100644 +86 −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.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); } } }); } } Loading
services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java +13 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(() -> { Loading @@ -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); } } }); Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +46 −31 Original line number Diff line number Diff line Loading @@ -869,9 +869,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (!mSystemReady) { return; } mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(), AdditionalSubtypeMapRepository.get(mSettings.getUserId()), 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); Loading Loading @@ -1118,12 +1126,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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, Loading Loading @@ -1281,23 +1292,24 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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); 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 */); } } } @GuardedBy("ImfLock.class") void scheduleSwitchUserTaskLocked(@UserIdInt int userId, Loading Loading @@ -1361,12 +1373,13 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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, Loading Loading @@ -1529,8 +1542,10 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. // 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 Loading Loading @@ -1612,9 +1627,11 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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); Loading Loading @@ -4076,22 +4093,20 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. 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); Loading
services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java 0 → 100644 +86 −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.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); } } }); } }