From ddad4b93fac5258e29c0f1d2e871b055cae6e6b8 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Thu, 2 Feb 2017 01:46:13 -0800 Subject: [PATCH] Simplify the constructor of InputMethodInfo This is a preparation CL for fixing Bug 32343335, where we aim to avoid unnecessary reconstruction of InputMethodInfo objects by caching immutable part of those metadata by APK revisions. The reason why we have had to pass additional subtypes not just as List but as Map> to create an instance of InputMethodInfo is that how to compute so-called IME ID is not exposed from InputMethodInfo even as @hide method. In practice it has been calculated as new ComponentName(packageName, serviceName).flattenToShortString() and those IDs are already stored here and there including secure settings. It is almost impossible to change the rule anymore hence we should consider them to be a kind of public API. This CL adds a @hide static method InputMethodInfo#computeId() to make it clear. This also enables us to simplify the constructor of InputMethodInfo finally, because we have used IME IDs as keys in subtypes.xml, where additional subtypes are stored. Test: Manually verified that addtional subtypes still work Test: checkbuild Bug: 32343335 Change-Id: I1deaa470e042eac749e7a847933d14448a0d9e03 --- .../view/inputmethod/InputMethodInfo.java | 24 ++++++++++++++----- .../server/InputMethodManagerService.java | 14 +++++------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index b6da1d8c9de3f..71809bdb43936 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -16,6 +16,7 @@ package android.view.inputmethod; +import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -42,7 +43,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * This class is used to specify meta information of an input method. @@ -109,6 +109,19 @@ public final class InputMethodInfo implements Parcelable { */ private final boolean mSupportsDismissingWindow; + /** + * @param service the {@link ResolveInfo} corresponds in which the IME is implemented. + * @return a unique ID to be returned by {@link #getId()}. We have used + * {@link ComponentName#flattenToShortString()} for this purpose (and it is already + * unrealistic to switch to a different scheme as it is already implicitly assumed in + * many places). + * @hide + */ + public static String computeId(@NonNull ResolveInfo service) { + final ServiceInfo si = service.serviceInfo; + return new ComponentName(si.packageName, si.name).flattenToShortString(); + } + /** * Constructor. * @@ -127,15 +140,15 @@ public final class InputMethodInfo implements Parcelable { * @param context The Context in which we are parsing the input method. * @param service The ResolveInfo returned from the package manager about * this input method's component. - * @param additionalSubtypesMap additional subtypes being added to this InputMethodInfo + * @param additionalSubtypes additional subtypes being added to this InputMethodInfo * @hide */ public InputMethodInfo(Context context, ResolveInfo service, - Map> additionalSubtypesMap) + List additionalSubtypes) throws XmlPullParserException, IOException { mService = service; ServiceInfo si = service.serviceInfo; - mId = new ComponentName(si.packageName, si.name).flattenToShortString(); + mId = computeId(service); boolean isAuxIme = true; boolean supportsSwitchingToNextInputMethod = false; // false as default boolean supportsDismissingWindow = false; // false as default @@ -233,8 +246,7 @@ public final class InputMethodInfo implements Parcelable { isAuxIme = false; } - if (additionalSubtypesMap != null && additionalSubtypesMap.containsKey(mId)) { - final List additionalSubtypes = additionalSubtypesMap.get(mId); + if (additionalSubtypes != null) { final int N = additionalSubtypes.size(); for (int i = 0; i < N; ++i) { final InputMethodSubtype subtype = additionalSubtypes.get(i); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 3e711ec05c753..22eca77c3a062 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -3028,22 +3028,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, mSettings.getCurrentUserId()); - final HashMap> additionalSubtypes = + final HashMap> additionalSubtypeMap = mFileManager.getAllAdditionalInputMethodSubtypes(); for (int i = 0; i < services.size(); ++i) { ResolveInfo ri = services.get(i); ServiceInfo si = ri.serviceInfo; - ComponentName compName = new ComponentName(si.packageName, si.name); - if (!android.Manifest.permission.BIND_INPUT_METHOD.equals( - si.permission)) { - Slog.w(TAG, "Skipping input method " + compName + final String imeId = InputMethodInfo.computeId(ri); + if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) { + Slog.w(TAG, "Skipping input method " + imeId + ": it does not require the permission " + android.Manifest.permission.BIND_INPUT_METHOD); continue; } - if (DEBUG) Slog.d(TAG, "Checking " + compName); + if (DEBUG) Slog.d(TAG, "Checking " + imeId); + final List additionalSubtypes = additionalSubtypeMap.get(imeId); try { InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes); mMethodList.add(p); @@ -3054,7 +3054,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.d(TAG, "Found an input method " + p); } } catch (Exception e) { - Slog.wtf(TAG, "Unable to load input method " + compName, e); + Slog.wtf(TAG, "Unable to load input method " + imeId, e); } }