diff --git a/res/values/strings.xml b/res/values/strings.xml
index c9ac0783ff0..46981b6f10e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3894,12 +3894,6 @@
Settings
Settings
-
- Active input methods
-
- Use system languages
%1$s settings
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index b9c07962587..a6df7a30dee 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -42,6 +42,8 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
import java.text.Collator;
import java.util.ArrayList;
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
index a47daa15ca5..5fcaccfbd82 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
@@ -16,42 +16,17 @@
package com.android.settings.inputmethod;
-import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
import android.os.Bundle;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.TwoStatePreference;
import android.text.TextUtils;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeEnablerManager;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-
-public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment
- implements OnPreferenceChangeListener {
- private boolean mHaveHardKeyboard;
- private final HashMap> mInputMethodAndSubtypePrefsMap =
- new HashMap<>();
- private final HashMap mAutoSelectionPrefsMap = new HashMap<>();
- private InputMethodManager mImm;
- // TODO: Change mInputMethodInfoList to Map
- private List mInputMethodInfoList;
- private Collator mCollator;
+public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
+ private InputMethodAndSubtypeEnablerManager mManager;
@Override
public int getMetricsCategory() {
@@ -61,9 +36,6 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment
@Override
public void onCreate(final Bundle icicle) {
super.onCreate(icicle);
- mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- final Configuration config = getResources().getConfiguration();
- mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
// Input method id should be available from an Intent when this preference is launched as a
// single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available
@@ -72,18 +44,10 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment
final String targetImi = getStringExtraFromIntentOrArguments(
android.provider.Settings.EXTRA_INPUT_METHOD_ID);
- mInputMethodInfoList = mImm.getInputMethodList();
- mCollator = Collator.getInstance();
-
- final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
- final int imiCount = mInputMethodInfoList.size();
- for (int index = 0; index < imiCount; ++index) {
- final InputMethodInfo imi = mInputMethodInfoList.get(index);
- // Add subtype preferences of this IME when it is specified or no IME is specified.
- if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) {
- addInputMethodSubtypePreferences(imi, root);
- }
- }
+ final PreferenceScreen root =
+ getPreferenceManager().createPreferenceScreen(getPrefContext());
+ mManager = new InputMethodAndSubtypeEnablerManager(this);
+ mManager.init(this, targetImi, root);
setPreferenceScreen(root);
}
@@ -109,202 +73,12 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment
@Override
public void onResume() {
super.onResume();
- // Refresh internal states in mInputMethodSettingValues to keep the latest
- // "InputMethodInfo"s and "InputMethodSubtype"s
- InputMethodSettingValuesWrapper
- .getInstance(getActivity()).refreshAllInputMethodAndSubtypes();
- InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
- this, getContentResolver(), mInputMethodInfoList, mInputMethodAndSubtypePrefsMap);
- updateAutoSelectionPreferences();
+ mManager.refresh(getContext(), this);
}
@Override
public void onPause() {
super.onPause();
- InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
- mInputMethodInfoList, mHaveHardKeyboard);
- }
-
- @Override
- public boolean onPreferenceChange(final Preference pref, final Object newValue) {
- if (!(newValue instanceof Boolean)) {
- return true; // Invoke default behavior.
- }
- final boolean isChecking = (Boolean) newValue;
- for (final String imiId : mAutoSelectionPrefsMap.keySet()) {
- // An auto select subtype preference is changing.
- if (mAutoSelectionPrefsMap.get(imiId) == pref) {
- final TwoStatePreference autoSelectionPref = (TwoStatePreference) pref;
- autoSelectionPref.setChecked(isChecking);
- // Enable or disable subtypes depending on the auto selection preference.
- setAutoSelectionSubtypesEnabled(imiId, autoSelectionPref.isChecked());
- return false;
- }
- }
- // A subtype preference is changing.
- if (pref instanceof InputMethodSubtypePreference) {
- final InputMethodSubtypePreference subtypePref = (InputMethodSubtypePreference) pref;
- subtypePref.setChecked(isChecking);
- if (!subtypePref.isChecked()) {
- // It takes care of the case where no subtypes are explicitly enabled then the auto
- // selection preference is going to be checked.
- updateAutoSelectionPreferences();
- }
- return false;
- }
- return true; // Invoke default behavior.
- }
-
- private void addInputMethodSubtypePreferences(final InputMethodInfo imi,
- final PreferenceScreen root) {
- final Context context = getPrefContext();
- final int subtypeCount = imi.getSubtypeCount();
- if (subtypeCount <= 1) {
- return;
- }
- final String imiId = imi.getId();
- final PreferenceCategory keyboardSettingsCategory =
- new PreferenceCategory(getPrefContext());
- root.addPreference(keyboardSettingsCategory);
- final PackageManager pm = getPackageManager();
- final CharSequence label = imi.loadLabel(pm);
-
- keyboardSettingsCategory.setTitle(label);
- keyboardSettingsCategory.setKey(imiId);
- // TODO: Use toggle Preference if images are ready.
- final TwoStatePreference autoSelectionPref =
- new SwitchWithNoTextPreference(getPrefContext());
- mAutoSelectionPrefsMap.put(imiId, autoSelectionPref);
- keyboardSettingsCategory.addPreference(autoSelectionPref);
- autoSelectionPref.setOnPreferenceChangeListener(this);
-
- final PreferenceCategory activeInputMethodsCategory =
- new PreferenceCategory(getPrefContext());
- activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
- root.addPreference(activeInputMethodsCategory);
-
- CharSequence autoSubtypeLabel = null;
- final ArrayList subtypePreferences = new ArrayList<>();
- for (int index = 0; index < subtypeCount; ++index) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(index);
- if (subtype.overridesImplicitlyEnabledSubtype()) {
- if (autoSubtypeLabel == null) {
- autoSubtypeLabel = InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
- subtype, context, imi);
- }
- } else {
- final Preference subtypePref = new InputMethodSubtypePreference(
- context, subtype, imi);
- subtypePreferences.add(subtypePref);
- }
- }
- Collections.sort(subtypePreferences, new Comparator() {
- @Override
- public int compare(final Preference lhs, final Preference rhs) {
- if (lhs instanceof InputMethodSubtypePreference) {
- return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator);
- }
- return lhs.compareTo(rhs);
- }
- });
- final int prefCount = subtypePreferences.size();
- for (int index = 0; index < prefCount; ++index) {
- final Preference pref = subtypePreferences.get(index);
- activeInputMethodsCategory.addPreference(pref);
- pref.setOnPreferenceChangeListener(this);
- InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
- }
- mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
- if (TextUtils.isEmpty(autoSubtypeLabel)) {
- autoSelectionPref.setTitle(
- R.string.use_system_language_to_select_input_method_subtypes);
- } else {
- autoSelectionPref.setTitle(autoSubtypeLabel);
- }
- }
-
- private boolean isNoSubtypesExplicitlySelected(final String imiId) {
- final List subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
- for (final Preference pref : subtypePrefs) {
- if (pref instanceof TwoStatePreference && ((TwoStatePreference)pref).isChecked()) {
- return false;
- }
- }
- return true;
- }
-
- private void setAutoSelectionSubtypesEnabled(final String imiId,
- final boolean autoSelectionEnabled) {
- final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
- if (autoSelectionPref == null) {
- return;
- }
- autoSelectionPref.setChecked(autoSelectionEnabled);
- final List subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
- for (final Preference pref : subtypePrefs) {
- if (pref instanceof TwoStatePreference) {
- // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
- // implicitly checked subtypes. In case of false, all subtype prefs need to be
- // enabled.
- pref.setEnabled(!autoSelectionEnabled);
- if (autoSelectionEnabled) {
- ((TwoStatePreference)pref).setChecked(false);
- }
- }
- }
- if (autoSelectionEnabled) {
- InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
- this, getContentResolver(), mInputMethodInfoList, mHaveHardKeyboard);
- updateImplicitlyEnabledSubtypes(imiId, true /* check */);
- }
- }
-
- private void updateImplicitlyEnabledSubtypes(final String targetImiId, final boolean check) {
- // When targetImiId is null, apply to all subtypes of all IMEs
- for (final InputMethodInfo imi : mInputMethodInfoList) {
- final String imiId = imi.getId();
- final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
- // No need to update implicitly enabled subtypes when the user has unchecked the
- // "subtype auto selection".
- if (autoSelectionPref == null || !autoSelectionPref.isChecked()) {
- continue;
- }
- if (imiId.equals(targetImiId) || targetImiId == null) {
- updateImplicitlyEnabledSubtypesOf(imi, check);
- }
- }
- }
-
- private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi, final boolean check) {
- final String imiId = imi.getId();
- final List subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
- final List implicitlyEnabledSubtypes =
- mImm.getEnabledInputMethodSubtypeList(imi, true);
- if (subtypePrefs == null || implicitlyEnabledSubtypes == null) {
- return;
- }
- for (final Preference pref : subtypePrefs) {
- if (!(pref instanceof TwoStatePreference)) {
- continue;
- }
- final TwoStatePreference subtypePref = (TwoStatePreference)pref;
- subtypePref.setChecked(false);
- if (check) {
- for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) {
- final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
- if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
- subtypePref.setChecked(true);
- break;
- }
- }
- }
- }
- }
-
- private void updateAutoSelectionPreferences() {
- for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) {
- setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
- }
- updateImplicitlyEnabledSubtypes(null /* targetImiId */, true /* check */);
+ mManager.save(getContext(), this);
}
}
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java
deleted file mode 100644
index 3d8d5730642..00000000000
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.inputmethod;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.icu.text.ListFormatter;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.TwoStatePreference;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.internal.app.LocaleHelper;
-import com.android.internal.inputmethod.InputMethodUtils;
-import com.android.settings.SettingsPreferenceFragment;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-// TODO: Consolidate this with {@link InputMethodSettingValuesWrapper}.
-class InputMethodAndSubtypeUtil {
-
- private static final boolean DEBUG = false;
- static final String TAG = "InputMethdAndSubtypeUtil";
-
- private static final char INPUT_METHOD_SEPARATER = ':';
- private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
- private static final int NOT_A_SUBTYPE_ID = -1;
-
- private static final TextUtils.SimpleStringSplitter sStringInputMethodSplitter
- = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);
-
- private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter
- = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
-
- // InputMethods and subtypes are saved in the settings as follows:
- // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1
- static String buildInputMethodsAndSubtypesString(
- final HashMap> imeToSubtypesMap) {
- final StringBuilder builder = new StringBuilder();
- for (final String imi : imeToSubtypesMap.keySet()) {
- if (builder.length() > 0) {
- builder.append(INPUT_METHOD_SEPARATER);
- }
- final HashSet subtypeIdSet = imeToSubtypesMap.get(imi);
- builder.append(imi);
- for (final String subtypeId : subtypeIdSet) {
- builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypeId);
- }
- }
- return builder.toString();
- }
-
- private static String buildInputMethodsString(final HashSet imiList) {
- final StringBuilder builder = new StringBuilder();
- for (final String imi : imiList) {
- if (builder.length() > 0) {
- builder.append(INPUT_METHOD_SEPARATER);
- }
- builder.append(imi);
- }
- return builder.toString();
- }
-
- private static int getInputMethodSubtypeSelected(ContentResolver resolver) {
- try {
- return Settings.Secure.getInt(resolver,
- Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
- } catch (SettingNotFoundException e) {
- return NOT_A_SUBTYPE_ID;
- }
- }
-
- private static boolean isInputMethodSubtypeSelected(ContentResolver resolver) {
- return getInputMethodSubtypeSelected(resolver) != NOT_A_SUBTYPE_ID;
- }
-
- private static void putSelectedInputMethodSubtype(ContentResolver resolver, int hashCode) {
- Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, hashCode);
- }
-
- // Needs to modify InputMethodManageService if you want to change the format of saved string.
- private static HashMap> getEnabledInputMethodsAndSubtypeList(
- ContentResolver resolver) {
- final String enabledInputMethodsStr = Settings.Secure.getString(
- resolver, Settings.Secure.ENABLED_INPUT_METHODS);
- if (DEBUG) {
- Log.d(TAG, "--- Load enabled input methods: " + enabledInputMethodsStr);
- }
- return parseInputMethodsAndSubtypesString(enabledInputMethodsStr);
- }
-
- static HashMap> parseInputMethodsAndSubtypesString(
- final String inputMethodsAndSubtypesString) {
- final HashMap> subtypesMap = new HashMap<>();
- if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
- return subtypesMap;
- }
- sStringInputMethodSplitter.setString(inputMethodsAndSubtypesString);
- while (sStringInputMethodSplitter.hasNext()) {
- final String nextImsStr = sStringInputMethodSplitter.next();
- sStringInputMethodSubtypeSplitter.setString(nextImsStr);
- if (sStringInputMethodSubtypeSplitter.hasNext()) {
- final HashSet subtypeIdSet = new HashSet<>();
- // The first element is {@link InputMethodInfoId}.
- final String imiId = sStringInputMethodSubtypeSplitter.next();
- while (sStringInputMethodSubtypeSplitter.hasNext()) {
- subtypeIdSet.add(sStringInputMethodSubtypeSplitter.next());
- }
- subtypesMap.put(imiId, subtypeIdSet);
- }
- }
- return subtypesMap;
- }
-
- static void enableInputMethodSubtypesOf(final ContentResolver resolver, final String imiId,
- final HashSet enabledSubtypeIdSet) {
- final HashMap> enabledImeAndSubtypeIdsMap =
- getEnabledInputMethodsAndSubtypeList(resolver);
- enabledImeAndSubtypeIdsMap.put(imiId, enabledSubtypeIdSet);
- final String enabledImesAndSubtypesString = buildInputMethodsAndSubtypesString(
- enabledImeAndSubtypeIdsMap);
- Settings.Secure.putString(resolver,
- Settings.Secure.ENABLED_INPUT_METHODS, enabledImesAndSubtypesString);
- }
-
- private static HashSet getDisabledSystemIMEs(ContentResolver resolver) {
- HashSet set = new HashSet<>();
- String disabledIMEsStr = Settings.Secure.getString(
- resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS);
- if (TextUtils.isEmpty(disabledIMEsStr)) {
- return set;
- }
- sStringInputMethodSplitter.setString(disabledIMEsStr);
- while(sStringInputMethodSplitter.hasNext()) {
- set.add(sStringInputMethodSplitter.next());
- }
- return set;
- }
-
- static void saveInputMethodSubtypeList(SettingsPreferenceFragment context,
- ContentResolver resolver, List inputMethodInfos,
- boolean hasHardKeyboard) {
- String currentInputMethodId = Settings.Secure.getString(resolver,
- Settings.Secure.DEFAULT_INPUT_METHOD);
- final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver);
- final HashMap> enabledIMEsAndSubtypesMap =
- getEnabledInputMethodsAndSubtypeList(resolver);
- final HashSet disabledSystemIMEs = getDisabledSystemIMEs(resolver);
-
- boolean needsToResetSelectedSubtype = false;
- for (final InputMethodInfo imi : inputMethodInfos) {
- final String imiId = imi.getId();
- final Preference pref = context.findPreference(imiId);
- if (pref == null) {
- continue;
- }
- // In the choose input method screen or in the subtype enabler screen,
- // pref
is an instance of TwoStatePreference.
- final boolean isImeChecked = (pref instanceof TwoStatePreference) ?
- ((TwoStatePreference) pref).isChecked()
- : enabledIMEsAndSubtypesMap.containsKey(imiId);
- final boolean isCurrentInputMethod = imiId.equals(currentInputMethodId);
- final boolean systemIme = InputMethodUtils.isSystemIme(imi);
- if ((!hasHardKeyboard && InputMethodSettingValuesWrapper.getInstance(
- context.getActivity()).isAlwaysCheckedIme(imi, context.getActivity()))
- || isImeChecked) {
- if (!enabledIMEsAndSubtypesMap.containsKey(imiId)) {
- // imiId has just been enabled
- enabledIMEsAndSubtypesMap.put(imiId, new HashSet());
- }
- final HashSet subtypesSet = enabledIMEsAndSubtypesMap.get(imiId);
-
- boolean subtypePrefFound = false;
- final int subtypeCount = imi.getSubtypeCount();
- for (int i = 0; i < subtypeCount; ++i) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(i);
- final String subtypeHashCodeStr = String.valueOf(subtype.hashCode());
- final TwoStatePreference subtypePref = (TwoStatePreference) context
- .findPreference(imiId + subtypeHashCodeStr);
- // In the Configure input method screen which does not have subtype preferences.
- if (subtypePref == null) {
- continue;
- }
- if (!subtypePrefFound) {
- // Once subtype preference is found, subtypeSet needs to be cleared.
- // Because of system change, hashCode value could have been changed.
- subtypesSet.clear();
- // If selected subtype preference is disabled, needs to reset.
- needsToResetSelectedSubtype = true;
- subtypePrefFound = true;
- }
- // Checking subtypePref.isEnabled()
is insufficient to determine
- // whether the user manually enabled this subtype or not. Implicitly-enabled
- // subtypes are also checked just as an indicator to users. We also need to
- // check subtypePref.isEnabled()
so that only manually enabled
- // subtypes can be saved here.
- if (subtypePref.isEnabled() && subtypePref.isChecked()) {
- subtypesSet.add(subtypeHashCodeStr);
- if (isCurrentInputMethod) {
- if (selectedInputMethodSubtype == subtype.hashCode()) {
- // Selected subtype is still enabled, there is no need to reset
- // selected subtype.
- needsToResetSelectedSubtype = false;
- }
- }
- } else {
- subtypesSet.remove(subtypeHashCodeStr);
- }
- }
- } else {
- enabledIMEsAndSubtypesMap.remove(imiId);
- if (isCurrentInputMethod) {
- // We are processing the current input method, but found that it's not enabled.
- // This means that the current input method has been uninstalled.
- // If currentInputMethod is already uninstalled, InputMethodManagerService will
- // find the applicable IME from the history and the system locale.
- if (DEBUG) {
- Log.d(TAG, "Current IME was uninstalled or disabled.");
- }
- currentInputMethodId = null;
- }
- }
- // If it's a disabled system ime, add it to the disabled list so that it
- // doesn't get enabled automatically on any changes to the package list
- if (systemIme && hasHardKeyboard) {
- if (disabledSystemIMEs.contains(imiId)) {
- if (isImeChecked) {
- disabledSystemIMEs.remove(imiId);
- }
- } else {
- if (!isImeChecked) {
- disabledSystemIMEs.add(imiId);
- }
- }
- }
- }
-
- final String enabledIMEsAndSubtypesString = buildInputMethodsAndSubtypesString(
- enabledIMEsAndSubtypesMap);
- final String disabledSystemIMEsString = buildInputMethodsString(disabledSystemIMEs);
- if (DEBUG) {
- Log.d(TAG, "--- Save enabled inputmethod settings. :" + enabledIMEsAndSubtypesString);
- Log.d(TAG, "--- Save disabled system inputmethod settings. :"
- + disabledSystemIMEsString);
- Log.d(TAG, "--- Save default inputmethod settings. :" + currentInputMethodId);
- Log.d(TAG, "--- Needs to reset the selected subtype :" + needsToResetSelectedSubtype);
- Log.d(TAG, "--- Subtype is selected :" + isInputMethodSubtypeSelected(resolver));
- }
-
- // Redefines SelectedSubtype when all subtypes are unchecked or there is no subtype
- // selected. And if the selected subtype of the current input method was disabled,
- // We should reset the selected input method's subtype.
- if (needsToResetSelectedSubtype || !isInputMethodSubtypeSelected(resolver)) {
- if (DEBUG) {
- Log.d(TAG, "--- Reset inputmethod subtype because it's not defined.");
- }
- putSelectedInputMethodSubtype(resolver, NOT_A_SUBTYPE_ID);
- }
-
- Settings.Secure.putString(resolver,
- Settings.Secure.ENABLED_INPUT_METHODS, enabledIMEsAndSubtypesString);
- if (disabledSystemIMEsString.length() > 0) {
- Settings.Secure.putString(resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
- disabledSystemIMEsString);
- }
- // If the current input method is unset, InputMethodManagerService will find the applicable
- // IME from the history and the system locale.
- Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD,
- currentInputMethodId != null ? currentInputMethodId : "");
- }
-
- static void loadInputMethodSubtypeList(final SettingsPreferenceFragment context,
- final ContentResolver resolver, final List inputMethodInfos,
- final Map> inputMethodPrefsMap) {
- final HashMap> enabledSubtypes =
- getEnabledInputMethodsAndSubtypeList(resolver);
-
- for (final InputMethodInfo imi : inputMethodInfos) {
- final String imiId = imi.getId();
- final Preference pref = context.findPreference(imiId);
- if (pref instanceof TwoStatePreference) {
- final TwoStatePreference subtypePref = (TwoStatePreference) pref;
- final boolean isEnabled = enabledSubtypes.containsKey(imiId);
- subtypePref.setChecked(isEnabled);
- if (inputMethodPrefsMap != null) {
- for (final Preference childPref: inputMethodPrefsMap.get(imiId)) {
- childPref.setEnabled(isEnabled);
- }
- }
- setSubtypesPreferenceEnabled(context, inputMethodInfos, imiId, isEnabled);
- }
- }
- updateSubtypesPreferenceChecked(context, inputMethodInfos, enabledSubtypes);
- }
-
- static void setSubtypesPreferenceEnabled(final SettingsPreferenceFragment context,
- final List inputMethodProperties, final String id,
- final boolean enabled) {
- final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
- for (final InputMethodInfo imi : inputMethodProperties) {
- if (id.equals(imi.getId())) {
- final int subtypeCount = imi.getSubtypeCount();
- for (int i = 0; i < subtypeCount; ++i) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(i);
- final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
- .findPreference(id + subtype.hashCode());
- if (pref != null) {
- pref.setEnabled(enabled);
- }
- }
- }
- }
- }
-
- private static void updateSubtypesPreferenceChecked(final SettingsPreferenceFragment context,
- final List inputMethodProperties,
- final HashMap> enabledSubtypes) {
- final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
- for (final InputMethodInfo imi : inputMethodProperties) {
- final String id = imi.getId();
- if (!enabledSubtypes.containsKey(id)) {
- // There is no need to enable/disable subtypes of disabled IMEs.
- continue;
- }
- final HashSet enabledSubtypesSet = enabledSubtypes.get(id);
- final int subtypeCount = imi.getSubtypeCount();
- for (int i = 0; i < subtypeCount; ++i) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(i);
- final String hashCode = String.valueOf(subtype.hashCode());
- if (DEBUG) {
- Log.d(TAG, "--- Set checked state: " + "id" + ", " + hashCode + ", "
- + enabledSubtypesSet.contains(hashCode));
- }
- final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
- .findPreference(id + hashCode);
- if (pref != null) {
- pref.setChecked(enabledSubtypesSet.contains(hashCode));
- }
- }
- }
- }
-
- static void removeUnnecessaryNonPersistentPreference(final Preference pref) {
- final String key = pref.getKey();
- if (pref.isPersistent() || key == null) {
- return;
- }
- final SharedPreferences prefs = pref.getSharedPreferences();
- if (prefs != null && prefs.contains(key)) {
- prefs.edit().remove(key).apply();
- }
- }
-
- @NonNull
- static String getSubtypeLocaleNameAsSentence(@Nullable InputMethodSubtype subtype,
- @NonNull final Context context, @NonNull final InputMethodInfo inputMethodInfo) {
- if (subtype == null) {
- return "";
- }
- final Locale locale = getDisplayLocale(context);
- final CharSequence subtypeName = subtype.getDisplayName(context,
- inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
- .applicationInfo);
- return LocaleHelper.toSentenceCase(subtypeName.toString(), locale);
- }
-
- @NonNull
- static String getSubtypeLocaleNameListAsSentence(
- @NonNull final List subtypes, @NonNull final Context context,
- @NonNull final InputMethodInfo inputMethodInfo) {
- if (subtypes.isEmpty()) {
- return "";
- }
- final Locale locale = getDisplayLocale(context);
- final int subtypeCount = subtypes.size();
- final CharSequence[] subtypeNames = new CharSequence[subtypeCount];
- for (int i = 0; i < subtypeCount; i++) {
- subtypeNames[i] = subtypes.get(i).getDisplayName(context,
- inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
- .applicationInfo);
- }
- return LocaleHelper.toSentenceCase(
- ListFormatter.getInstance(locale).format(subtypeNames), locale);
- }
-
- @NonNull
- private static Locale getDisplayLocale(@Nullable final Context context) {
- if (context == null) {
- return Locale.getDefault();
- }
- if (context.getResources() == null) {
- return Locale.getDefault();
- }
- final Configuration configuration = context.getResources().getConfiguration();
- if (configuration == null) {
- return Locale.getDefault();
- }
- final Locale configurationLocale = configuration.getLocales().get(0);
- if (configurationLocale == null) {
- return Locale.getDefault();
- }
- return configurationLocale;
- }
-}
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index b2c28001a25..463a043cd6d 100755
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -16,13 +16,14 @@
package com.android.settings.inputmethod;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.UserHandle;
-import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
@@ -37,12 +38,12 @@ import com.android.internal.inputmethod.InputMethodUtils;
import com.android.settings.R;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
import java.text.Collator;
import java.util.List;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
/**
* Input method preference.
*
diff --git a/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java b/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
deleted file mode 100644
index cb2661995e8..00000000000
--- a/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.inputmethod;
-
-import android.app.ActivityManager;
-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;
-import java.util.HashSet;
-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.
- */
-// TODO: Consolidate this with {@link InputMethodAndSubtypeUtil}.
-class InputMethodSettingValuesWrapper {
- private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();
-
- private static volatile InputMethodSettingValuesWrapper sInstance;
- private final ArrayList mMethodList = new ArrayList<>();
- private final HashMap mMethodMap = new HashMap<>();
- private final InputMethodSettings mSettings;
- private final InputMethodManager mImm;
- private final HashSet mAsciiCapableEnabledImis = new HashSet<>();
-
- static InputMethodSettingValuesWrapper getInstance(Context context) {
- if (sInstance == null) {
- synchronized (TAG) {
- if (sInstance == null) {
- sInstance = new InputMethodSettingValuesWrapper(context);
- }
- }
- }
- 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);
- refreshAllInputMethodAndSubtypes();
- }
-
- void refreshAllInputMethodAndSubtypes() {
- synchronized (mMethodMap) {
- mMethodList.clear();
- mMethodMap.clear();
- final List imms = mImm.getInputMethodList();
- mMethodList.addAll(imms);
- for (InputMethodInfo imi : imms) {
- mMethodMap.put(imi.getId(), imi);
- }
- updateAsciiCapableEnabledImis();
- }
- }
-
- // TODO: Add a cts to ensure at least one AsciiCapableSubtypeEnabledImis exist
- private void updateAsciiCapableEnabledImis() {
- synchronized (mMethodMap) {
- mAsciiCapableEnabledImis.clear();
- final List enabledImis = mSettings.getEnabledInputMethodListLocked();
- for (final InputMethodInfo imi : enabledImis) {
- final int subtypeCount = imi.getSubtypeCount();
- for (int i = 0; i < subtypeCount; ++i) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(i);
- if (InputMethodUtils.SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())
- && subtype.isAsciiCapable()) {
- mAsciiCapableEnabledImis.add(imi);
- break;
- }
- }
- }
- }
- }
-
- List getInputMethodList() {
- synchronized (mMethodMap) {
- return mMethodList;
- }
- }
-
- CharSequence getCurrentInputMethodName(Context context) {
- synchronized (mMethodMap) {
- final InputMethodInfo imi = mMethodMap.get(mSettings.getSelectedInputMethod());
- if (imi == null) {
- Log.w(TAG, "Invalid selected imi: " + mSettings.getSelectedInputMethod());
- return "";
- }
- final InputMethodSubtype subtype = mImm.getCurrentInputMethodSubtype();
- return InputMethodUtils.getImeAndSubtypeDisplayName(context, imi, subtype);
- }
- }
-
- boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
- final boolean isEnabled = isEnabledImi(imi);
- synchronized (mMethodMap) {
- if (mSettings.getEnabledInputMethodListLocked().size() <= 1 && isEnabled) {
- return true;
- }
- }
-
- final int enabledValidSystemNonAuxAsciiCapableImeCount =
- getEnabledValidSystemNonAuxAsciiCapableImeCount(context);
- if (enabledValidSystemNonAuxAsciiCapableImeCount > 1) {
- return false;
- }
-
- if (enabledValidSystemNonAuxAsciiCapableImeCount == 1 && !isEnabled) {
- return false;
- }
-
- if (!InputMethodUtils.isSystemIme(imi)) {
- return false;
- }
- return isValidSystemNonAuxAsciiCapableIme(imi, context);
- }
-
- private int getEnabledValidSystemNonAuxAsciiCapableImeCount(Context context) {
- int count = 0;
- final List enabledImis;
- synchronized (mMethodMap) {
- enabledImis = mSettings.getEnabledInputMethodListLocked();
- }
- for (final InputMethodInfo imi : enabledImis) {
- if (isValidSystemNonAuxAsciiCapableIme(imi, context)) {
- ++count;
- }
- }
- if (count == 0) {
- Log.w(TAG, "No \"enabledValidSystemNonAuxAsciiCapableIme\"s found.");
- }
- return count;
- }
-
- boolean isEnabledImi(InputMethodInfo imi) {
- final List enabledImis;
- synchronized (mMethodMap) {
- enabledImis = mSettings.getEnabledInputMethodListLocked();
- }
- for (final InputMethodInfo tempImi : enabledImis) {
- if (tempImi.getId().equals(imi.getId())) {
- return true;
- }
- }
- return false;
- }
-
- boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi, Context context) {
- if (imi.isAuxiliaryIme()) {
- return false;
- }
- final Locale systemLocale = context.getResources().getConfiguration().locale;
- if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
- true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
- InputMethodUtils.SUBTYPE_MODE_ANY)) {
- return true;
- }
- if (mAsciiCapableEnabledImis.isEmpty()) {
- Log.w(TAG, "ascii capable subtype enabled imi not found. Fall back to English"
- + " Keyboard subtype.");
- return InputMethodUtils.containsSubtypeOf(imi, Locale.ENGLISH, false /* checkCountry */,
- InputMethodUtils.SUBTYPE_MODE_KEYBOARD);
- }
- return mAsciiCapableEnabledImis.contains(imi);
- }
-}
diff --git a/src/com/android/settings/inputmethod/InputMethodSubtypePreference.java b/src/com/android/settings/inputmethod/InputMethodSubtypePreference.java
deleted file mode 100644
index 678b2d96aa5..00000000000
--- a/src/com/android/settings/inputmethod/InputMethodSubtypePreference.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.inputmethod;
-
-import android.content.Context;
-import android.support.v7.preference.Preference;
-import android.text.TextUtils;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.internal.inputmethod.InputMethodUtils;
-
-import java.text.Collator;
-import java.util.Locale;
-
-/**
- * Input method subtype preference.
- *
- * This preference represents a subtype of an IME. It is used to enable or disable the subtype.
- */
-class InputMethodSubtypePreference extends SwitchWithNoTextPreference {
- private final boolean mIsSystemLocale;
- private final boolean mIsSystemLanguage;
-
- InputMethodSubtypePreference(final Context context, final InputMethodSubtype subtype,
- final InputMethodInfo imi) {
- super(context);
- setPersistent(false);
- setKey(imi.getId() + subtype.hashCode());
- final CharSequence subtypeLabel =
- InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(subtype, context, imi);
- setTitle(subtypeLabel);
- final String subtypeLocaleString = subtype.getLocale();
- if (TextUtils.isEmpty(subtypeLocaleString)) {
- mIsSystemLocale = false;
- mIsSystemLanguage = false;
- } else {
- final Locale systemLocale = context.getResources().getConfiguration().locale;
- mIsSystemLocale = subtypeLocaleString.equals(systemLocale.toString());
- mIsSystemLanguage = mIsSystemLocale
- || InputMethodUtils.getLanguageFromLocaleString(subtypeLocaleString)
- .equals(systemLocale.getLanguage());
- }
- }
-
- int compareTo(final Preference rhs, final Collator collator) {
- if (this == rhs) {
- return 0;
- }
- if (rhs instanceof InputMethodSubtypePreference) {
- final InputMethodSubtypePreference rhsPref = (InputMethodSubtypePreference) rhs;
- if (mIsSystemLocale && !rhsPref.mIsSystemLocale) {
- return -1;
- }
- if (!mIsSystemLocale && rhsPref.mIsSystemLocale) {
- return 1;
- }
- if (mIsSystemLanguage && !rhsPref.mIsSystemLanguage) {
- return -1;
- }
- if (!mIsSystemLanguage && rhsPref.mIsSystemLanguage) {
- return 1;
- }
- final CharSequence t0 = getTitle();
- final CharSequence t1 = rhs.getTitle();
- if (t0 == null && t1 == null) {
- return Integer.compare(hashCode(), rhs.hashCode());
- }
- if (t0 != null && t1 != null) {
- return collator.compare(t0.toString(), t1.toString());
- }
- return t0 == null ? -1 : 1;
- }
- return super.compareTo(rhs);
- }
-}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 1ecb2502533..ad6e0417ff7 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -52,6 +52,7 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import java.text.Collator;
import java.util.ArrayList;
diff --git a/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java b/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java
index 8fcaa74043f..5ab2cbae08c 100644
--- a/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java
+++ b/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java
@@ -24,6 +24,7 @@ import android.view.textservice.TextServicesManager;
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
public class SpellCheckerPreferenceController extends PreferenceController {
diff --git a/src/com/android/settings/inputmethod/SwitchWithNoTextPreference.java b/src/com/android/settings/inputmethod/SwitchWithNoTextPreference.java
deleted file mode 100644
index 727f56f4e54..00000000000
--- a/src/com/android/settings/inputmethod/SwitchWithNoTextPreference.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.inputmethod;
-
-import android.content.Context;
-import android.support.v14.preference.SwitchPreference;
-
-class SwitchWithNoTextPreference extends SwitchPreference {
- private static final String EMPTY_TEXT = "";
-
- SwitchWithNoTextPreference(final Context context) {
- super(context);
- setSwitchTextOn(EMPTY_TEXT);
- setSwitchTextOff(EMPTY_TEXT);
- }
-}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index da5cb04db1d..c3623894d51 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -26,7 +26,6 @@ import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
@@ -35,6 +34,7 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import java.text.Collator;
import java.util.ArrayList;