diff options
author | Tadashi G. Takaoka <takaoka@google.com> | 2014-07-21 17:58:47 -0700 |
---|---|---|
committer | Tadashi G. Takaoka <takaoka@google.com> | 2014-07-28 11:40:22 +0900 |
commit | 9a8b4f239f219bb2cd2d08470b8c858fd74341e7 (patch) | |
tree | 4a053e73ae3a7ba73fce3b5a4992517f51b3831c /src/com/android/settings/inputmethod | |
parent | 935f97cd9bc38fefc5b3358a2151440b85c54c32 (diff) | |
download | packages_apps_Settings-9a8b4f239f219bb2cd2d08470b8c858fd74341e7.zip packages_apps_Settings-9a8b4f239f219bb2cd2d08470b8c858fd74341e7.tar.gz packages_apps_Settings-9a8b4f239f219bb2cd2d08470b8c858fd74341e7.tar.bz2 |
Preserve enabled subtypes across disabling and re-enabling an IME
Bug: 16464156
Change-Id: I2ea4d010e47e5f48b2df11775b0c262330b28e89
Diffstat (limited to 'src/com/android/settings/inputmethod')
3 files changed, 134 insertions, 59 deletions
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java index 878c3c1..1601cd0 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java +++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java @@ -22,6 +22,7 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -38,6 +39,7 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceCategory; +import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.provider.Settings; import android.provider.Settings.System; @@ -67,6 +69,8 @@ import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.TreeSet; @@ -80,6 +84,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector"; private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; + private static final String KEY_PREVIOUSLY_ENABLED_SUBTYPES = "previously_enabled_subtypes"; // false: on ICS or later private static final boolean SHOW_INPUT_METHOD_SWITCHER_SETTINGS = false; @@ -471,17 +476,72 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment @Override public void onSaveInputMethodPreference(final InputMethodPreference pref) { + final InputMethodInfo imi = pref.getInputMethodInfo(); + if (!pref.isChecked()) { + // An IME is being disabled. Save enabled subtypes of the IME to shared preference to be + // able to re-enable these subtypes when the IME gets re-enabled. + saveEnabledSubtypesOf(imi); + } final boolean hasHardwareKeyboard = getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY; InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), mImm.getInputMethodList(), hasHardwareKeyboard); // Update input method settings and preference list. mInputMethodSettingValues.refreshAllInputMethodAndSubtypes(); + if (pref.isChecked()) { + // An IME is being enabled. Load the previously enabled subtypes from shared preference + // and enable these subtypes. + restorePreviouslyEnabledSubtypesOf(imi); + } for (final InputMethodPreference p : mInputMethodPreferenceList) { p.updatePreferenceViews(); } } + private void saveEnabledSubtypesOf(final InputMethodInfo imi) { + final HashSet<String> enabledSubtypeIdSet = new HashSet<>(); + final List<InputMethodSubtype> enabledSubtypes = mImm.getEnabledInputMethodSubtypeList( + imi, true /* allowsImplicitlySelectedSubtypes */); + for (final InputMethodSubtype subtype : enabledSubtypes) { + final String subtypeId = Integer.toString(subtype.hashCode()); + enabledSubtypeIdSet.add(subtypeId); + } + final HashMap<String, HashSet<String>> imeToEnabledSubtypeIdsMap = + loadPreviouslyEnabledSubtypeIdsMap(); + final String imiId = imi.getId(); + imeToEnabledSubtypeIdsMap.put(imiId, enabledSubtypeIdSet); + savePreviouslyEnabledSubtypeIdsMap(imeToEnabledSubtypeIdsMap); + } + + private void restorePreviouslyEnabledSubtypesOf(final InputMethodInfo imi) { + final HashMap<String, HashSet<String>> imeToEnabledSubtypeIdsMap = + loadPreviouslyEnabledSubtypeIdsMap(); + final String imiId = imi.getId(); + final HashSet<String> enabledSubtypeIdSet = imeToEnabledSubtypeIdsMap.remove(imiId); + if (enabledSubtypeIdSet == null) { + return; + } + savePreviouslyEnabledSubtypeIdsMap(imeToEnabledSubtypeIdsMap); + InputMethodAndSubtypeUtil.enableInputMethodSubtypesOf( + getContentResolver(), imiId, enabledSubtypeIdSet); + } + + private HashMap<String, HashSet<String>> loadPreviouslyEnabledSubtypeIdsMap() { + final Context context = getActivity(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final String imesAndSubtypesString = prefs.getString(KEY_PREVIOUSLY_ENABLED_SUBTYPES, null); + return InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString(imesAndSubtypesString); + } + + private void savePreviouslyEnabledSubtypeIdsMap( + final HashMap<String, HashSet<String>> subtypesMap) { + final Context context = getActivity(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final String imesAndSubtypesString = InputMethodAndSubtypeUtil + .buildInputMethodsAndSubtypesString(subtypesMap); + prefs.edit().putString(KEY_PREVIOUSLY_ENABLED_SUBTYPES, imesAndSubtypesString).apply(); + } + private void updateCurrentImeName() { final Context context = getActivity(); if (context == null || mImm == null) return; diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java index 3f37db7..b184066 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java +++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java @@ -52,40 +52,33 @@ class InputMethodAndSubtypeUtil { private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER); - private static void buildEnabledInputMethodsString(StringBuilder builder, String imi, - HashSet<String> subtypes) { - builder.append(imi); - // Inputmethod and subtypes are saved in the settings as follows: - // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 - for (String subtypeId: subtypes) { - builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypeId); - } - } - - private static void buildInputMethodsAndSubtypesString(StringBuilder builder, - HashMap<String, HashSet<String>> imsList) { - boolean needsAppendSeparator = false; - for (String imi: imsList.keySet()) { - if (needsAppendSeparator) { + // InputMethods and subtypes are saved in the settings as follows: + // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 + static String buildInputMethodsAndSubtypesString( + final HashMap<String, HashSet<String>> imeToSubtypesMap) { + final StringBuilder builder = new StringBuilder(); + for (final String imi : imeToSubtypesMap.keySet()) { + if (builder.length() > 0) { builder.append(INPUT_METHOD_SEPARATER); - } else { - needsAppendSeparator = true; } - buildEnabledInputMethodsString(builder, imi, imsList.get(imi)); + final HashSet<String> 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 void buildDisabledSystemInputMethods(StringBuilder builder, - HashSet<String> imes) { - boolean needsAppendSeparator = false; - for (String ime: imes) { - if (needsAppendSeparator) { + private static String buildInputMethodsString(final HashSet<String> imiList) { + final StringBuilder builder = new StringBuilder(); + for (final String imi : imiList) { + if (builder.length() > 0) { builder.append(INPUT_METHOD_SEPARATER); - } else { - needsAppendSeparator = true; } - builder.append(ime); + builder.append(imi); } + return builder.toString(); } private static int getInputMethodSubtypeSelected(ContentResolver resolver) { @@ -110,29 +103,44 @@ class InputMethodAndSubtypeUtil { ContentResolver resolver) { final String enabledInputMethodsStr = Settings.Secure.getString( resolver, Settings.Secure.ENABLED_INPUT_METHODS); - HashMap<String, HashSet<String>> imsList = new HashMap<>(); if (DEBUG) { Log.d(TAG, "--- Load enabled input methods: " + enabledInputMethodsStr); } + return parseInputMethodsAndSubtypesString(enabledInputMethodsStr); + } - if (TextUtils.isEmpty(enabledInputMethodsStr)) { - return imsList; + static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString( + final String inputMethodsAndSubtypesString) { + final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>(); + if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { + return subtypesMap; } - sStringInputMethodSplitter.setString(enabledInputMethodsStr); + sStringInputMethodSplitter.setString(inputMethodsAndSubtypesString); while (sStringInputMethodSplitter.hasNext()) { - String nextImsStr = sStringInputMethodSplitter.next(); + final String nextImsStr = sStringInputMethodSplitter.next(); sStringInputMethodSubtypeSplitter.setString(nextImsStr); if (sStringInputMethodSubtypeSplitter.hasNext()) { - HashSet<String> subtypeHashes = new HashSet<>(); - // The first element is ime id. - String imeId = sStringInputMethodSubtypeSplitter.next(); + final HashSet<String> subtypeIdSet = new HashSet<>(); + // The first element is {@link InputMethodInfoId}. + final String imiId = sStringInputMethodSubtypeSplitter.next(); while (sStringInputMethodSubtypeSplitter.hasNext()) { - subtypeHashes.add(sStringInputMethodSubtypeSplitter.next()); + subtypeIdSet.add(sStringInputMethodSubtypeSplitter.next()); } - imsList.put(imeId, subtypeHashes); + subtypesMap.put(imiId, subtypeIdSet); } } - return imsList; + return subtypesMap; + } + + static void enableInputMethodSubtypesOf(final ContentResolver resolver, final String imiId, + final HashSet<String> enabledSubtypeIdSet) { + final HashMap<String, HashSet<String>> 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<String> getDisabledSystemIMEs(ContentResolver resolver) { @@ -155,40 +163,44 @@ class InputMethodAndSubtypeUtil { String currentInputMethodId = Settings.Secure.getString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD); final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver); - HashMap<String, HashSet<String>> enabledIMEAndSubtypesMap = + final HashMap<String, HashSet<String>> enabledIMEsAndSubtypesMap = getEnabledInputMethodsAndSubtypeList(resolver); - HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver); + final HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver); boolean needsToResetSelectedSubtype = false; - for (InputMethodInfo imi : inputMethodInfos) { + for (final InputMethodInfo imi : inputMethodInfos) { final String imiId = imi.getId(); - Preference pref = context.findPreference(imiId); - if (pref == null) continue; + final Preference pref = context.findPreference(imiId); + if (pref == null) { + continue; + } // In the choose input method screen or in the subtype enabler screen, // <code>pref</code> is an instance of TwoStatePreference. final boolean isImeChecked = (pref instanceof TwoStatePreference) ? ((TwoStatePreference) pref).isChecked() - : enabledIMEAndSubtypesMap.containsKey(imiId); + : 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 (!enabledIMEAndSubtypesMap.containsKey(imiId)) { + if (!enabledIMEsAndSubtypesMap.containsKey(imiId)) { // imiId has just been enabled - enabledIMEAndSubtypesMap.put(imiId, new HashSet<String>()); + enabledIMEsAndSubtypesMap.put(imiId, new HashSet<String>()); } - HashSet<String> subtypesSet = enabledIMEAndSubtypesMap.get(imiId); + final HashSet<String> subtypesSet = enabledIMEsAndSubtypesMap.get(imiId); boolean subtypePrefFound = false; final int subtypeCount = imi.getSubtypeCount(); for (int i = 0; i < subtypeCount; ++i) { - InputMethodSubtype subtype = imi.getSubtypeAt(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 (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. @@ -211,7 +223,7 @@ class InputMethodAndSubtypeUtil { } } } else { - enabledIMEAndSubtypesMap.remove(imiId); + 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. @@ -238,14 +250,13 @@ class InputMethodAndSubtypeUtil { } } - StringBuilder builder = new StringBuilder(); - buildInputMethodsAndSubtypesString(builder, enabledIMEAndSubtypesMap); - StringBuilder disabledSysImesBuilder = new StringBuilder(); - buildDisabledSystemInputMethods(disabledSysImesBuilder, disabledSystemIMEs); + final String enabledIMEsAndSubtypesString = buildInputMethodsAndSubtypesString( + enabledIMEsAndSubtypesMap); + final String disabledSystemIMEsString = buildInputMethodsString(disabledSystemIMEs); if (DEBUG) { - Log.d(TAG, "--- Save enabled inputmethod settings. :" + builder.toString()); - Log.d(TAG, "--- Save disable system inputmethod settings. :" - + disabledSysImesBuilder.toString()); + 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)); @@ -262,10 +273,10 @@ class InputMethodAndSubtypeUtil { } Settings.Secure.putString(resolver, - Settings.Secure.ENABLED_INPUT_METHODS, builder.toString()); - if (disabledSysImesBuilder.length() > 0) { + Settings.Secure.ENABLED_INPUT_METHODS, enabledIMEsAndSubtypesString); + if (disabledSystemIMEsString.length() > 0) { Settings.Secure.putString(resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, - disabledSysImesBuilder.toString()); + disabledSystemIMEsString); } // If the current input method is unset, InputMethodManagerService will find the applicable // IME from the history and the system locale. diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java index a65e5e5..111f79b 100755 --- a/src/com/android/settings/inputmethod/InputMethodPreference.java +++ b/src/com/android/settings/inputmethod/InputMethodPreference.java @@ -112,6 +112,10 @@ class InputMethodPreference extends SwitchPreference implements OnPreferenceClic setOnPreferenceChangeListener(this); } + public InputMethodInfo getInputMethodInfo() { + return mImi; + } + private boolean isImeEnabler() { // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the // switch widget at constructor. |