InputMethodAndSubtypeEnabler.java revision 3460a2683ca820d8d7d184bc1e98241ea3986a4a
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 194a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.app.AlertDialog; 204a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.Context; 214a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.DialogInterface; 225e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satokimport android.content.Intent; 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.PreferenceCategory; 294a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceScreen; 30c88a7ff1efd10374974e45768bde1658cc1d8483satokimport android.text.TextUtils; 314a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodInfo; 324a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodManager; 334a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodSubtype; 344a5f889f80b683446e498f244d0eadfd979ca5d0satok 3555aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport com.android.internal.inputmethod.InputMethodUtils; 3655aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport com.android.settings.R; 3755aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport com.android.settings.SettingsPreferenceFragment; 3855aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaoka 39ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataokaimport java.text.Collator; 404a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.ArrayList; 41ae70ee49492bd89c949946562b43a75f3c81b0adsatokimport java.util.Collections; 4255aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport java.util.Comparator; 43c88a7ff1efd10374974e45768bde1658cc1d8483satokimport java.util.HashMap; 444a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.List; 454a5f889f80b683446e498f244d0eadfd979ca5d0satok 464a5f889f80b683446e498f244d0eadfd979ca5d0satokpublic class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment { 47c88a7ff1efd10374974e45768bde1658cc1d8483satok private boolean mHaveHardKeyboard; 48989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private final HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap = 49d2dd7d33c9206f7aa29abbff48119d0f86ddfc36Tadashi G. Takaoka new HashMap<>(); 50989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private final HashMap<String, CheckBoxPreference> mAutoSelectionPrefsMap = new HashMap<>(); 511c58c15e7a84b582b7d4d20c26824cabce80bce9satok private InputMethodManager mImm; 5272c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka // TODO: Change mInputMethodInfoList to Map 5372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka private List<InputMethodInfo> mInputMethodInfoList; 54989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private Collator mCollator; 55989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private AlertDialog mDialog = null; 564a5f889f80b683446e498f244d0eadfd979ca5d0satok 574a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 5872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka public void onCreate(final Bundle icicle) { 594a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onCreate(icicle); 601c58c15e7a84b582b7d4d20c26824cabce80bce9satok mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 61ae70ee49492bd89c949946562b43a75f3c81b0adsatok final Configuration config = getResources().getConfiguration(); 624a5f889f80b683446e498f244d0eadfd979ca5d0satok mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); 63649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa 64649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // Input method id should be available from an Intent when this preference is launched as a 65649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available 66649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // from a preference argument when the preference is launched as a part of the other 67649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // Activity (like a right pane of 2-pane Settings app) 68fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String targetImi = getStringExtraFromIntentOrArguments( 699f7320132b7a5e7def378ae754c8c708759a8670Tadashi G. Takaoka android.provider.Settings.EXTRA_INPUT_METHOD_ID); 70649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa 7172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka mInputMethodInfoList = mImm.getInputMethodList(); 72989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka mCollator = Collator.getInstance(); 73fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka 74fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity()); 75fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final int imiCount = mInputMethodInfoList.size(); 76fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (int index = 0; index < imiCount; ++index) { 77fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final InputMethodInfo imi = mInputMethodInfoList.get(index); 78fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Add subtype preferences of this IME when it is specified or no IME is specified. 79fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) { 80fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka addInputMethodSubtypePreferences(imi, root); 81fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 82fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 83fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka setPreferenceScreen(root); 844a5f889f80b683446e498f244d0eadfd979ca5d0satok } 854a5f889f80b683446e498f244d0eadfd979ca5d0satok 8672c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka private String getStringExtraFromIntentOrArguments(final String name) { 8772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final Intent intent = getActivity().getIntent(); 8872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final String fromIntent = intent.getStringExtra(name); 8972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka if (fromIntent != null) { 9072c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka return fromIntent; 9172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 9272c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final Bundle arguments = getArguments(); 9372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka return (arguments == null) ? null : arguments.getString(name); 9472c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 9572c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka 964a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 9772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka public void onActivityCreated(final Bundle icicle) { 9816c3e74d72ec2d18aff007cb88fcf02995918a90satok super.onActivityCreated(icicle); 9972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final String title = getStringExtraFromIntentOrArguments(Intent.EXTRA_TITLE); 10072c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 10172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka getActivity().setTitle(title); 10216c3e74d72ec2d18aff007cb88fcf02995918a90satok } 10316c3e74d72ec2d18aff007cb88fcf02995918a90satok } 10416c3e74d72ec2d18aff007cb88fcf02995918a90satok 10516c3e74d72ec2d18aff007cb88fcf02995918a90satok @Override 1064a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onResume() { 1074a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onResume(); 108cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka // Refresh internal states in mInputMethodSettingValues to keep the latest 109cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka // "InputMethodInfo"s and "InputMethodSubtype"s 110cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka InputMethodSettingValuesWrapper 111cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka .getInstance(getActivity()).refreshAllInputMethodAndSubtypes(); 1120417e4094713c5f4dac700b645000d0959bf62fasatok InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( 11372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka this, getContentResolver(), mInputMethodInfoList, mInputMethodAndSubtypePrefsMap); 114989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateAutoSelectionPreferences(); 1154a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1164a5f889f80b683446e498f244d0eadfd979ca5d0satok 1174a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 1184a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onPause() { 1194a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onPause(); 1201c58c15e7a84b582b7d4d20c26824cabce80bce9satok // Clear all subtypes of all IMEs to make sure 121989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateImplicitlyEnabledSubtypes(null /* targetImiId */, false /* check */); 1220417e4094713c5f4dac700b645000d0959bf62fasatok InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), 12372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka mInputMethodInfoList, mHaveHardKeyboard); 1244a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1254a5f889f80b683446e498f244d0eadfd979ca5d0satok 126fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // TODO: Stop overriding this method. Instead start using {@link OnPreferenceChangedListener}. 1274a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 12872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka public boolean onPreferenceTreeClick(final PreferenceScreen preferenceScreen, 12972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final Preference preference) { 130fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (!(preference instanceof CheckBoxPreference)) { 131fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return super.onPreferenceTreeClick(preferenceScreen, preference); 132fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 133fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final CheckBoxPreference chkPref = (CheckBoxPreference) preference; 1344a5f889f80b683446e498f244d0eadfd979ca5d0satok 135fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (final String imiId : mAutoSelectionPrefsMap.keySet()) { 136fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (mAutoSelectionPrefsMap.get(imiId) == chkPref) { 137fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // We look for the first preference item in subtype enabler. The first item is used 138fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // for turning on/off subtype auto selection. We are in the subtype enabler and 139fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // trying selecting subtypes automatically. 140fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka setAutoSelectionSubtypesEnabled(imiId, chkPref.isChecked()); 141fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return super.onPreferenceTreeClick(preferenceScreen, preference); 1421c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 143fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 1441c58c15e7a84b582b7d4d20c26824cabce80bce9satok 145fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String id = chkPref.getKey(); 146fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Turns off a subtype. 147fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (!chkPref.isChecked()) { 148fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // TODO: Because no preference on this screen has {@link InputMethodInfo} id as a key, 149fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // the following setSubtypesPreferenceEnabled call is effectively no-operation and 150fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // can be removed. 151fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled( 152fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka this, mInputMethodInfoList, id, false); 153fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka updateAutoSelectionPreferences(); 154fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return super.onPreferenceTreeClick(preferenceScreen, preference); 155fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 1564a5f889f80b683446e498f244d0eadfd979ca5d0satok 157fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Turns on a subtype. 158fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final InputMethodInfo imi = getInputMethodInfoById(id); 159fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // TODO: Because no preference on this screen has {@link InputMethodInfo} id as a key, 160fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // <code>imi</code> is always null and the following code can be removed. 161fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (imi == null) { 162fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return super.onPreferenceTreeClick(preferenceScreen, preference); 163fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 164fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Turns on a system IME's subtype. 165fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (InputMethodUtils.isSystemIme(imi)) { 166fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled( 167fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka this, mInputMethodInfoList, id, true); 168fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // This is a built-in IME, so no need to warn. 169fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return super.onPreferenceTreeClick(preferenceScreen, preference); 170fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 171fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Turns on a 3rd party IME's subtype. 172fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Turns off a subtype before showing a security warning dialog. 173fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka chkPref.setChecked(false); 174fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (mDialog != null && mDialog.isShowing()) { 175fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mDialog.dismiss(); 176fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 177fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 178fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka builder.setCancelable(true); 179fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka builder.setTitle(android.R.string.dialog_alert_title); 180fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final CharSequence label = imi.getServiceInfo().applicationInfo 181fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka .loadLabel(getPackageManager()); 182fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka builder.setMessage(getString(R.string.ime_security_warning, label)); 183fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 184fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka @Override 185fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka public void onClick(final DialogInterface dialog, final int which) { 186fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // The user explicitly enable the subtype. 187fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka chkPref.setChecked(true); 1889cd11a9aa5ac74ca89432655d019f68d789bc405satok InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled( 189fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka InputMethodAndSubtypeEnabler.this, mInputMethodInfoList, id, true); 1904a5f889f80b683446e498f244d0eadfd979ca5d0satok } 191fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka }); 192fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 193fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka @Override 194fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka public void onClick(final DialogInterface dialog, final int which) {} 195fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka }); 196fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mDialog = builder.create(); 197fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mDialog.show(); 1984a5f889f80b683446e498f244d0eadfd979ca5d0satok return super.onPreferenceTreeClick(preferenceScreen, preference); 1994a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2004a5f889f80b683446e498f244d0eadfd979ca5d0satok 201989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private InputMethodInfo getInputMethodInfoById(final String imiId) { 202989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka final int imiCount = mInputMethodInfoList.size(); 203989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka for (int index = 0; index < imiCount; ++index) { 204989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka final InputMethodInfo imi = mInputMethodInfoList.get(index); 205989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka if (imi.getId().equals(imiId)) { 206989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka return imi; 207989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka } 208989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka } 209989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka return null; 210989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka } 211989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka 2124a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 2134a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onDestroy() { 2144a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onDestroy(); 2154a5f889f80b683446e498f244d0eadfd979ca5d0satok if (mDialog != null) { 2164a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog.dismiss(); 2174a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog = null; 2184a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2194a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2204a5f889f80b683446e498f244d0eadfd979ca5d0satok 221fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka private void addInputMethodSubtypePreferences(final InputMethodInfo imi, 222fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceScreen root) { 223f0ae329740eb66663b6f099ca24a13ea7572418csatok final Context context = getActivity(); 224fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final int subtypeCount = imi.getSubtypeCount(); 225fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtypeCount <= 1) { 226fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return; 227fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 228fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String imiId = imi.getId(); 229fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(context); 230fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka root.addPreference(keyboardSettingsCategory); 231fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PackageManager pm = getPackageManager(); 232fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final CharSequence label = imi.loadLabel(pm); 2334a5f889f80b683446e498f244d0eadfd979ca5d0satok 234fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka keyboardSettingsCategory.setTitle(label); 235fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka keyboardSettingsCategory.setKey(imiId); 236fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // TODO: Use toggle Preference if images are ready. 237fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final CheckBoxPreference autoSelectionPref = new CheckBoxPreference(context); 238fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mAutoSelectionPrefsMap.put(imiId, autoSelectionPref); 239fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka keyboardSettingsCategory.addPreference(autoSelectionPref); 2401c58c15e7a84b582b7d4d20c26824cabce80bce9satok 241fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(context); 242fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes); 243fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka root.addPreference(activeInputMethodsCategory); 2444a5f889f80b683446e498f244d0eadfd979ca5d0satok 245fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka CharSequence autoSubtypeLabel = null; 246fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final ArrayList<Preference> subtypePreferences = new ArrayList<>(); 247fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (int index = 0; index < subtypeCount; ++index) { 248fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final InputMethodSubtype subtype = imi.getSubtypeAt(index); 249fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtype.overridesImplicitlyEnabledSubtype()) { 250fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (autoSubtypeLabel == null) { 251fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka autoSubtypeLabel = subtype.getDisplayName( 252fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka context, imi.getPackageName(), imi.getServiceInfo().applicationInfo); 2534a5f889f80b683446e498f244d0eadfd979ca5d0satok } 254fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } else { 255fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final Preference subtypePref = new InputMethodSubtypePreference( 256fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka context, subtype, imi); 257fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka subtypePreferences.add(subtypePref); 258989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka } 259fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 260fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka Collections.sort(subtypePreferences, new Comparator<Preference>() { 261fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka @Override 262fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka public int compare(final Preference lhs, final Preference rhs) { 263fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (lhs instanceof InputMethodSubtypePreference) { 264fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator); 265ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 266fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return lhs.compareTo(rhs); 26794bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } 268fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka }); 269fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final int prefCount = subtypePreferences.size(); 270fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (int index = 0; index < prefCount; ++index) { 271fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final Preference pref = subtypePreferences.get(index); 272fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka activeInputMethodsCategory.addPreference(pref); 2733460a2683ca820d8d7d184bc1e98241ea3986a4aTadashi G. Takaoka InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref); 274fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 275fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences); 276fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (TextUtils.isEmpty(autoSubtypeLabel)) { 277fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka autoSelectionPref.setTitle( 278fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka R.string.use_system_language_to_select_input_method_subtypes); 279fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } else { 280fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka autoSelectionPref.setTitle(autoSubtypeLabel); 2814a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2824a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2831c58c15e7a84b582b7d4d20c26824cabce80bce9satok 284989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private boolean isNoSubtypesExplicitlySelected(final String imiId) { 2851c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 28672c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka for (final Preference pref : subtypePrefs) { 28772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka if (pref instanceof CheckBoxPreference && ((CheckBoxPreference)pref).isChecked()) { 288989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka return false; 2891c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2901c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 291989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka return true; 2921c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2931c58c15e7a84b582b7d4d20c26824cabce80bce9satok 294989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private void setAutoSelectionSubtypesEnabled(final String imiId, 295989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka final boolean autoSelectionEnabled) { 296989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka final CheckBoxPreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId); 297989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka if (autoSelectionPref == null) { 29872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka return; 29972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 300989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka autoSelectionPref.setChecked(autoSelectionEnabled); 3011c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 302989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka for (final Preference pref : subtypePrefs) { 303989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka if (pref instanceof CheckBoxPreference) { 3041c58c15e7a84b582b7d4d20c26824cabce80bce9satok // When autoSelectionEnabled is true, all subtype prefs need to be disabled with 3051c58c15e7a84b582b7d4d20c26824cabce80bce9satok // implicitly checked subtypes. In case of false, all subtype prefs need to be 3061c58c15e7a84b582b7d4d20c26824cabce80bce9satok // enabled. 307989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka pref.setEnabled(!autoSelectionEnabled); 3081c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoSelectionEnabled) { 309989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka ((CheckBoxPreference)pref).setChecked(false); 3101c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3111c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3121c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3131c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoSelectionEnabled) { 31472c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka InputMethodAndSubtypeUtil.saveInputMethodSubtypeList( 31572c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka this, getContentResolver(), mInputMethodInfoList, mHaveHardKeyboard); 316989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateImplicitlyEnabledSubtypes(imiId, true /* check */); 3171c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3181c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3191c58c15e7a84b582b7d4d20c26824cabce80bce9satok 320989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private void updateImplicitlyEnabledSubtypes(final String targetImiId, final boolean check) { 3211c58c15e7a84b582b7d4d20c26824cabce80bce9satok // When targetImiId is null, apply to all subtypes of all IMEs 32272c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka for (final InputMethodInfo imi : mInputMethodInfoList) { 32372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final String imiId = imi.getId(); 324989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka final CheckBoxPreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId); 3251c58c15e7a84b582b7d4d20c26824cabce80bce9satok // No need to update implicitly enabled subtypes when the user has unchecked the 3261c58c15e7a84b582b7d4d20c26824cabce80bce9satok // "subtype auto selection". 327989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka if (autoSelectionPref == null || !autoSelectionPref.isChecked()) { 32872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka continue; 32972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 330fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (imiId.equals(targetImiId) || targetImiId == null) { 331fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka updateImplicitlyEnabledSubtypesOf(imi, check); 332fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 333fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 334fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 335fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka 336fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi, final boolean check) { 337fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String imiId = imi.getId(); 338fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 339fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final List<InputMethodSubtype> implicitlyEnabledSubtypes = 340fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mImm.getEnabledInputMethodSubtypeList(imi, true); 341fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtypePrefs == null || implicitlyEnabledSubtypes == null) { 342fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return; 343fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 344fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (final Preference pref : subtypePrefs) { 345fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (!(pref instanceof CheckBoxPreference)) { 34672c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka continue; 34772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 348fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final CheckBoxPreference subtypePref = (CheckBoxPreference)pref; 349fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka subtypePref.setChecked(false); 350fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (check) { 351fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) { 352fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode(); 353fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) { 354fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka subtypePref.setChecked(true); 355fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka break; 3561c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3571c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3581c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3591c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3601c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3611c58c15e7a84b582b7d4d20c26824cabce80bce9satok 362989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private void updateAutoSelectionPreferences() { 36372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) { 364989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId)); 3651c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 366989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateImplicitlyEnabledSubtypes(null /* targetImiId */, true /* check */); 3671c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3684a5f889f80b683446e498f244d0eadfd979ca5d0satok} 369