Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddad4b93 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

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<InputMethodSubtype> but as Map<String, List<InputMethodSubtype>>
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
parent 82c8e5c9
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -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<String, List<InputMethodSubtype>> additionalSubtypesMap)
            List<InputMethodSubtype> 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<InputMethodSubtype> 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);
+7 −7
Original line number Diff line number Diff line
@@ -3028,22 +3028,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
                mSettings.getCurrentUserId());

        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
        final HashMap<String, List<InputMethodSubtype>> 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<InputMethodSubtype> 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);
            }
        }