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

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

Let SettingsLib not depend on InputMethodSettings

This is part of an effort to remove dependencies on InputMethodUtils
from Settings and other non-core Framework code.

Currently InputMethodSettingValuesWrapper depends on
InputMethodUtils.InputMethodSettings just to parse
Settings.Secure.ENABLED_INPUT_METHODS to extract enabled IMEs from the
result of InputMethodManager#getInputMethodList(), which can be
rewritten with InputMethodAndSubtypeUtil.

Also, seems that the dependency on
InputMethodUtils.InputMethodSettings confused the author and some
unnecessary synchronization blocks were introduced.

This CL completely removes the dependency on InputMethodSettings as
well as unnecessary synchronization blocks because methods of
InputMethodSettingValuesWrapper are expected to be called only from
the UI thread.

There should be no user-visible behavior change.

Bug: 77730201
Test: Manually verified that IME enabler still works as expected.
Change-Id: I0c52fb31ac2bb976dcd867f72992e260aee255b7
parent a47c0396
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ public class InputMethodAndSubtypeUtil {
    }

    // Needs to modify InputMethodManageService if you want to change the format of saved string.
    private static HashMap<String, HashSet<String>> getEnabledInputMethodsAndSubtypeList(
    static HashMap<String, HashSet<String>> getEnabledInputMethodsAndSubtypeList(
            ContentResolver resolver) {
        final String enabledInputMethodsStr = Settings.Secure.getString(
                resolver, Settings.Secure.ENABLED_INPUT_METHODS);
+48 −60
Original line number Diff line number Diff line
@@ -16,17 +16,15 @@

package com.android.settingslib.inputmethod;

import android.app.ActivityManager;
import android.annotation.UiThread;
import android.content.ContentResolver;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;

import com.android.internal.inputmethod.InputMethodUtils;
import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;

import java.util.ArrayList;
import java.util.HashMap;
@@ -35,18 +33,19 @@ import java.util.List;
import java.util.Locale;

/**
 * This class is a wrapper for InputMethodSettings. You need to refresh internal states
 * manually on some events when "InputMethodInfo"s and "InputMethodSubtype"s can be
 * changed.
 * This class is a wrapper for {@link InputMethodManager} and
 * {@link android.provider.Settings.Secure#ENABLED_INPUT_METHODS}. You need to refresh internal
 * states manually on some events when "InputMethodInfo"s and "InputMethodSubtype"s can be changed.
 *
 * <p>TODO: Consolidate this with {@link InputMethodAndSubtypeUtil}.</p>
 */
// TODO: Consolidate this with {@link InputMethodAndSubtypeUtil}.
@UiThread
public class InputMethodSettingValuesWrapper {
    private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();

    private static volatile InputMethodSettingValuesWrapper sInstance;
    private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
    private final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<>();
    private final InputMethodSettings mSettings;
    private final ContentResolver mContentResolver;
    private final InputMethodManager mImm;
    private final HashSet<InputMethodInfo> mAsciiCapableEnabledImis = new HashSet<>();

@@ -61,41 +60,23 @@ public class InputMethodSettingValuesWrapper {
        return sInstance;
    }

    private static int getDefaultCurrentUserId() {
        try {
            return ActivityManager.getService().getCurrentUser().id;
        } catch (RemoteException e) {
            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
        }
        return 0;
    }

    // Ensure singleton
    private InputMethodSettingValuesWrapper(Context context) {
        mSettings = new InputMethodSettings(context.getResources(), context.getContentResolver(),
                mMethodMap, mMethodList, getDefaultCurrentUserId(), false /* copyOnWrite */);
        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        mContentResolver = context.getContentResolver();
        mImm = context.getSystemService(InputMethodManager.class);
        refreshAllInputMethodAndSubtypes();
    }

    public void refreshAllInputMethodAndSubtypes() {
        synchronized (mMethodMap) {
        mMethodList.clear();
            mMethodMap.clear();
            final List<InputMethodInfo> imms = mImm.getInputMethodList();
            mMethodList.addAll(imms);
            for (InputMethodInfo imi : imms) {
                mMethodMap.put(imi.getId(), imi);
            }
        mMethodList.addAll(mImm.getInputMethodList());
        updateAsciiCapableEnabledImis();
    }
    }

    // TODO: Add a cts to ensure at least one AsciiCapableSubtypeEnabledImis exist
    private void updateAsciiCapableEnabledImis() {
        synchronized (mMethodMap) {
        mAsciiCapableEnabledImis.clear();
            final List<InputMethodInfo> enabledImis = mSettings.getEnabledInputMethodListLocked();
        final List<InputMethodInfo> enabledImis = getEnabledInputMethodList();
        for (final InputMethodInfo imi : enabledImis) {
            final int subtypeCount = imi.getSubtypeCount();
            for (int i = 0; i < subtypeCount; ++i) {
@@ -108,21 +89,16 @@ public class InputMethodSettingValuesWrapper {
            }
        }
    }
    }

    public List<InputMethodInfo> getInputMethodList() {
        synchronized (mMethodMap) {
            return mMethodList;
        }
        return new ArrayList<>(mMethodList);
    }

    public boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
        final boolean isEnabled = isEnabledImi(imi);
        synchronized (mMethodMap) {
            if (mSettings.getEnabledInputMethodListLocked().size() <= 1 && isEnabled) {
        if (getEnabledInputMethodList().size() <= 1 && isEnabled) {
            return true;
        }
        }

        final int enabledValidSystemNonAuxAsciiCapableImeCount =
                getEnabledValidSystemNonAuxAsciiCapableImeCount(context);
@@ -131,15 +107,11 @@ public class InputMethodSettingValuesWrapper {
                && !(enabledValidSystemNonAuxAsciiCapableImeCount == 1 && !isEnabled)
                && imi.isSystem()
                && isValidSystemNonAuxAsciiCapableIme(imi, context);

    }

    private int getEnabledValidSystemNonAuxAsciiCapableImeCount(Context context) {
        int count = 0;
        final List<InputMethodInfo> enabledImis;
        synchronized (mMethodMap) {
            enabledImis = mSettings.getEnabledInputMethodListLocked();
        }
        final List<InputMethodInfo> enabledImis = getEnabledInputMethodList();
        for (final InputMethodInfo imi : enabledImis) {
            if (isValidSystemNonAuxAsciiCapableIme(imi, context)) {
                ++count;
@@ -152,10 +124,7 @@ public class InputMethodSettingValuesWrapper {
    }

    public boolean isEnabledImi(InputMethodInfo imi) {
        final List<InputMethodInfo> enabledImis;
        synchronized (mMethodMap) {
            enabledImis = mSettings.getEnabledInputMethodListLocked();
        }
        final List<InputMethodInfo> enabledImis = getEnabledInputMethodList();
        for (final InputMethodInfo tempImi : enabledImis) {
            if (tempImi.getId().equals(imi.getId())) {
                return true;
@@ -182,4 +151,23 @@ public class InputMethodSettingValuesWrapper {
        }
        return mAsciiCapableEnabledImis.contains(imi);
    }

    /**
     * Returns the list of the enabled {@link InputMethodInfo} determined by
     * {@link android.provider.Settings.Secure#ENABLED_INPUT_METHODS} rather than just returning
     * {@link InputMethodManager#getEnabledInputMethodList()}.
     *
     * @return the list of the enabled {@link InputMethodInfo}
     */
    private ArrayList<InputMethodInfo> getEnabledInputMethodList() {
        final HashMap<String, HashSet<String>> enabledInputMethodsAndSubtypes =
                InputMethodAndSubtypeUtil.getEnabledInputMethodsAndSubtypeList(mContentResolver);
        final ArrayList<InputMethodInfo> result = new ArrayList<>();
        for (InputMethodInfo imi : mMethodList) {
            if (enabledInputMethodsAndSubtypes.keySet().contains(imi.getId())) {
                result.add(imi);
            }
        }
        return result;
    }
}