1b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler/*
2b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * Copyright (C) 2017 The Android Open Source Project
3b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler *
4b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * Licensed under the Apache License, Version 2.0 (the "License");
5b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * you may not use this file except in compliance with the License.
6b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * You may obtain a copy of the License at
7b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler *
8b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler *      http://www.apache.org/licenses/LICENSE-2.0
9b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler *
10b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * Unless required by applicable law or agreed to in writing, software
11b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * distributed under the License is distributed on an "AS IS" BASIS,
12b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * See the License for the specific language governing permissions and
14b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler * limitations under the License
15b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler */
16b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
17b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerpackage com.android.settingslib.inputmethod;
18b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
19b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.content.Context;
20b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.content.pm.PackageManager;
21b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.content.res.Configuration;
22b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.support.v14.preference.PreferenceFragment;
23b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.support.v7.preference.Preference;
24b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.support.v7.preference.PreferenceCategory;
25b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.support.v7.preference.PreferenceScreen;
26b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.support.v7.preference.TwoStatePreference;
27b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.text.TextUtils;
28b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.view.inputmethod.InputMethodInfo;
29b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.view.inputmethod.InputMethodManager;
30b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport android.view.inputmethod.InputMethodSubtype;
31b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
32b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport com.android.settingslib.R;
33b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
34b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport java.text.Collator;
35b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport java.util.ArrayList;
36b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport java.util.HashMap;
37b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerimport java.util.List;
38b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
39b8592357c37e681ba709b524a7202b7787f35e5aTony Mantlerpublic class InputMethodAndSubtypeEnablerManager implements Preference.OnPreferenceChangeListener {
40b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
41b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private final PreferenceFragment mFragment;
42b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
43b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private boolean mHaveHardKeyboard;
44b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private final HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
45b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            new HashMap<>();
46b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private final HashMap<String, TwoStatePreference> mAutoSelectionPrefsMap = new HashMap<>();
47b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private InputMethodManager mImm;
48b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    // TODO: Change mInputMethodInfoList to Map
49b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private List<InputMethodInfo> mInputMethodInfoList;
50b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private final Collator mCollator = Collator.getInstance();
51b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
52b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    public InputMethodAndSubtypeEnablerManager(PreferenceFragment fragment) {
53b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        mFragment = fragment;
54b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        mImm = fragment.getContext().getSystemService(InputMethodManager.class);
55b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
56b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        mInputMethodInfoList = mImm.getInputMethodList();
57b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
58b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
59b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    public void init(PreferenceFragment fragment, String targetImi, PreferenceScreen root) {
60b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final Configuration config = fragment.getResources().getConfiguration();
61b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
62b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
63b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final InputMethodInfo imi : mInputMethodInfoList) {
64b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            // Add subtype preferences of this IME when it is specified or no IME is specified.
65b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) {
66b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                addInputMethodSubtypePreferences(fragment, imi, root);
67b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
68b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
69b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
70b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
71b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    public void refresh(Context context, PreferenceFragment fragment) {
72b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        // Refresh internal states in mInputMethodSettingValues to keep the latest
73b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        // "InputMethodInfo"s and "InputMethodSubtype"s
74b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        InputMethodSettingValuesWrapper
75b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                .getInstance(context).refreshAllInputMethodAndSubtypes();
76b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(fragment, context.getContentResolver(),
77b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                mInputMethodInfoList, mInputMethodAndSubtypePrefsMap);
78b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        updateAutoSelectionPreferences();
79b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
80b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
81b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    public void save(Context context, PreferenceFragment fragment) {
82b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(fragment, context.getContentResolver(),
83b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                mInputMethodInfoList, mHaveHardKeyboard);
84b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
85b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
86b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    @Override
87b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    public boolean onPreferenceChange(final Preference pref, final Object newValue) {
88b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (!(newValue instanceof Boolean)) {
89b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            return true; // Invoke default behavior.
90b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
91b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final boolean isChecking = (Boolean) newValue;
92b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final String imiId : mAutoSelectionPrefsMap.keySet()) {
93b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            // An auto select subtype preference is changing.
94b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (mAutoSelectionPrefsMap.get(imiId) == pref) {
95b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                final TwoStatePreference autoSelectionPref = (TwoStatePreference) pref;
96b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                autoSelectionPref.setChecked(isChecking);
97b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                // Enable or disable subtypes depending on the auto selection preference.
98b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                setAutoSelectionSubtypesEnabled(imiId, autoSelectionPref.isChecked());
99b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                return false;
100b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
101b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
102b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        // A subtype preference is changing.
103b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (pref instanceof InputMethodSubtypePreference) {
104b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final InputMethodSubtypePreference subtypePref = (InputMethodSubtypePreference) pref;
105b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            subtypePref.setChecked(isChecking);
106b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (!subtypePref.isChecked()) {
107b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                // It takes care of the case where no subtypes are explicitly enabled then the auto
108b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                // selection preference is going to be checked.
109b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                updateAutoSelectionPreferences();
110b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
111b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            return false;
112b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
113b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        return true; // Invoke default behavior.
114b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
115b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
116b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private void addInputMethodSubtypePreferences(PreferenceFragment fragment, InputMethodInfo imi,
117b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final PreferenceScreen root) {
118b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        Context prefContext = fragment.getPreferenceManager().getContext();
119b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
120b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final int subtypeCount = imi.getSubtypeCount();
121b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (subtypeCount <= 1) {
122b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            return;
123b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
124b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final String imiId = imi.getId();
125b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final PreferenceCategory keyboardSettingsCategory =
126b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                new PreferenceCategory(prefContext);
127b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        root.addPreference(keyboardSettingsCategory);
128b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final PackageManager pm = prefContext.getPackageManager();
129b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final CharSequence label = imi.loadLabel(pm);
130b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
131b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        keyboardSettingsCategory.setTitle(label);
132b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        keyboardSettingsCategory.setKey(imiId);
133b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        // TODO: Use toggle Preference if images are ready.
134b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final TwoStatePreference autoSelectionPref =
135b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                new SwitchWithNoTextPreference(prefContext);
136b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        mAutoSelectionPrefsMap.put(imiId, autoSelectionPref);
137b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        keyboardSettingsCategory.addPreference(autoSelectionPref);
138b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        autoSelectionPref.setOnPreferenceChangeListener(this);
139b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
140b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final PreferenceCategory activeInputMethodsCategory =
141b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                new PreferenceCategory(prefContext);
142b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
143b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        root.addPreference(activeInputMethodsCategory);
144b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
145b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        CharSequence autoSubtypeLabel = null;
146b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final ArrayList<Preference> subtypePreferences = new ArrayList<>();
147b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (int index = 0; index < subtypeCount; ++index) {
148b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final InputMethodSubtype subtype = imi.getSubtypeAt(index);
149b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (subtype.overridesImplicitlyEnabledSubtype()) {
150b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                if (autoSubtypeLabel == null) {
151b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    autoSubtypeLabel = InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
152b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                            subtype, prefContext, imi);
153b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                }
154b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            } else {
155b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                final Preference subtypePref = new InputMethodSubtypePreference(
156b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                        prefContext, subtype, imi);
157b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                subtypePreferences.add(subtypePref);
158b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
159b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
160b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        subtypePreferences.sort((lhs, rhs) -> {
161b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (lhs instanceof InputMethodSubtypePreference) {
162b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator);
163b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
164b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            return lhs.compareTo(rhs);
165b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        });
166b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final Preference pref : subtypePreferences) {
167b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            activeInputMethodsCategory.addPreference(pref);
168b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            pref.setOnPreferenceChangeListener(this);
169b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
170b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
171b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
172b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (TextUtils.isEmpty(autoSubtypeLabel)) {
173b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            autoSelectionPref.setTitle(
174b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    R.string.use_system_language_to_select_input_method_subtypes);
175b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        } else {
176b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            autoSelectionPref.setTitle(autoSubtypeLabel);
177b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
178b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
179b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
180b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private boolean isNoSubtypesExplicitlySelected(final String imiId) {
181b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
182b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final Preference pref : subtypePrefs) {
183b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (pref instanceof TwoStatePreference && ((TwoStatePreference) pref).isChecked()) {
184b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                return false;
185b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
186b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
187b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        return true;
188b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
189b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
190b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private void setAutoSelectionSubtypesEnabled(final String imiId,
191b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final boolean autoSelectionEnabled) {
192b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
193b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (autoSelectionPref == null) {
194b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            return;
195b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
196b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        autoSelectionPref.setChecked(autoSelectionEnabled);
197b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
198b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final Preference pref : subtypePrefs) {
199b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (pref instanceof TwoStatePreference) {
200b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
201b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                // implicitly checked subtypes. In case of false, all subtype prefs need to be
202b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                // enabled.
203b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                pref.setEnabled(!autoSelectionEnabled);
204b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                if (autoSelectionEnabled) {
205b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    ((TwoStatePreference) pref).setChecked(false);
206b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                }
207b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
208b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
209b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (autoSelectionEnabled) {
210b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
211b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    mFragment, mFragment.getContext().getContentResolver(),
212b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    mInputMethodInfoList, mHaveHardKeyboard);
213b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            updateImplicitlyEnabledSubtypes(imiId);
214b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
215b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
216b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
217b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private void updateImplicitlyEnabledSubtypes(final String targetImiId) {
218b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        // When targetImiId is null, apply to all subtypes of all IMEs
219b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final InputMethodInfo imi : mInputMethodInfoList) {
220b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final String imiId = imi.getId();
221b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
222b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            // No need to update implicitly enabled subtypes when the user has unchecked the
223b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            // "subtype auto selection".
224b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (autoSelectionPref == null || !autoSelectionPref.isChecked()) {
225b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                continue;
226b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
227b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (imiId.equals(targetImiId) || targetImiId == null) {
228b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                updateImplicitlyEnabledSubtypesOf(imi);
229b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
230b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
231b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
232b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
233b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi) {
234b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final String imiId = imi.getId();
235b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
236b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        final List<InputMethodSubtype> implicitlyEnabledSubtypes =
237b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                mImm.getEnabledInputMethodSubtypeList(imi, true);
238b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        if (subtypePrefs == null || implicitlyEnabledSubtypes == null) {
239b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            return;
240b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
241b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final Preference pref : subtypePrefs) {
242b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            if (!(pref instanceof TwoStatePreference)) {
243b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                continue;
244b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
245b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            final TwoStatePreference subtypePref = (TwoStatePreference) pref;
246b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            subtypePref.setChecked(false);
247b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) {
248b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
249b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
250b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    subtypePref.setChecked(true);
251b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                    break;
252b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler                }
253b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            }
254b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
255b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
256b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler
257b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    private void updateAutoSelectionPreferences() {
258b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) {
259b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler            setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
260b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        }
261b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler        updateImplicitlyEnabledSubtypes(null /* targetImiId */  /* check */);
262b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler    }
263b8592357c37e681ba709b524a7202b7787f35e5aTony Mantler}
264