Loading core/api/test-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -3547,6 +3547,8 @@ package android.view.inputmethod { public final class InputMethodInfo implements android.os.Parcelable { ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, boolean, @NonNull String); ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int); field public static final int COMPONENT_NAME_MAX_LENGTH = 1000; // 0x3e8 field public static final int MAX_IMES_PER_PACKAGE = 20; // 0x14 } public final class InputMethodManager { Loading core/java/android/view/inputmethod/InputMethodInfo.java +24 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.view.inputmethod; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; Loading Loading @@ -83,6 +84,22 @@ public final class InputMethodInfo implements Parcelable { public static final String ACTION_STYLUS_HANDWRITING_SETTINGS = "android.view.inputmethod.action.STYLUS_HANDWRITING_SETTINGS"; /** * Maximal length of a component name * @hide */ @TestApi public static final int COMPONENT_NAME_MAX_LENGTH = 1000; /** * The maximum amount of IMEs that are loaded per package (in order). * If a package contains more IMEs, they will be ignored and cannot be enabled. * @hide */ @TestApi @SuppressLint("MinMaxConstant") public static final int MAX_IMES_PER_PACKAGE = 20; static final String TAG = "InputMethodInfo"; /** Loading Loading @@ -252,6 +269,13 @@ public final class InputMethodInfo implements Parcelable { com.android.internal.R.styleable.InputMethod); settingsActivityComponent = sa.getString( com.android.internal.R.styleable.InputMethod_settingsActivity); if ((si.name != null && si.name.length() > COMPONENT_NAME_MAX_LENGTH) || ( settingsActivityComponent != null && settingsActivityComponent.length() > COMPONENT_NAME_MAX_LENGTH)) { throw new XmlPullParserException( "Activity name exceeds maximum of 1000 characters"); } isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false); isDefaultResId = sa.getResourceId( com.android.internal.R.styleable.InputMethod_isDefault, 0); Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +36 −11 Original line number Diff line number Diff line Loading @@ -2079,7 +2079,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, directBootAwareness); methodList, directBootAwareness, mSettings.getEnabledInputMethodNames()); settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */); } // filter caller's access to input methods Loading Loading @@ -4136,7 +4136,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, DirectBootAwareness.AUTO); methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId, false); settings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, additionalSubtypeMap, Loading Loading @@ -5033,7 +5033,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub static void queryInputMethodServicesInternal(Context context, @UserIdInt int userId, ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap, ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, @DirectBootAwareness int directBootAwareness) { @DirectBootAwareness int directBootAwareness, List<String> enabledInputMethodList) { final Context userAwareContext = context.getUserId() == userId ? context : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); Loading Loading @@ -5066,6 +5066,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub methodList.ensureCapacity(services.size()); methodMap.ensureCapacity(services.size()); filterInputMethodServices(additionalSubtypeMap, methodMap, methodList, enabledInputMethodList, userAwareContext, services); } static void filterInputMethodServices( ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap, ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, List<String> enabledInputMethodList, Context userAwareContext, List<ResolveInfo> services) { final ArrayMap<String, Integer> imiPackageCount = new ArrayMap<>(); for (int i = 0; i < services.size(); ++i) { ResolveInfo ri = services.get(i); ServiceInfo si = ri.serviceInfo; Loading @@ -5085,11 +5096,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (imi.isVrOnly()) { continue; // Skip VR-only IME, which isn't supported for now. } final String packageName = si.packageName; // only include IMEs which are from the system, enabled, or below the threshold if (si.applicationInfo.isSystemApp() || enabledInputMethodList.contains(imi.getId()) || imiPackageCount.getOrDefault(packageName, 0) < InputMethodInfo.MAX_IMES_PER_PACKAGE) { imiPackageCount.put(packageName, 1 + imiPackageCount.getOrDefault(packageName, 0)); methodList.add(imi); methodMap.put(imi.getId(), imi); if (DEBUG) { Slog.d(TAG, "Found an input method " + imi); } } else if (DEBUG) { Slog.d(TAG, "Found an input method, but ignored due threshold: " + imi); } } catch (Exception e) { Slog.wtf(TAG, "Unable to load input method " + imeId, e); } Loading @@ -5110,7 +5132,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mMyPackageMonitor.clearKnownImePackageNamesLocked(); queryInputMethodServicesInternal(mContext, mSettings.getCurrentUserId(), mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO); mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); // 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 @@ -5469,7 +5492,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, DirectBootAwareness.AUTO); methodMap, methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); return methodMap; } Loading Loading @@ -6429,7 +6453,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, DirectBootAwareness.AUTO); methodMap, methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId, false); Loading services/core/java/com/android/server/inputmethod/InputMethodUtils.java +9 −0 Original line number Diff line number Diff line Loading @@ -438,6 +438,15 @@ final class InputMethodUtils { mSubtypeSplitter); } List<String> getEnabledInputMethodNames() { List<String> result = new ArrayList<>(); for (Pair<String, ArrayList<String>> pair : getEnabledInputMethodsAndSubtypeListLocked()) { result.add(pair.first); } return result; } void appendAndPutEnabledInputMethodLocked(String id, boolean reloadInputMethodStr) { if (reloadInputMethodStr) { getEnabledInputMethodsStr(); Loading services/tests/InputMethodSystemServerTests/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,10 @@ android_test { "android.test.runner", ], data: [ ":SimpleTestIme", ], certificate: "platform", platform_apis: true, test_suites: ["device-tests"], Loading Loading
core/api/test-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -3547,6 +3547,8 @@ package android.view.inputmethod { public final class InputMethodInfo implements android.os.Parcelable { ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, boolean, @NonNull String); ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int); field public static final int COMPONENT_NAME_MAX_LENGTH = 1000; // 0x3e8 field public static final int MAX_IMES_PER_PACKAGE = 20; // 0x14 } public final class InputMethodManager { Loading
core/java/android/view/inputmethod/InputMethodInfo.java +24 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.view.inputmethod; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; Loading Loading @@ -83,6 +84,22 @@ public final class InputMethodInfo implements Parcelable { public static final String ACTION_STYLUS_HANDWRITING_SETTINGS = "android.view.inputmethod.action.STYLUS_HANDWRITING_SETTINGS"; /** * Maximal length of a component name * @hide */ @TestApi public static final int COMPONENT_NAME_MAX_LENGTH = 1000; /** * The maximum amount of IMEs that are loaded per package (in order). * If a package contains more IMEs, they will be ignored and cannot be enabled. * @hide */ @TestApi @SuppressLint("MinMaxConstant") public static final int MAX_IMES_PER_PACKAGE = 20; static final String TAG = "InputMethodInfo"; /** Loading Loading @@ -252,6 +269,13 @@ public final class InputMethodInfo implements Parcelable { com.android.internal.R.styleable.InputMethod); settingsActivityComponent = sa.getString( com.android.internal.R.styleable.InputMethod_settingsActivity); if ((si.name != null && si.name.length() > COMPONENT_NAME_MAX_LENGTH) || ( settingsActivityComponent != null && settingsActivityComponent.length() > COMPONENT_NAME_MAX_LENGTH)) { throw new XmlPullParserException( "Activity name exceeds maximum of 1000 characters"); } isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false); isDefaultResId = sa.getResourceId( com.android.internal.R.styleable.InputMethod_isDefault, 0); Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +36 −11 Original line number Diff line number Diff line Loading @@ -2079,7 +2079,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, directBootAwareness); methodList, directBootAwareness, mSettings.getEnabledInputMethodNames()); settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */); } // filter caller's access to input methods Loading Loading @@ -4136,7 +4136,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, DirectBootAwareness.AUTO); methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId, false); settings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, additionalSubtypeMap, Loading Loading @@ -5033,7 +5033,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub static void queryInputMethodServicesInternal(Context context, @UserIdInt int userId, ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap, ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, @DirectBootAwareness int directBootAwareness) { @DirectBootAwareness int directBootAwareness, List<String> enabledInputMethodList) { final Context userAwareContext = context.getUserId() == userId ? context : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); Loading Loading @@ -5066,6 +5066,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub methodList.ensureCapacity(services.size()); methodMap.ensureCapacity(services.size()); filterInputMethodServices(additionalSubtypeMap, methodMap, methodList, enabledInputMethodList, userAwareContext, services); } static void filterInputMethodServices( ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap, ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, List<String> enabledInputMethodList, Context userAwareContext, List<ResolveInfo> services) { final ArrayMap<String, Integer> imiPackageCount = new ArrayMap<>(); for (int i = 0; i < services.size(); ++i) { ResolveInfo ri = services.get(i); ServiceInfo si = ri.serviceInfo; Loading @@ -5085,11 +5096,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (imi.isVrOnly()) { continue; // Skip VR-only IME, which isn't supported for now. } final String packageName = si.packageName; // only include IMEs which are from the system, enabled, or below the threshold if (si.applicationInfo.isSystemApp() || enabledInputMethodList.contains(imi.getId()) || imiPackageCount.getOrDefault(packageName, 0) < InputMethodInfo.MAX_IMES_PER_PACKAGE) { imiPackageCount.put(packageName, 1 + imiPackageCount.getOrDefault(packageName, 0)); methodList.add(imi); methodMap.put(imi.getId(), imi); if (DEBUG) { Slog.d(TAG, "Found an input method " + imi); } } else if (DEBUG) { Slog.d(TAG, "Found an input method, but ignored due threshold: " + imi); } } catch (Exception e) { Slog.wtf(TAG, "Unable to load input method " + imeId, e); } Loading @@ -5110,7 +5132,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mMyPackageMonitor.clearKnownImePackageNamesLocked(); queryInputMethodServicesInternal(mContext, mSettings.getCurrentUserId(), mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO); mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); // 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 @@ -5469,7 +5492,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, DirectBootAwareness.AUTO); methodMap, methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); return methodMap; } Loading Loading @@ -6429,7 +6453,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, methodList, DirectBootAwareness.AUTO); methodMap, methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames()); final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId, false); Loading
services/core/java/com/android/server/inputmethod/InputMethodUtils.java +9 −0 Original line number Diff line number Diff line Loading @@ -438,6 +438,15 @@ final class InputMethodUtils { mSubtypeSplitter); } List<String> getEnabledInputMethodNames() { List<String> result = new ArrayList<>(); for (Pair<String, ArrayList<String>> pair : getEnabledInputMethodsAndSubtypeListLocked()) { result.add(pair.first); } return result; } void appendAndPutEnabledInputMethodLocked(String id, boolean reloadInputMethodStr) { if (reloadInputMethodStr) { getEnabledInputMethodsStr(); Loading
services/tests/InputMethodSystemServerTests/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,10 @@ android_test { "android.test.runner", ], data: [ ":SimpleTestIme", ], certificate: "platform", platform_apis: true, test_suites: ["device-tests"], Loading