InputMethodAndSubtypeEnabler.java revision 4a5f889f80b683446e498f244d0eadfd979ca5d0
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
174a5f889f80b683446e498f244d0eadfd979ca5d0satokpackage com.android.settings;
184a5f889f80b683446e498f244d0eadfd979ca5d0satok
194a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.app.AlertDialog;
204a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.Context;
214a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.DialogInterface;
224a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.pm.ApplicationInfo;
234a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.pm.PackageManager;
244a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.res.Configuration;
254a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.os.Bundle;
264a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.CheckBoxPreference;
274a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.Preference;
284a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceActivity;
294a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceCategory;
304a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceScreen;
314a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.provider.Settings;
324a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.text.TextUtils;
334a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodInfo;
344a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodManager;
354a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodSubtype;
364a5f889f80b683446e498f244d0eadfd979ca5d0satok
374a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.ArrayList;
384a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.HashSet;
394a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.List;
404a5f889f80b683446e498f244d0eadfd979ca5d0satok
414a5f889f80b683446e498f244d0eadfd979ca5d0satokpublic class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
424a5f889f80b683446e498f244d0eadfd979ca5d0satok
434a5f889f80b683446e498f244d0eadfd979ca5d0satok    private boolean mHaveHardKeyboard;
444a5f889f80b683446e498f244d0eadfd979ca5d0satok
454a5f889f80b683446e498f244d0eadfd979ca5d0satok    private List<InputMethodInfo> mInputMethodProperties;
464a5f889f80b683446e498f244d0eadfd979ca5d0satok
474a5f889f80b683446e498f244d0eadfd979ca5d0satok    private final TextUtils.SimpleStringSplitter mStringColonSplitter
484a5f889f80b683446e498f244d0eadfd979ca5d0satok            = new TextUtils.SimpleStringSplitter(':');
494a5f889f80b683446e498f244d0eadfd979ca5d0satok
504a5f889f80b683446e498f244d0eadfd979ca5d0satok    private String mLastInputMethodId;
514a5f889f80b683446e498f244d0eadfd979ca5d0satok    private String mLastTickedInputMethodId;
524a5f889f80b683446e498f244d0eadfd979ca5d0satok
534a5f889f80b683446e498f244d0eadfd979ca5d0satok    private AlertDialog mDialog = null;
544a5f889f80b683446e498f244d0eadfd979ca5d0satok
554a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
564a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onCreate(Bundle icicle) {
574a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onCreate(icicle);
584a5f889f80b683446e498f244d0eadfd979ca5d0satok        Configuration config = getResources().getConfiguration();
594a5f889f80b683446e498f244d0eadfd979ca5d0satok        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
604a5f889f80b683446e498f244d0eadfd979ca5d0satok        onCreateIMM();
614a5f889f80b683446e498f244d0eadfd979ca5d0satok        setPreferenceScreen(createPreferenceHierarchy());
624a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
634a5f889f80b683446e498f244d0eadfd979ca5d0satok
644a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
654a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onResume() {
664a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onResume();
674a5f889f80b683446e498f244d0eadfd979ca5d0satok        loadInputMethodSubtypeList();
684a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
694a5f889f80b683446e498f244d0eadfd979ca5d0satok
704a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
714a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onPause() {
724a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onPause();
734a5f889f80b683446e498f244d0eadfd979ca5d0satok        saveInputMethodSubtypeList();
744a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
754a5f889f80b683446e498f244d0eadfd979ca5d0satok
764a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
774a5f889f80b683446e498f244d0eadfd979ca5d0satok    public boolean onPreferenceTreeClick(
784a5f889f80b683446e498f244d0eadfd979ca5d0satok            PreferenceScreen preferenceScreen, Preference preference) {
794a5f889f80b683446e498f244d0eadfd979ca5d0satok
804a5f889f80b683446e498f244d0eadfd979ca5d0satok        if (preference instanceof CheckBoxPreference) {
814a5f889f80b683446e498f244d0eadfd979ca5d0satok            final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
824a5f889f80b683446e498f244d0eadfd979ca5d0satok            final String id = chkPref.getKey();
834a5f889f80b683446e498f244d0eadfd979ca5d0satok            // TODO: Check subtype or not here
844a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (chkPref.isChecked()) {
854a5f889f80b683446e498f244d0eadfd979ca5d0satok                InputMethodInfo selImi = null;
864a5f889f80b683446e498f244d0eadfd979ca5d0satok                final int N = mInputMethodProperties.size();
874a5f889f80b683446e498f244d0eadfd979ca5d0satok                for (int i = 0; i < N; i++) {
884a5f889f80b683446e498f244d0eadfd979ca5d0satok                    InputMethodInfo imi = mInputMethodProperties.get(i);
894a5f889f80b683446e498f244d0eadfd979ca5d0satok                    if (id.equals(imi.getId())) {
904a5f889f80b683446e498f244d0eadfd979ca5d0satok                        selImi = imi;
914a5f889f80b683446e498f244d0eadfd979ca5d0satok                        if (isSystemIme(imi)) {
924a5f889f80b683446e498f244d0eadfd979ca5d0satok                            setSubtypesPreferenceEnabled(id, true);
934a5f889f80b683446e498f244d0eadfd979ca5d0satok                            // This is a built-in IME, so no need to warn.
944a5f889f80b683446e498f244d0eadfd979ca5d0satok                            mLastTickedInputMethodId = id;
954a5f889f80b683446e498f244d0eadfd979ca5d0satok                            return super.onPreferenceTreeClick(preferenceScreen, preference);
964a5f889f80b683446e498f244d0eadfd979ca5d0satok                        }
974a5f889f80b683446e498f244d0eadfd979ca5d0satok                        break;
984a5f889f80b683446e498f244d0eadfd979ca5d0satok                    }
994a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1004a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (selImi == null) {
1014a5f889f80b683446e498f244d0eadfd979ca5d0satok                    return super.onPreferenceTreeClick(preferenceScreen, preference);
1024a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1034a5f889f80b683446e498f244d0eadfd979ca5d0satok                chkPref.setChecked(false);
1044a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (mDialog == null) {
1054a5f889f80b683446e498f244d0eadfd979ca5d0satok                    mDialog = (new AlertDialog.Builder(getActivity()))
1064a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setTitle(android.R.string.dialog_alert_title)
1074a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setIcon(android.R.drawable.ic_dialog_alert)
1084a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setCancelable(true)
1094a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setPositiveButton(android.R.string.ok,
1104a5f889f80b683446e498f244d0eadfd979ca5d0satok                                    new DialogInterface.OnClickListener() {
1114a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        public void onClick(DialogInterface dialog, int which) {
1124a5f889f80b683446e498f244d0eadfd979ca5d0satok                                            chkPref.setChecked(true);
1134a5f889f80b683446e498f244d0eadfd979ca5d0satok                                            setSubtypesPreferenceEnabled(id, true);
1144a5f889f80b683446e498f244d0eadfd979ca5d0satok                                            mLastTickedInputMethodId = id;
1154a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        }
1164a5f889f80b683446e498f244d0eadfd979ca5d0satok
1174a5f889f80b683446e498f244d0eadfd979ca5d0satok                            })
1184a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .setNegativeButton(android.R.string.cancel,
1194a5f889f80b683446e498f244d0eadfd979ca5d0satok                                    new DialogInterface.OnClickListener() {
1204a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        public void onClick(DialogInterface dialog, int which) {
1214a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        }
1224a5f889f80b683446e498f244d0eadfd979ca5d0satok
1234a5f889f80b683446e498f244d0eadfd979ca5d0satok                            })
1244a5f889f80b683446e498f244d0eadfd979ca5d0satok                            .create();
1254a5f889f80b683446e498f244d0eadfd979ca5d0satok                } else {
1264a5f889f80b683446e498f244d0eadfd979ca5d0satok                    if (mDialog.isShowing()) {
1274a5f889f80b683446e498f244d0eadfd979ca5d0satok                        mDialog.dismiss();
1284a5f889f80b683446e498f244d0eadfd979ca5d0satok                    }
1294a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1304a5f889f80b683446e498f244d0eadfd979ca5d0satok                mDialog.setMessage(getResources().getString(
1314a5f889f80b683446e498f244d0eadfd979ca5d0satok                        R.string.ime_security_warning,
1324a5f889f80b683446e498f244d0eadfd979ca5d0satok                        selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager())));
1334a5f889f80b683446e498f244d0eadfd979ca5d0satok                mDialog.show();
1344a5f889f80b683446e498f244d0eadfd979ca5d0satok            } else {
1354a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (id.equals(mLastTickedInputMethodId)) {
1364a5f889f80b683446e498f244d0eadfd979ca5d0satok                    mLastTickedInputMethodId = null;
1374a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
1384a5f889f80b683446e498f244d0eadfd979ca5d0satok                setSubtypesPreferenceEnabled(id, false);
1394a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
1404a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
1414a5f889f80b683446e498f244d0eadfd979ca5d0satok        return super.onPreferenceTreeClick(preferenceScreen, preference);
1424a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
1434a5f889f80b683446e498f244d0eadfd979ca5d0satok
1444a5f889f80b683446e498f244d0eadfd979ca5d0satok    @Override
1454a5f889f80b683446e498f244d0eadfd979ca5d0satok    public void onDestroy() {
1464a5f889f80b683446e498f244d0eadfd979ca5d0satok        super.onDestroy();
1474a5f889f80b683446e498f244d0eadfd979ca5d0satok        if (mDialog != null) {
1484a5f889f80b683446e498f244d0eadfd979ca5d0satok            mDialog.dismiss();
1494a5f889f80b683446e498f244d0eadfd979ca5d0satok            mDialog = null;
1504a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
1514a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
1524a5f889f80b683446e498f244d0eadfd979ca5d0satok
1534a5f889f80b683446e498f244d0eadfd979ca5d0satok    private void onCreateIMM() {
1544a5f889f80b683446e498f244d0eadfd979ca5d0satok        InputMethodManager imm = (InputMethodManager) getSystemService(
1554a5f889f80b683446e498f244d0eadfd979ca5d0satok                Context.INPUT_METHOD_SERVICE);
1564a5f889f80b683446e498f244d0eadfd979ca5d0satok
1574a5f889f80b683446e498f244d0eadfd979ca5d0satok        // TODO: Change mInputMethodProperties to Map
1584a5f889f80b683446e498f244d0eadfd979ca5d0satok        mInputMethodProperties = imm.getInputMethodList();
1594a5f889f80b683446e498f244d0eadfd979ca5d0satok
1604a5f889f80b683446e498f244d0eadfd979ca5d0satok        mLastInputMethodId = Settings.Secure.getString(getContentResolver(),
1614a5f889f80b683446e498f244d0eadfd979ca5d0satok                Settings.Secure.DEFAULT_INPUT_METHOD);
1624a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
1634a5f889f80b683446e498f244d0eadfd979ca5d0satok
1644a5f889f80b683446e498f244d0eadfd979ca5d0satok    private PreferenceScreen createPreferenceHierarchy() {
1654a5f889f80b683446e498f244d0eadfd979ca5d0satok        // Root
1664a5f889f80b683446e498f244d0eadfd979ca5d0satok        PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
1674a5f889f80b683446e498f244d0eadfd979ca5d0satok
1684a5f889f80b683446e498f244d0eadfd979ca5d0satok        int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size());
1694a5f889f80b683446e498f244d0eadfd979ca5d0satok        // TODO: Use iterator.
1704a5f889f80b683446e498f244d0eadfd979ca5d0satok        for (int i = 0; i < N; ++i) {
1714a5f889f80b683446e498f244d0eadfd979ca5d0satok            PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(getActivity());
1724a5f889f80b683446e498f244d0eadfd979ca5d0satok            root.addPreference(keyboardSettingsCategory);
1734a5f889f80b683446e498f244d0eadfd979ca5d0satok            InputMethodInfo property = mInputMethodProperties.get(i);
1744a5f889f80b683446e498f244d0eadfd979ca5d0satok            String prefKey = property.getId();
1754a5f889f80b683446e498f244d0eadfd979ca5d0satok
1764a5f889f80b683446e498f244d0eadfd979ca5d0satok            PackageManager pm = getPackageManager();
1774a5f889f80b683446e498f244d0eadfd979ca5d0satok            CharSequence label = property.loadLabel(pm);
1784a5f889f80b683446e498f244d0eadfd979ca5d0satok            boolean systemIME = isSystemIme(property);
1794a5f889f80b683446e498f244d0eadfd979ca5d0satok
1804a5f889f80b683446e498f244d0eadfd979ca5d0satok            keyboardSettingsCategory.setTitle(label);
1814a5f889f80b683446e498f244d0eadfd979ca5d0satok
1824a5f889f80b683446e498f244d0eadfd979ca5d0satok            // Add a check box.
1834a5f889f80b683446e498f244d0eadfd979ca5d0satok            // Don't show the toggle if it's the only keyboard in the system, or it's a system IME.
1844a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (mHaveHardKeyboard || (N > 1 && !systemIME)) {
1854a5f889f80b683446e498f244d0eadfd979ca5d0satok                CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity());
1864a5f889f80b683446e498f244d0eadfd979ca5d0satok                chkbxPref.setKey(prefKey);
1874a5f889f80b683446e498f244d0eadfd979ca5d0satok                chkbxPref.setTitle(label);
1884a5f889f80b683446e498f244d0eadfd979ca5d0satok                keyboardSettingsCategory.addPreference(chkbxPref);
1894a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
1904a5f889f80b683446e498f244d0eadfd979ca5d0satok
1914a5f889f80b683446e498f244d0eadfd979ca5d0satok            ArrayList<InputMethodSubtype> subtypes = property.getSubtypes();
1924a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (subtypes.size() > 0) {
1934a5f889f80b683446e498f244d0eadfd979ca5d0satok                PreferenceCategory subtypesCategory = new PreferenceCategory(getActivity());
1944a5f889f80b683446e498f244d0eadfd979ca5d0satok                subtypesCategory.setTitle(getResources().getString(
1954a5f889f80b683446e498f244d0eadfd979ca5d0satok                        R.string.input_methods_and_subtype_enabler_title_format, label));
1964a5f889f80b683446e498f244d0eadfd979ca5d0satok                root.addPreference(subtypesCategory);
1974a5f889f80b683446e498f244d0eadfd979ca5d0satok                for (InputMethodSubtype subtype: subtypes) {
1984a5f889f80b683446e498f244d0eadfd979ca5d0satok                    CharSequence subtypeLabel;
1994a5f889f80b683446e498f244d0eadfd979ca5d0satok                    int nameResId = subtype.getNameResId();
2004a5f889f80b683446e498f244d0eadfd979ca5d0satok                    if (nameResId != 0) {
2014a5f889f80b683446e498f244d0eadfd979ca5d0satok                        subtypeLabel = pm.getText(property.getPackageName(), nameResId,
2024a5f889f80b683446e498f244d0eadfd979ca5d0satok                                property.getServiceInfo().applicationInfo);
2034a5f889f80b683446e498f244d0eadfd979ca5d0satok                    } else {
2044a5f889f80b683446e498f244d0eadfd979ca5d0satok                        int modeResId = subtype.getModeResId();
2054a5f889f80b683446e498f244d0eadfd979ca5d0satok                        CharSequence language = subtype.getLocale();
2064a5f889f80b683446e498f244d0eadfd979ca5d0satok                        CharSequence mode = modeResId == 0 ? null
2074a5f889f80b683446e498f244d0eadfd979ca5d0satok                                : pm.getText(property.getPackageName(), modeResId,
2084a5f889f80b683446e498f244d0eadfd979ca5d0satok                                        property.getServiceInfo().applicationInfo);
2094a5f889f80b683446e498f244d0eadfd979ca5d0satok                        // TODO: Use more friendly Title and UI
2104a5f889f80b683446e498f244d0eadfd979ca5d0satok                        subtypeLabel = (mode == null ? "" : mode) + ","
2114a5f889f80b683446e498f244d0eadfd979ca5d0satok                                + (language == null ? "" : language);
2124a5f889f80b683446e498f244d0eadfd979ca5d0satok                    }
2134a5f889f80b683446e498f244d0eadfd979ca5d0satok                    CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity());
2144a5f889f80b683446e498f244d0eadfd979ca5d0satok                    chkbxPref.setKey(prefKey + subtype.hashCode());
2154a5f889f80b683446e498f244d0eadfd979ca5d0satok                    chkbxPref.setTitle(subtypeLabel);
2164a5f889f80b683446e498f244d0eadfd979ca5d0satok                    chkbxPref.setSummary(label);
2174a5f889f80b683446e498f244d0eadfd979ca5d0satok                    subtypesCategory.addPreference(chkbxPref);
2184a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
2194a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2204a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
2214a5f889f80b683446e498f244d0eadfd979ca5d0satok        return root;
2224a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
2234a5f889f80b683446e498f244d0eadfd979ca5d0satok
2244a5f889f80b683446e498f244d0eadfd979ca5d0satok    private void loadInputMethodSubtypeList() {
2254a5f889f80b683446e498f244d0eadfd979ca5d0satok        final HashSet<String> enabled = new HashSet<String>();
2264a5f889f80b683446e498f244d0eadfd979ca5d0satok        String enabledStr = Settings.Secure.getString(getContentResolver(),
2274a5f889f80b683446e498f244d0eadfd979ca5d0satok                Settings.Secure.ENABLED_INPUT_METHODS);
2284a5f889f80b683446e498f244d0eadfd979ca5d0satok        if (enabledStr != null) {
2294a5f889f80b683446e498f244d0eadfd979ca5d0satok            final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
2304a5f889f80b683446e498f244d0eadfd979ca5d0satok            splitter.setString(enabledStr);
2314a5f889f80b683446e498f244d0eadfd979ca5d0satok            while (splitter.hasNext()) {
2324a5f889f80b683446e498f244d0eadfd979ca5d0satok                enabled.add(splitter.next());
2334a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2344a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
2354a5f889f80b683446e498f244d0eadfd979ca5d0satok
2364a5f889f80b683446e498f244d0eadfd979ca5d0satok        // Update the statuses of the Check Boxes.
2374a5f889f80b683446e498f244d0eadfd979ca5d0satok        int N = mInputMethodProperties.size();
2384a5f889f80b683446e498f244d0eadfd979ca5d0satok        // TODO: Use iterator.
2394a5f889f80b683446e498f244d0eadfd979ca5d0satok        for (int i = 0; i < N; ++i) {
2404a5f889f80b683446e498f244d0eadfd979ca5d0satok            final String id = mInputMethodProperties.get(i).getId();
2414a5f889f80b683446e498f244d0eadfd979ca5d0satok            CheckBoxPreference pref = (CheckBoxPreference) findPreference(
2424a5f889f80b683446e498f244d0eadfd979ca5d0satok                    mInputMethodProperties.get(i).getId());
2434a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (pref != null) {
2444a5f889f80b683446e498f244d0eadfd979ca5d0satok                boolean isEnabled = enabled.contains(id);
2454a5f889f80b683446e498f244d0eadfd979ca5d0satok                pref.setChecked(isEnabled);
2464a5f889f80b683446e498f244d0eadfd979ca5d0satok                setSubtypesPreferenceEnabled(id, isEnabled);
2474a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2484a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
2494a5f889f80b683446e498f244d0eadfd979ca5d0satok        mLastTickedInputMethodId = null;
2504a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
2514a5f889f80b683446e498f244d0eadfd979ca5d0satok
2524a5f889f80b683446e498f244d0eadfd979ca5d0satok    private void saveInputMethodSubtypeList() {
2534a5f889f80b683446e498f244d0eadfd979ca5d0satok        StringBuilder builder = new StringBuilder();
2544a5f889f80b683446e498f244d0eadfd979ca5d0satok        StringBuilder disabledSysImes = new StringBuilder();
2554a5f889f80b683446e498f244d0eadfd979ca5d0satok
2564a5f889f80b683446e498f244d0eadfd979ca5d0satok        int firstEnabled = -1;
2574a5f889f80b683446e498f244d0eadfd979ca5d0satok        int N = mInputMethodProperties.size();
2584a5f889f80b683446e498f244d0eadfd979ca5d0satok        for (int i = 0; i < N; ++i) {
2594a5f889f80b683446e498f244d0eadfd979ca5d0satok            final InputMethodInfo property = mInputMethodProperties.get(i);
2604a5f889f80b683446e498f244d0eadfd979ca5d0satok            final String id = property.getId();
2614a5f889f80b683446e498f244d0eadfd979ca5d0satok            CheckBoxPreference pref = (CheckBoxPreference) findPreference(id);
2624a5f889f80b683446e498f244d0eadfd979ca5d0satok            boolean currentInputMethod = id.equals(mLastInputMethodId);
2634a5f889f80b683446e498f244d0eadfd979ca5d0satok            boolean systemIme = isSystemIme(property);
2644a5f889f80b683446e498f244d0eadfd979ca5d0satok            // TODO: Append subtypes by using the separator ";"
2654a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (((N == 1 || systemIme) && !mHaveHardKeyboard)
2664a5f889f80b683446e498f244d0eadfd979ca5d0satok                    || (pref != null && pref.isChecked())) {
2674a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (builder.length() > 0) builder.append(':');
2684a5f889f80b683446e498f244d0eadfd979ca5d0satok                builder.append(id);
2694a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (firstEnabled < 0) {
2704a5f889f80b683446e498f244d0eadfd979ca5d0satok                    firstEnabled = i;
2714a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
2724a5f889f80b683446e498f244d0eadfd979ca5d0satok            } else if (currentInputMethod) {
2734a5f889f80b683446e498f244d0eadfd979ca5d0satok                mLastInputMethodId = mLastTickedInputMethodId;
2744a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2754a5f889f80b683446e498f244d0eadfd979ca5d0satok            // If it's a disabled system ime, add it to the disabled list so that it
2764a5f889f80b683446e498f244d0eadfd979ca5d0satok            // doesn't get enabled automatically on any changes to the package list
2774a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (pref != null && !pref.isChecked() && systemIme && mHaveHardKeyboard) {
2784a5f889f80b683446e498f244d0eadfd979ca5d0satok                if (disabledSysImes.length() > 0) disabledSysImes.append(":");
2794a5f889f80b683446e498f244d0eadfd979ca5d0satok                disabledSysImes.append(id);
2804a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2814a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
2824a5f889f80b683446e498f244d0eadfd979ca5d0satok
2834a5f889f80b683446e498f244d0eadfd979ca5d0satok        // If the last input method is unset, set it as the first enabled one.
2844a5f889f80b683446e498f244d0eadfd979ca5d0satok        if (TextUtils.isEmpty(mLastInputMethodId)) {
2854a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (firstEnabled >= 0) {
2864a5f889f80b683446e498f244d0eadfd979ca5d0satok                mLastInputMethodId = mInputMethodProperties.get(firstEnabled).getId();
2874a5f889f80b683446e498f244d0eadfd979ca5d0satok            } else {
2884a5f889f80b683446e498f244d0eadfd979ca5d0satok                mLastInputMethodId = null;
2894a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
2904a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
2914a5f889f80b683446e498f244d0eadfd979ca5d0satok
2924a5f889f80b683446e498f244d0eadfd979ca5d0satok        Settings.Secure.putString(getContentResolver(),
2934a5f889f80b683446e498f244d0eadfd979ca5d0satok                Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
2944a5f889f80b683446e498f244d0eadfd979ca5d0satok        Settings.Secure.putString(getContentResolver(),
2954a5f889f80b683446e498f244d0eadfd979ca5d0satok                Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, disabledSysImes.toString());
2964a5f889f80b683446e498f244d0eadfd979ca5d0satok        Settings.Secure.putString(getContentResolver(),
2974a5f889f80b683446e498f244d0eadfd979ca5d0satok                Settings.Secure.DEFAULT_INPUT_METHOD,
2984a5f889f80b683446e498f244d0eadfd979ca5d0satok                mLastInputMethodId != null ? mLastInputMethodId : "");
2994a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
3004a5f889f80b683446e498f244d0eadfd979ca5d0satok
3014a5f889f80b683446e498f244d0eadfd979ca5d0satok    private void setSubtypesPreferenceEnabled(String id, boolean enabled) {
3024a5f889f80b683446e498f244d0eadfd979ca5d0satok        PreferenceScreen preferenceScreen = getPreferenceScreen();
3034a5f889f80b683446e498f244d0eadfd979ca5d0satok        final int N = mInputMethodProperties.size();
3044a5f889f80b683446e498f244d0eadfd979ca5d0satok        // TODO: Use iterator.
3054a5f889f80b683446e498f244d0eadfd979ca5d0satok        for (int i = 0; i < N; i++) {
3064a5f889f80b683446e498f244d0eadfd979ca5d0satok            InputMethodInfo imi = mInputMethodProperties.get(i);
3074a5f889f80b683446e498f244d0eadfd979ca5d0satok            if (id.equals(imi.getId())) {
3084a5f889f80b683446e498f244d0eadfd979ca5d0satok                for (InputMethodSubtype subtype: imi.getSubtypes()) {
3094a5f889f80b683446e498f244d0eadfd979ca5d0satok                    preferenceScreen.findPreference(id + subtype.hashCode()).setEnabled(enabled);
3104a5f889f80b683446e498f244d0eadfd979ca5d0satok                }
3114a5f889f80b683446e498f244d0eadfd979ca5d0satok            }
3124a5f889f80b683446e498f244d0eadfd979ca5d0satok        }
3134a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
3144a5f889f80b683446e498f244d0eadfd979ca5d0satok
3154a5f889f80b683446e498f244d0eadfd979ca5d0satok    private boolean isSystemIme(InputMethodInfo property) {
3164a5f889f80b683446e498f244d0eadfd979ca5d0satok        return (property.getServiceInfo().applicationInfo.flags
3174a5f889f80b683446e498f244d0eadfd979ca5d0satok                & ApplicationInfo.FLAG_SYSTEM) != 0;
3184a5f889f80b683446e498f244d0eadfd979ca5d0satok    }
3194a5f889f80b683446e498f244d0eadfd979ca5d0satok}
320