InputMethodAndSubtypeEnabler.java revision 1c58c15e7a84b582b7d4d20c26824cabce80bce9
14a5f889f80b683446e498f244d0eadfd979ca5d0satok/*
24a5f889f80b683446e498f244d0eadfd979ca5d0satok * Copyright (C) 2010 The Android Open Source Project
34a5f889f80b683446e498f244d0eadfd979ca5d0satok *
44a5f889f80b683446e498f244d0eadfd979ca5d0satok * Licensed under the Apache License, Version 2.0 (the "License");
54a5f889f80b683446e498f244d0eadfd979ca5d0satok * you may not use this file except in compliance with the License.
64a5f889f80b683446e498f244d0eadfd979ca5d0satok * You may obtain a copy of the License at
74a5f889f80b683446e498f244d0eadfd979ca5d0satok *
84a5f889f80b683446e498f244d0eadfd979ca5d0satok *      http://www.apache.org/licenses/LICENSE-2.0
94a5f889f80b683446e498f244d0eadfd979ca5d0satok *
104a5f889f80b683446e498f244d0eadfd979ca5d0satok * Unless required by applicable law or agreed to in writing, software
114a5f889f80b683446e498f244d0eadfd979ca5d0satok * distributed under the License is distributed on an "AS IS" BASIS,
124a5f889f80b683446e498f244d0eadfd979ca5d0satok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134a5f889f80b683446e498f244d0eadfd979ca5d0satok * See the License for the specific language governing permissions and
144a5f889f80b683446e498f244d0eadfd979ca5d0satok * limitations under the License.
154a5f889f80b683446e498f244d0eadfd979ca5d0satok */
164a5f889f80b683446e498f244d0eadfd979ca5d0satok
170417e4094713c5f4dac700b645000d0959bf62fasatokpackage com.android.settings.inputmethod;
180417e4094713c5f4dac700b645000d0959bf62fasatok
190417e4094713c5f4dac700b645000d0959bf62fasatokimport com.android.settings.R;
200417e4094713c5f4dac700b645000d0959bf62fasatokimport com.android.settings.SettingsPreferenceFragment;
214a5f889f80b683446e498f244d0eadfd979ca5d0satok
224a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.app.AlertDialog;
234a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.Context;
244a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.DialogInterface;
254a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.pm.PackageManager;
264a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.res.Configuration;
274a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.os.Bundle;
284a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.CheckBoxPreference;
294a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.Preference;
304a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceCategory;
314a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceScreen;
32c88a7ff1efd10374974e45768bde1658cc1d8483satokimport android.text.TextUtils;
334a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodInfo;
344a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodManager;
354a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodSubtype;
364a5f889f80b683446e498f244d0eadfd979ca5d0satok
374a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.ArrayList;
38c88a7ff1efd10374974e45768bde1658cc1d8483satokimport java.util.HashMap;
394a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.List;
404a5f889f80b683446e498f244d0eadfd979ca5d0satok
414a5f889f80b683446e498f244d0eadfd979ca5d0satokpublic class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
424a5f889f80b683446e498f244d0eadfd979ca5d0satok
43c88a7ff1efd10374974e45768bde1658cc1d8483satok    public static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
444a5f889f80b683446e498f244d0eadfd979ca5d0satok
454a5f889f80b683446e498f244d0eadfd979ca5d0satok    private AlertDialog mDialog = null;
46c88a7ff1efd10374974e45768bde1658cc1d8483satok    private boolean mHaveHardKeyboard;
471c58c15e7a84b582b7d4d20c26824cabce80bce9satok    final private HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
481c58c15e7a84b582b7d4d20c26824cabce80bce9satok            new HashMap<String, List<Preference>>();
491c58c15e7a84b582b7d4d20c26824cabce80bce9satok    final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap =
501c58c15e7a84b582b7d4d20c26824cabce80bce9satok            new HashMap<String, CheckBoxPreference>();
511c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private InputMethodManager mImm;
52c88a7ff1efd10374974e45768bde1658cc1d8483satok    private List<InputMethodInfo> mInputMethodProperties;
53c88a7ff1efd10374974e45768bde1658cc1d8483satok    private String mInputMethodId;
544a5f889f80b683446e498f244d0eadfd979ca5d0satok
554a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
564a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onCreate(Bundle icicle) {
574a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onCreate(icicle);
581c58c15e7a84b582b7d4d20c26824cabce80bce9satok        mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
594a5f889f80b683446e498f244d0eadfd979ca5d0satok        Configuration config = getResources().getConfiguration();
604a5f889f80b683446e498f244d0eadfd979ca5d0satok        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
61c88a7ff1efd10374974e45768bde1658cc1d8483satok        mInputMethodId = getActivity().getIntent().getStringExtra(EXTRA_INPUT_METHOD_ID);
624a5f889f80b683446e498f244d0eadfd979ca5d0satok        onCreateIMM();
634a5f889f80b683446e498f244d0eadfd979ca5d0satok        setPreferenceScreen(createPreferenceHierarchy());
644a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
654a5f889f80b683446e498f244d0eadfd979ca5d0satok
664a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
674a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onResume() {
684a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onResume();
690417e4094713c5f4dac700b645000d0959bf62fasatok        InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
701c58c15e7a84b582b7d4d20c26824cabce80bce9satok                this, getContentResolver(), mInputMethodProperties, mInputMethodAndSubtypePrefsMap);
711c58c15e7a84b582b7d4d20c26824cabce80bce9satok        updateAutoSelectionCB();
724a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
734a5f889f80b683446e498f244d0eadfd979ca5d0satok
744a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
754a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onPause() {
764a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onPause();
771c58c15e7a84b582b7d4d20c26824cabce80bce9satok        // Clear all subtypes of all IMEs to make sure
781c58c15e7a84b582b7d4d20c26824cabce80bce9satok        clearImplicitlyEnabledSubtypes(null);
790417e4094713c5f4dac700b645000d0959bf62fasatok        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
805fd39cafe1de792300e9e3dd60258a1ce5079f73satok                mInputMethodProperties, mHaveHardKeyboard);
814a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
824a5f889f80b683446e498f244d0eadfd979ca5d0satok
834a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
844a5f889f80b683446e498f244d0eadfd979ca5d0satok    public boolean onPreferenceTreeClick(
854a5f889f80b683446e498f244d0eadfd979ca5d0satok            PreferenceScreen preferenceScreen, Preference preference) {
864a5f889f80b683446e498f244d0eadfd979ca5d0satok
874a5f889f80b683446e498f244d0eadfd979ca5d0satok        if (preference instanceof CheckBoxPreference) {
884a5f889f80b683446e498f244d0eadfd979ca5d0satok            final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
891c58c15e7a84b582b7d4d20c26824cabce80bce9satok
901c58c15e7a84b582b7d4d20c26824cabce80bce9satok            for (String imiId: mSubtypeAutoSelectionCBMap.keySet()) {
911c58c15e7a84b582b7d4d20c26824cabce80bce9satok                if (mSubtypeAutoSelectionCBMap.get(imiId) == chkPref) {
921c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    // We look for the first preference item in subtype enabler.
931c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    // The first item is used for turning on/off subtype auto selection.
941c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    // We are in the subtype enabler and trying selecting subtypes automatically.
951c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    setSubtypeAutoSelectionEnabled(imiId, chkPref.isChecked());
961c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    return super.onPreferenceTreeClick(preferenceScreen, preference);
971c58c15e7a84b582b7d4d20c26824cabce80bce9satok                }
981c58c15e7a84b582b7d4d20c26824cabce80bce9satok            }
991c58c15e7a84b582b7d4d20c26824cabce80bce9satok
1004a5f889f80b683446e498f244d0eadfd979ca5d0satok            final String id = chkPref.getKey();
1014a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (chkPref.isChecked()) {
1024a5f889f80b683446e498f244d0eadfd979ca5d0satok                InputMethodInfo selImi = null;
1034a5f889f80b683446e498f244d0eadfd979ca5d0satok                final int N = mInputMethodProperties.size();
1044a5f889f80b683446e498f244d0eadfd979ca5d0satok                for (int i = 0; i < N; i++) {
1054a5f889f80b683446e498f244d0eadfd979ca5d0satok                    InputMethodInfo imi = mInputMethodProperties.get(i);
1064a5f889f80b683446e498f244d0eadfd979ca5d0satok                    if (id.equals(imi.getId())) {
1074a5f889f80b683446e498f244d0eadfd979ca5d0satok                        selImi = imi;
1089cd11a9aa5ac74ca89432655d019f68d789bc405satok                        if (InputMethodAndSubtypeUtil.isSystemIme(imi)) {
1099cd11a9aa5ac74ca89432655d019f68d789bc405satok                            InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
1109cd11a9aa5ac74ca89432655d019f68d789bc405satok                                    this, mInputMethodProperties, id, true);
1114a5f889f80b683446e498f244d0eadfd979ca5d0satok                            // This is a built-in IME, so no need to warn.
1124a5f889f80b683446e498f244d0eadfd979ca5d0satok                            return super.onPreferenceTreeClick(preferenceScreen, preference);
1134a5f889f80b683446e498f244d0eadfd979ca5d0satok                        }
1144a5f889f80b683446e498f244d0eadfd979ca5d0satok                        break;
1154a5f889f80b683446e498f244d0eadfd979ca5d0satok                    }
1164a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1174a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (selImi == null) {
1184a5f889f80b683446e498f244d0eadfd979ca5d0satok                    return super.onPreferenceTreeClick(preferenceScreen, preference);
1194a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1204a5f889f80b683446e498f244d0eadfd979ca5d0satok                chkPref.setChecked(false);
1214a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (mDialog == null) {
1224a5f889f80b683446e498f244d0eadfd979ca5d0satok                    mDialog = (new AlertDialog.Builder(getActivity()))
1234a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setTitle(android.R.string.dialog_alert_title)
1244a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setIcon(android.R.drawable.ic_dialog_alert)
1254a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setCancelable(true)
1264a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setPositiveButton(android.R.string.ok,
1274a5f889f80b683446e498f244d0eadfd979ca5d0satok                                    new DialogInterface.OnClickListener() {
1284a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        public void onClick(DialogInterface dialog, int which) {
1294a5f889f80b683446e498f244d0eadfd979ca5d0satok                                            chkPref.setChecked(true);
1309cd11a9aa5ac74ca89432655d019f68d789bc405satok                                            InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
1319cd11a9aa5ac74ca89432655d019f68d789bc405satok                                                    InputMethodAndSubtypeEnabler.this,
1329cd11a9aa5ac74ca89432655d019f68d789bc405satok                                                    mInputMethodProperties, id, true);
1334a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        }
1344a5f889f80b683446e498f244d0eadfd979ca5d0satok
1354a5f889f80b683446e498f244d0eadfd979ca5d0satok                            })
1364a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setNegativeButton(android.R.string.cancel,
1374a5f889f80b683446e498f244d0eadfd979ca5d0satok                                    new DialogInterface.OnClickListener() {
1384a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        public void onClick(DialogInterface dialog, int which) {
1394a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        }
1404a5f889f80b683446e498f244d0eadfd979ca5d0satok
1414a5f889f80b683446e498f244d0eadfd979ca5d0satok                            })
1424a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .create();
1434a5f889f80b683446e498f244d0eadfd979ca5d0satok                } else {
1444a5f889f80b683446e498f244d0eadfd979ca5d0satok                    if (mDialog.isShowing()) {
1454a5f889f80b683446e498f244d0eadfd979ca5d0satok                        mDialog.dismiss();
1464a5f889f80b683446e498f244d0eadfd979ca5d0satok                    }
1474a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1484a5f889f80b683446e498f244d0eadfd979ca5d0satok                mDialog.setMessage(getResources().getString(
1494a5f889f80b683446e498f244d0eadfd979ca5d0satok                        R.string.ime_security_warning,
1504a5f889f80b683446e498f244d0eadfd979ca5d0satok                        selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager())));
1514a5f889f80b683446e498f244d0eadfd979ca5d0satok                mDialog.show();
1524a5f889f80b683446e498f244d0eadfd979ca5d0satok            } else {
1539cd11a9aa5ac74ca89432655d019f68d789bc405satok                InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
1549cd11a9aa5ac74ca89432655d019f68d789bc405satok                        this, mInputMethodProperties, id, false);
1554a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
1564a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
1574a5f889f80b683446e498f244d0eadfd979ca5d0satok        return super.onPreferenceTreeClick(preferenceScreen, preference);
1584a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
1594a5f889f80b683446e498f244d0eadfd979ca5d0satok
1604a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
1614a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onDestroy() {
1624a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onDestroy();
1634a5f889f80b683446e498f244d0eadfd979ca5d0satok        if (mDialog != null) {
1644a5f889f80b683446e498f244d0eadfd979ca5d0satok            mDialog.dismiss();
1654a5f889f80b683446e498f244d0eadfd979ca5d0satok            mDialog = null;
1664a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
1674a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
1684a5f889f80b683446e498f244d0eadfd979ca5d0satok
1694a5f889f80b683446e498f244d0eadfd979ca5d0satok    private void onCreateIMM() {
1704a5f889f80b683446e498f244d0eadfd979ca5d0satok        InputMethodManager imm = (InputMethodManager) getSystemService(
1714a5f889f80b683446e498f244d0eadfd979ca5d0satok                Context.INPUT_METHOD_SERVICE);
1724a5f889f80b683446e498f244d0eadfd979ca5d0satok
1734a5f889f80b683446e498f244d0eadfd979ca5d0satok        // TODO: Change mInputMethodProperties to Map
1744a5f889f80b683446e498f244d0eadfd979ca5d0satok        mInputMethodProperties = imm.getInputMethodList();
1754a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
1764a5f889f80b683446e498f244d0eadfd979ca5d0satok
1774a5f889f80b683446e498f244d0eadfd979ca5d0satok    private PreferenceScreen createPreferenceHierarchy() {
1784a5f889f80b683446e498f244d0eadfd979ca5d0satok        // Root
1794a5f889f80b683446e498f244d0eadfd979ca5d0satok        PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
1804a5f889f80b683446e498f244d0eadfd979ca5d0satok
1814a5f889f80b683446e498f244d0eadfd979ca5d0satok        int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size());
182c88a7ff1efd10374974e45768bde1658cc1d8483satok
1834a5f889f80b683446e498f244d0eadfd979ca5d0satok        for (int i = 0; i < N; ++i) {
184c88a7ff1efd10374974e45768bde1658cc1d8483satok            final InputMethodInfo imi = mInputMethodProperties.get(i);
185c88a7ff1efd10374974e45768bde1658cc1d8483satok            if (imi.getSubtypes().size() <= 1) continue;
1861c58c15e7a84b582b7d4d20c26824cabce80bce9satok            final String imiId = imi.getId();
1871c58c15e7a84b582b7d4d20c26824cabce80bce9satok            // Add this subtype to the list when no IME is specified or when the IME of this
188c88a7ff1efd10374974e45768bde1658cc1d8483satok            // subtype is the specified IME.
189c88a7ff1efd10374974e45768bde1658cc1d8483satok            if (!TextUtils.isEmpty(mInputMethodId) && !mInputMethodId.equals(imiId)) {
190c88a7ff1efd10374974e45768bde1658cc1d8483satok                continue;
191c88a7ff1efd10374974e45768bde1658cc1d8483satok            }
1924a5f889f80b683446e498f244d0eadfd979ca5d0satok            PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(getActivity());
1934a5f889f80b683446e498f244d0eadfd979ca5d0satok            root.addPreference(keyboardSettingsCategory);
1944a5f889f80b683446e498f244d0eadfd979ca5d0satok            PackageManager pm = getPackageManager();
195c88a7ff1efd10374974e45768bde1658cc1d8483satok            CharSequence label = imi.loadLabel(pm);
196c88a7ff1efd10374974e45768bde1658cc1d8483satok
1971c58c15e7a84b582b7d4d20c26824cabce80bce9satok            keyboardSettingsCategory.setTitle(label);
198c88a7ff1efd10374974e45768bde1658cc1d8483satok            keyboardSettingsCategory.setKey(imiId);
1991c58c15e7a84b582b7d4d20c26824cabce80bce9satok            // TODO: Use toggle Preference if images are ready.
2001c58c15e7a84b582b7d4d20c26824cabce80bce9satok            CheckBoxPreference autoCB = new CheckBoxPreference(getActivity());
2011c58c15e7a84b582b7d4d20c26824cabce80bce9satok            autoCB.setTitle(R.string.use_system_language_to_select_input_method_subtypes);
2021c58c15e7a84b582b7d4d20c26824cabce80bce9satok            mSubtypeAutoSelectionCBMap.put(imiId, autoCB);
2031c58c15e7a84b582b7d4d20c26824cabce80bce9satok            keyboardSettingsCategory.addPreference(autoCB);
2041c58c15e7a84b582b7d4d20c26824cabce80bce9satok
2051c58c15e7a84b582b7d4d20c26824cabce80bce9satok            PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(getActivity());
2061c58c15e7a84b582b7d4d20c26824cabce80bce9satok            activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
2071c58c15e7a84b582b7d4d20c26824cabce80bce9satok            root.addPreference(activeInputMethodsCategory);
2084a5f889f80b683446e498f244d0eadfd979ca5d0satok
209c88a7ff1efd10374974e45768bde1658cc1d8483satok            ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
210c88a7ff1efd10374974e45768bde1658cc1d8483satok            ArrayList<Preference> subtypePreferences = new ArrayList<Preference>();
2114a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (subtypes.size() > 0) {
2124a5f889f80b683446e498f244d0eadfd979ca5d0satok                for (InputMethodSubtype subtype: subtypes) {
2134a5f889f80b683446e498f244d0eadfd979ca5d0satok                    CharSequence subtypeLabel;
2144a5f889f80b683446e498f244d0eadfd979ca5d0satok                    int nameResId = subtype.getNameResId();
2154a5f889f80b683446e498f244d0eadfd979ca5d0satok                    if (nameResId != 0) {
216c88a7ff1efd10374974e45768bde1658cc1d8483satok                        subtypeLabel = pm.getText(imi.getPackageName(), nameResId,
217c88a7ff1efd10374974e45768bde1658cc1d8483satok                                imi.getServiceInfo().applicationInfo);
2184a5f889f80b683446e498f244d0eadfd979ca5d0satok                    } else {
2196ea661863daff6907ac7205e12c081b0ad3bdb22satok                        String mode = subtype.getMode();
2204a5f889f80b683446e498f244d0eadfd979ca5d0satok                        CharSequence language = subtype.getLocale();
2214a5f889f80b683446e498f244d0eadfd979ca5d0satok                        subtypeLabel = (mode == null ? "" : mode) + ","
2224a5f889f80b683446e498f244d0eadfd979ca5d0satok                                + (language == null ? "" : language);
2234a5f889f80b683446e498f244d0eadfd979ca5d0satok                    }
2244a5f889f80b683446e498f244d0eadfd979ca5d0satok                    CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity());
225c88a7ff1efd10374974e45768bde1658cc1d8483satok                    chkbxPref.setKey(imiId + subtype.hashCode());
2264a5f889f80b683446e498f244d0eadfd979ca5d0satok                    chkbxPref.setTitle(subtypeLabel);
2271c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    activeInputMethodsCategory.addPreference(chkbxPref);
228c88a7ff1efd10374974e45768bde1658cc1d8483satok                    subtypePreferences.add(chkbxPref);
2294a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
2301c58c15e7a84b582b7d4d20c26824cabce80bce9satok                mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
2314a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2324a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
2334a5f889f80b683446e498f244d0eadfd979ca5d0satok        return root;
2344a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
2351c58c15e7a84b582b7d4d20c26824cabce80bce9satok
2361c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private boolean isNoSubtypesExplicitlySelected(String imiId) {
2371c58c15e7a84b582b7d4d20c26824cabce80bce9satok        boolean allSubtypesOff = true;
2381c58c15e7a84b582b7d4d20c26824cabce80bce9satok        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
2391c58c15e7a84b582b7d4d20c26824cabce80bce9satok        for (Preference subtypePref: subtypePrefs) {
2401c58c15e7a84b582b7d4d20c26824cabce80bce9satok            if (subtypePref instanceof CheckBoxPreference
2411c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    && ((CheckBoxPreference)subtypePref).isChecked()) {
2421c58c15e7a84b582b7d4d20c26824cabce80bce9satok                allSubtypesOff = false;
2431c58c15e7a84b582b7d4d20c26824cabce80bce9satok                break;
2441c58c15e7a84b582b7d4d20c26824cabce80bce9satok            }
2451c58c15e7a84b582b7d4d20c26824cabce80bce9satok        }
2461c58c15e7a84b582b7d4d20c26824cabce80bce9satok        return allSubtypesOff;
2471c58c15e7a84b582b7d4d20c26824cabce80bce9satok    }
2481c58c15e7a84b582b7d4d20c26824cabce80bce9satok
2491c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private void setSubtypeAutoSelectionEnabled(String imiId, boolean autoSelectionEnabled) {
2501c58c15e7a84b582b7d4d20c26824cabce80bce9satok        mSubtypeAutoSelectionCBMap.get(imiId).setChecked(autoSelectionEnabled);
2511c58c15e7a84b582b7d4d20c26824cabce80bce9satok        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
2521c58c15e7a84b582b7d4d20c26824cabce80bce9satok        for (Preference subtypePref: subtypePrefs) {
2531c58c15e7a84b582b7d4d20c26824cabce80bce9satok            if (subtypePref instanceof CheckBoxPreference) {
2541c58c15e7a84b582b7d4d20c26824cabce80bce9satok                // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
2551c58c15e7a84b582b7d4d20c26824cabce80bce9satok                // implicitly checked subtypes. In case of false, all subtype prefs need to be
2561c58c15e7a84b582b7d4d20c26824cabce80bce9satok                // enabled.
2571c58c15e7a84b582b7d4d20c26824cabce80bce9satok                subtypePref.setEnabled(!autoSelectionEnabled);
2581c58c15e7a84b582b7d4d20c26824cabce80bce9satok                if (autoSelectionEnabled) {
2591c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    ((CheckBoxPreference)subtypePref).setChecked(false);
2601c58c15e7a84b582b7d4d20c26824cabce80bce9satok                }
2611c58c15e7a84b582b7d4d20c26824cabce80bce9satok            }
2621c58c15e7a84b582b7d4d20c26824cabce80bce9satok        }
2631c58c15e7a84b582b7d4d20c26824cabce80bce9satok        if (autoSelectionEnabled) {
2641c58c15e7a84b582b7d4d20c26824cabce80bce9satok            InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
2651c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    mInputMethodProperties, mHaveHardKeyboard);
2661c58c15e7a84b582b7d4d20c26824cabce80bce9satok            setCheckedImplicitlyEnabledSubtypes(imiId);
2671c58c15e7a84b582b7d4d20c26824cabce80bce9satok        }
2681c58c15e7a84b582b7d4d20c26824cabce80bce9satok    }
2691c58c15e7a84b582b7d4d20c26824cabce80bce9satok
2701c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private void setCheckedImplicitlyEnabledSubtypes(String targetImiId) {
2711c58c15e7a84b582b7d4d20c26824cabce80bce9satok        updateImplicitlyEnabledSubtypes(targetImiId, true);
2721c58c15e7a84b582b7d4d20c26824cabce80bce9satok    }
2731c58c15e7a84b582b7d4d20c26824cabce80bce9satok
2741c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private void clearImplicitlyEnabledSubtypes(String targetImiId) {
2751c58c15e7a84b582b7d4d20c26824cabce80bce9satok        updateImplicitlyEnabledSubtypes(targetImiId, false);
2761c58c15e7a84b582b7d4d20c26824cabce80bce9satok    }
2771c58c15e7a84b582b7d4d20c26824cabce80bce9satok
2781c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private void updateImplicitlyEnabledSubtypes(String targetImiId, boolean check) {
2791c58c15e7a84b582b7d4d20c26824cabce80bce9satok        // When targetImiId is null, apply to all subtypes of all IMEs
2801c58c15e7a84b582b7d4d20c26824cabce80bce9satok        for (InputMethodInfo imi: mInputMethodProperties) {
2811c58c15e7a84b582b7d4d20c26824cabce80bce9satok            String imiId = imi.getId();
2821c58c15e7a84b582b7d4d20c26824cabce80bce9satok            if (targetImiId != null && !targetImiId.equals(imiId)) continue;
2831c58c15e7a84b582b7d4d20c26824cabce80bce9satok            final CheckBoxPreference autoCB = mSubtypeAutoSelectionCBMap.get(imiId);
2841c58c15e7a84b582b7d4d20c26824cabce80bce9satok            // No need to update implicitly enabled subtypes when the user has unchecked the
2851c58c15e7a84b582b7d4d20c26824cabce80bce9satok            // "subtype auto selection".
2861c58c15e7a84b582b7d4d20c26824cabce80bce9satok            if (autoCB == null || !autoCB.isChecked()) continue;
2871c58c15e7a84b582b7d4d20c26824cabce80bce9satok            final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
2881c58c15e7a84b582b7d4d20c26824cabce80bce9satok            final List<InputMethodSubtype> implicitlyEnabledSubtypes =
2891c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    mImm.getEnabledInputMethodSubtypeList(imi, true);
2901c58c15e7a84b582b7d4d20c26824cabce80bce9satok            if (subtypePrefs == null || implicitlyEnabledSubtypes == null) continue;
2911c58c15e7a84b582b7d4d20c26824cabce80bce9satok            for (Preference subtypePref: subtypePrefs) {
2921c58c15e7a84b582b7d4d20c26824cabce80bce9satok                if (subtypePref instanceof CheckBoxPreference) {
2931c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    CheckBoxPreference cb = (CheckBoxPreference)subtypePref;
2941c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    cb.setChecked(false);
2951c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    if (check) {
2961c58c15e7a84b582b7d4d20c26824cabce80bce9satok                        for (InputMethodSubtype subtype: implicitlyEnabledSubtypes) {
2971c58c15e7a84b582b7d4d20c26824cabce80bce9satok                            String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
2981c58c15e7a84b582b7d4d20c26824cabce80bce9satok                            if (cb.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
2991c58c15e7a84b582b7d4d20c26824cabce80bce9satok                                cb.setChecked(true);
3001c58c15e7a84b582b7d4d20c26824cabce80bce9satok                                break;
3011c58c15e7a84b582b7d4d20c26824cabce80bce9satok                            }
3021c58c15e7a84b582b7d4d20c26824cabce80bce9satok                        }
3031c58c15e7a84b582b7d4d20c26824cabce80bce9satok                    }
3041c58c15e7a84b582b7d4d20c26824cabce80bce9satok                }
3051c58c15e7a84b582b7d4d20c26824cabce80bce9satok            }
3061c58c15e7a84b582b7d4d20c26824cabce80bce9satok        }
3071c58c15e7a84b582b7d4d20c26824cabce80bce9satok    }
3081c58c15e7a84b582b7d4d20c26824cabce80bce9satok
3091c58c15e7a84b582b7d4d20c26824cabce80bce9satok    private void updateAutoSelectionCB() {
3101c58c15e7a84b582b7d4d20c26824cabce80bce9satok        for (String imiId: mInputMethodAndSubtypePrefsMap.keySet()) {
3111c58c15e7a84b582b7d4d20c26824cabce80bce9satok            setSubtypeAutoSelectionEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
3121c58c15e7a84b582b7d4d20c26824cabce80bce9satok        }
3131c58c15e7a84b582b7d4d20c26824cabce80bce9satok        setCheckedImplicitlyEnabledSubtypes(null);
3141c58c15e7a84b582b7d4d20c26824cabce80bce9satok    }
3154a5f889f80b683446e498f244d0eadfd979ca5d0satok}
316