Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +7 −136 Original line number Diff line number Diff line Loading @@ -861,37 +861,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } final class MyPackageMonitor extends PackageMonitor { /** * Package names that are known to contain {@link InputMethodService}. * * <p>No need to include packages because of direct-boot unaware IMEs since we always rescan * all the packages when the user is unlocked, and direct-boot awareness will not be changed * dynamically unless the entire package is updated, which also always triggers package * rescanning.</p> */ @GuardedBy("ImfLock.class") private final ArraySet<String> mKnownImePackageNames = new ArraySet<>(); /** * Packages that are appeared, disappeared, or modified for whatever reason. * * <p>Note: For now we intentionally use {@link ArrayList} instead of {@link ArraySet} * because 1) the number of elements is almost always 1 or so, and 2) we do not care * duplicate elements for our use case.</p> * * <p>This object must be accessed only from callback methods in {@link PackageMonitor}, * which should be bound to {@link #getRegisteredHandler()}.</p> */ private final ArrayList<String> mChangedPackages = new ArrayList<>(); /** * {@code true} if one or more packages that contain {@link InputMethodService} appeared. * * <p>This field must be accessed only from callback methods in {@link PackageMonitor}, * which should be bound to {@link #getRegisteredHandler()}.</p> */ private boolean mImePackageAppeared = false; /** * Remembers package names passed to {@link #onPackageDataCleared(String, int)}. * Loading @@ -904,16 +873,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. super(true); } @GuardedBy("ImfLock.class") void clearKnownImePackageNamesLocked() { mKnownImePackageNames.clear(); } @GuardedBy("ImfLock.class") void addKnownImePackageNameLocked(@NonNull String packageName) { mKnownImePackageNames.add(packageName); } @GuardedBy("ImfLock.class") private boolean isChangingPackagesOfCurrentUserLocked() { final int userId = getChangingUserId(); Loading Loading @@ -963,53 +922,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. clearPackageChangeState(); } @Override public void onPackageAppeared(String packageName, int reason) { if (!mImePackageAppeared) { final PackageManager pm = mContext.getPackageManager(); final List<ResolveInfo> services = pm.queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE).setPackage(packageName), PackageManager.MATCH_DISABLED_COMPONENTS, getChangingUserId()); // No need to lock this because we access it only on getRegisteredHandler(). if (!services.isEmpty()) { mImePackageAppeared = true; } } // No need to lock this because we access it only on getRegisteredHandler(). mChangedPackages.add(packageName); } @Override public void onPackageDisappeared(String packageName, int reason) { // No need to lock this because we access it only on getRegisteredHandler(). mChangedPackages.add(packageName); } @Override public void onPackageModified(String packageName) { // No need to lock this because we access it only on getRegisteredHandler(). mChangedPackages.add(packageName); } @Override public void onPackagesSuspended(String[] packages) { // No need to lock this because we access it only on getRegisteredHandler(). for (String packageName : packages) { mChangedPackages.add(packageName); } } @Override public void onPackagesUnsuspended(String[] packages) { // No need to lock this because we access it only on getRegisteredHandler(). for (String packageName : packages) { mChangedPackages.add(packageName); } } @Override public void onPackageDataCleared(String packageName, int uid) { mChangedPackages.add(packageName); mDataClearedPackages.add(packageName); } Loading @@ -1021,32 +935,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. private void clearPackageChangeState() { // No need to lock them because we access these fields only on getRegisteredHandler(). mChangedPackages.clear(); mDataClearedPackages.clear(); mImePackageAppeared = false; } @GuardedBy("ImfLock.class") private boolean shouldRebuildInputMethodListLocked() { // This method is guaranteed to be called only by getRegisteredHandler(). // If there is any new package that contains at least one IME, then rebuilt the list // of IMEs. if (mImePackageAppeared) { return true; } // Otherwise, check if mKnownImePackageNames and mChangedPackages have any intersection. // TODO: Consider to create a utility method to do the following test. List.retainAll() // is an option, but it may still do some extra operations that we do not need here. final int numPackages = mChangedPackages.size(); for (int i = 0; i < numPackages; ++i) { final String packageName = mChangedPackages.get(i); if (mKnownImePackageNames.contains(packageName)) { return true; } } return false; } private void onFinishPackageChangesInternal() { Loading Loading @@ -1107,12 +996,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap, settings.getMethodMap()); } if (isCurrentUser && !(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) { return; } final var newMethodMap = newMethodMapWithoutAdditionalSubtypes .applyAdditionalSubtypes(newAdditionalSubtypeMap); if (InputMethodMap.areSame(settings.getMethodMap(), newMethodMap)) { // No update in the actual IME map. return; } final InputMethodSettings newSettings = InputMethodSettings.create(newMethodMap, userId); InputMethodSettingsRepository.put(userId, newSettings); Loading Loading @@ -5128,30 +5020,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. return; } mMethodMapUpdateCount++; mMyPackageMonitor.clearKnownImePackageNamesLocked(); final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId); // 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 // changed. { // Here we intentionally use PackageManager.MATCH_DISABLED_COMPONENTS since the purpose // of this query is to avoid false negatives. PackageManager.MATCH_ALL could be more // conservative, but it seems we cannot use it for now (Issue 35176630). final List<ResolveInfo> allInputMethodServices = mContext.getPackageManager().queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE), PackageManager.MATCH_DISABLED_COMPONENTS, settings.getUserId()); final int numImes = allInputMethodServices.size(); for (int i = 0; i < numImes; ++i) { final ServiceInfo si = allInputMethodServices.get(i).serviceInfo; if (android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) { mMyPackageMonitor.addKnownImePackageNameLocked(si.packageName); } } } boolean reenableMinimumNonAuxSystemImes = false; // TODO: The following code should find better place to live. if (!resetDefaultEnabledIme) { Loading Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +7 −136 Original line number Diff line number Diff line Loading @@ -861,37 +861,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } final class MyPackageMonitor extends PackageMonitor { /** * Package names that are known to contain {@link InputMethodService}. * * <p>No need to include packages because of direct-boot unaware IMEs since we always rescan * all the packages when the user is unlocked, and direct-boot awareness will not be changed * dynamically unless the entire package is updated, which also always triggers package * rescanning.</p> */ @GuardedBy("ImfLock.class") private final ArraySet<String> mKnownImePackageNames = new ArraySet<>(); /** * Packages that are appeared, disappeared, or modified for whatever reason. * * <p>Note: For now we intentionally use {@link ArrayList} instead of {@link ArraySet} * because 1) the number of elements is almost always 1 or so, and 2) we do not care * duplicate elements for our use case.</p> * * <p>This object must be accessed only from callback methods in {@link PackageMonitor}, * which should be bound to {@link #getRegisteredHandler()}.</p> */ private final ArrayList<String> mChangedPackages = new ArrayList<>(); /** * {@code true} if one or more packages that contain {@link InputMethodService} appeared. * * <p>This field must be accessed only from callback methods in {@link PackageMonitor}, * which should be bound to {@link #getRegisteredHandler()}.</p> */ private boolean mImePackageAppeared = false; /** * Remembers package names passed to {@link #onPackageDataCleared(String, int)}. * Loading @@ -904,16 +873,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. super(true); } @GuardedBy("ImfLock.class") void clearKnownImePackageNamesLocked() { mKnownImePackageNames.clear(); } @GuardedBy("ImfLock.class") void addKnownImePackageNameLocked(@NonNull String packageName) { mKnownImePackageNames.add(packageName); } @GuardedBy("ImfLock.class") private boolean isChangingPackagesOfCurrentUserLocked() { final int userId = getChangingUserId(); Loading Loading @@ -963,53 +922,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. clearPackageChangeState(); } @Override public void onPackageAppeared(String packageName, int reason) { if (!mImePackageAppeared) { final PackageManager pm = mContext.getPackageManager(); final List<ResolveInfo> services = pm.queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE).setPackage(packageName), PackageManager.MATCH_DISABLED_COMPONENTS, getChangingUserId()); // No need to lock this because we access it only on getRegisteredHandler(). if (!services.isEmpty()) { mImePackageAppeared = true; } } // No need to lock this because we access it only on getRegisteredHandler(). mChangedPackages.add(packageName); } @Override public void onPackageDisappeared(String packageName, int reason) { // No need to lock this because we access it only on getRegisteredHandler(). mChangedPackages.add(packageName); } @Override public void onPackageModified(String packageName) { // No need to lock this because we access it only on getRegisteredHandler(). mChangedPackages.add(packageName); } @Override public void onPackagesSuspended(String[] packages) { // No need to lock this because we access it only on getRegisteredHandler(). for (String packageName : packages) { mChangedPackages.add(packageName); } } @Override public void onPackagesUnsuspended(String[] packages) { // No need to lock this because we access it only on getRegisteredHandler(). for (String packageName : packages) { mChangedPackages.add(packageName); } } @Override public void onPackageDataCleared(String packageName, int uid) { mChangedPackages.add(packageName); mDataClearedPackages.add(packageName); } Loading @@ -1021,32 +935,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. private void clearPackageChangeState() { // No need to lock them because we access these fields only on getRegisteredHandler(). mChangedPackages.clear(); mDataClearedPackages.clear(); mImePackageAppeared = false; } @GuardedBy("ImfLock.class") private boolean shouldRebuildInputMethodListLocked() { // This method is guaranteed to be called only by getRegisteredHandler(). // If there is any new package that contains at least one IME, then rebuilt the list // of IMEs. if (mImePackageAppeared) { return true; } // Otherwise, check if mKnownImePackageNames and mChangedPackages have any intersection. // TODO: Consider to create a utility method to do the following test. List.retainAll() // is an option, but it may still do some extra operations that we do not need here. final int numPackages = mChangedPackages.size(); for (int i = 0; i < numPackages; ++i) { final String packageName = mChangedPackages.get(i); if (mKnownImePackageNames.contains(packageName)) { return true; } } return false; } private void onFinishPackageChangesInternal() { Loading Loading @@ -1107,12 +996,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap, settings.getMethodMap()); } if (isCurrentUser && !(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) { return; } final var newMethodMap = newMethodMapWithoutAdditionalSubtypes .applyAdditionalSubtypes(newAdditionalSubtypeMap); if (InputMethodMap.areSame(settings.getMethodMap(), newMethodMap)) { // No update in the actual IME map. return; } final InputMethodSettings newSettings = InputMethodSettings.create(newMethodMap, userId); InputMethodSettingsRepository.put(userId, newSettings); Loading Loading @@ -5128,30 +5020,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. return; } mMethodMapUpdateCount++; mMyPackageMonitor.clearKnownImePackageNamesLocked(); final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId); // 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 // changed. { // Here we intentionally use PackageManager.MATCH_DISABLED_COMPONENTS since the purpose // of this query is to avoid false negatives. PackageManager.MATCH_ALL could be more // conservative, but it seems we cannot use it for now (Issue 35176630). final List<ResolveInfo> allInputMethodServices = mContext.getPackageManager().queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE), PackageManager.MATCH_DISABLED_COMPONENTS, settings.getUserId()); final int numImes = allInputMethodServices.size(); for (int i = 0; i < numImes; ++i) { final ServiceInfo si = allInputMethodServices.get(i).serviceInfo; if (android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) { mMyPackageMonitor.addKnownImePackageNameLocked(si.packageName); } } } boolean reenableMinimumNonAuxSystemImes = false; // TODO: The following code should find better place to live. if (!resetDefaultEnabledIme) { Loading