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

Commit af730e95 authored by Felix Stern's avatar Felix Stern Committed by Android (Google) Code Review
Browse files

Merge "Fix loading of large IMEs" into udc-dev

parents f0052f08 eed10082
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 {
+24 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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";

    /**
@@ -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);
+36 −11
Original line number Diff line number Diff line
@@ -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
@@ -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,
@@ -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 */);
@@ -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;
@@ -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);
            }
@@ -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
@@ -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;
    }

@@ -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);

+9 −0
Original line number Diff line number Diff line
@@ -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();
+4 −0
Original line number Diff line number Diff line
@@ -52,6 +52,10 @@ android_test {
        "android.test.runner",
    ],

    data: [
        ":SimpleTestIme",
    ],

    certificate: "platform",
    platform_apis: true,
    test_suites: ["device-tests"],
Loading