Allow the users to disable system IME

Bug: 8364845
Change-Id: Icc5173a68fa00b2895c0768ff8f8b9dcf30e6171
This commit is contained in:
Satoshi Kataoka
2013-07-31 16:20:29 +09:00
parent 15885f4998
commit c6fc8e46f2
4 changed files with 119 additions and 54 deletions

View File

@@ -40,6 +40,7 @@ import android.os.Handler;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener; import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
@@ -49,6 +50,7 @@ import android.text.TextUtils;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.BaseAdapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -88,11 +90,20 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
private InputMethodManager mImm; private InputMethodManager mImm;
private boolean mIsOnlyImeSettings; private boolean mIsOnlyImeSettings;
private Handler mHandler; private Handler mHandler;
@SuppressWarnings("unused")
private SettingsObserver mSettingsObserver; private SettingsObserver mSettingsObserver;
private Intent mIntentWaitingForResult; private Intent mIntentWaitingForResult;
private InputMethodSettingValuesWrapper mInputMethodSettingValues; private InputMethodSettingValuesWrapper mInputMethodSettingValues;
private final OnPreferenceChangeListener mOnImePreferenceChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference arg0, Object arg1) {
((BaseAdapter)getPreferenceScreen().getRootAdapter()).notifyDataSetChanged();
updateInputMethodPreferenceViews();
return true;
}
};
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
@@ -153,19 +164,22 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
mKeyboardSettingsCategory.addPreference(currentIme); mKeyboardSettingsCategory.addPreference(currentIme);
} }
mInputMethodPreferenceList.clear(); synchronized (mInputMethodPreferenceList) {
final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList(); mInputMethodPreferenceList.clear();
final int N = (imis == null ? 0 : imis.size()); final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList();
for (int i = 0; i < N; ++i) { final int N = (imis == null ? 0 : imis.size());
final InputMethodInfo imi = imis.get(i);
final InputMethodPreference pref = getInputMethodPreference(imi, N);
mInputMethodPreferenceList.add(pref);
}
if (!mInputMethodPreferenceList.isEmpty()) {
Collections.sort(mInputMethodPreferenceList);
for (int i = 0; i < N; ++i) { for (int i = 0; i < N; ++i) {
mKeyboardSettingsCategory.addPreference(mInputMethodPreferenceList.get(i)); final InputMethodInfo imi = imis.get(i);
final InputMethodPreference pref = getInputMethodPreference(imi);
pref.setOnImePreferenceChangeListener(mOnImePreferenceChangedListener);
mInputMethodPreferenceList.add(pref);
}
if (!mInputMethodPreferenceList.isEmpty()) {
Collections.sort(mInputMethodPreferenceList);
for (int i = 0; i < N; ++i) {
mKeyboardSettingsCategory.addPreference(mInputMethodPreferenceList.get(i));
}
} }
} }
@@ -299,7 +313,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
this, getContentResolver(), this, getContentResolver(),
mInputMethodSettingValues.getInputMethodList(), null); mInputMethodSettingValues.getInputMethodList(), null);
updateActiveInputMethodsSummary(); updateInputMethodPreferenceViews();
} }
@Override @Override
@@ -409,10 +423,12 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
return false; return false;
} }
private void updateActiveInputMethodsSummary() { private void updateInputMethodPreferenceViews() {
for (Preference pref : mInputMethodPreferenceList) { synchronized (mInputMethodPreferenceList) {
if (pref instanceof InputMethodPreference) { for (Preference pref : mInputMethodPreferenceList) {
((InputMethodPreference)pref).updateSummary(); if (pref instanceof InputMethodPreference) {
((InputMethodPreference) pref).updatePreferenceViews();
}
} }
} }
updateCurrentImeName(); updateCurrentImeName();
@@ -433,7 +449,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
} }
} }
private InputMethodPreference getInputMethodPreference(InputMethodInfo imi, int imiSize) { private InputMethodPreference getInputMethodPreference(InputMethodInfo imi) {
final PackageManager pm = getPackageManager(); final PackageManager pm = getPackageManager();
final CharSequence label = imi.loadLabel(pm); final CharSequence label = imi.loadLabel(pm);
// IME settings // IME settings
@@ -447,7 +463,8 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
} }
// Add a check box for enabling/disabling IME // Add a check box for enabling/disabling IME
InputMethodPreference pref = new InputMethodPreference(this, intent, mImm, imi, imiSize); final InputMethodPreference pref =
new InputMethodPreference(this, intent, mImm, imi);
pref.setKey(imi.getId()); pref.setKey(imi.getId());
pref.setTitle(label); pref.setTitle(label);
return pref; return pref;

View File

@@ -20,10 +20,6 @@ import com.android.internal.inputmethod.InputMethodUtils;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
@@ -32,13 +28,11 @@ import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
public class InputMethodAndSubtypeUtil { public class InputMethodAndSubtypeUtil {
@@ -49,7 +43,6 @@ public class InputMethodAndSubtypeUtil {
private static final char INPUT_METHOD_SEPARATER = ':'; private static final char INPUT_METHOD_SEPARATER = ':';
private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';'; private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
private static final int NOT_A_SUBTYPE_ID = -1; private static final int NOT_A_SUBTYPE_ID = -1;
private static final Locale ENGLISH_LOCALE = new Locale("en");
private static final TextUtils.SimpleStringSplitter sStringInputMethodSplitter private static final TextUtils.SimpleStringSplitter sStringInputMethodSplitter
= new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER); = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);

View File

@@ -24,6 +24,7 @@ import com.android.settings.Utils;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Fragment; import android.app.Fragment;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
@@ -52,8 +53,8 @@ public class InputMethodPreference extends CheckBoxPreference {
private final SettingsPreferenceFragment mFragment; private final SettingsPreferenceFragment mFragment;
private final InputMethodInfo mImi; private final InputMethodInfo mImi;
private final InputMethodManager mImm; private final InputMethodManager mImm;
private final boolean mIsValidSystemNonAuxAsciiCapableIme;
private final Intent mSettingsIntent; private final Intent mSettingsIntent;
private final boolean mAlwaysChecked;
private final boolean mIsSystemIme; private final boolean mIsSystemIme;
private final Collator mCollator; private final Collator mCollator;
@@ -62,6 +63,7 @@ public class InputMethodPreference extends CheckBoxPreference {
private TextView mTitleText; private TextView mTitleText;
private TextView mSummaryText; private TextView mSummaryText;
private View mInputMethodPref; private View mInputMethodPref;
private OnPreferenceChangeListener mOnImePreferenceChangeListener;
private final OnClickListener mPrefOnclickListener = new OnClickListener() { private final OnClickListener mPrefOnclickListener = new OnClickListener() {
@Override @Override
@@ -82,7 +84,7 @@ public class InputMethodPreference extends CheckBoxPreference {
}; };
public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent, public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
InputMethodManager imm, InputMethodInfo imi, int imiCount) { InputMethodManager imm, InputMethodInfo imi) {
super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle); super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
setLayoutResource(R.layout.preference_inputmethod); setLayoutResource(R.layout.preference_inputmethod);
setWidgetLayoutResource(R.layout.preference_inputmethod_widget); setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
@@ -90,15 +92,12 @@ public class InputMethodPreference extends CheckBoxPreference {
mSettingsIntent = settingsIntent; mSettingsIntent = settingsIntent;
mImm = imm; mImm = imm;
mImi = imi; mImi = imi;
updateSummary();
mAlwaysChecked = InputMethodSettingValuesWrapper.getInstance(
fragment.getActivity()).isAlwaysCheckedIme(
imi, fragment.getActivity());
mIsSystemIme = InputMethodUtils.isSystemIme(imi); mIsSystemIme = InputMethodUtils.isSystemIme(imi);
if (mAlwaysChecked) {
setEnabled(false);
}
mCollator = Collator.getInstance(fragment.getResources().getConfiguration().locale); mCollator = Collator.getInstance(fragment.getResources().getConfiguration().locale);
final Context context = fragment.getActivity();
mIsValidSystemNonAuxAsciiCapableIme = InputMethodSettingValuesWrapper
.getInstance(context).isValidSystemNonAuxAsciiCapableIme(imi, context);
updatePreferenceViews();
} }
@Override @Override
@@ -158,9 +157,8 @@ public class InputMethodPreference extends CheckBoxPreference {
} }
if (mSettingsIntent == null) { if (mSettingsIntent == null) {
mInputMethodSettingsButton.setVisibility(View.GONE); mInputMethodSettingsButton.setVisibility(View.GONE);
} else {
updatePreferenceViews();
} }
updatePreferenceViews();
} }
@Override @Override
@@ -169,7 +167,16 @@ public class InputMethodPreference extends CheckBoxPreference {
updatePreferenceViews(); updatePreferenceViews();
} }
private void updatePreferenceViews() { public void updatePreferenceViews() {
final boolean isAlwaysChecked =
InputMethodSettingValuesWrapper.getInstance(getContext()).isAlwaysCheckedIme(
mImi, getContext());
if (isAlwaysChecked) {
super.setChecked(true);
super.setEnabled(false);
} else {
super.setEnabled(true);
}
final boolean checked = isChecked(); final boolean checked = isChecked();
if (mInputMethodSettingsButton != null) { if (mInputMethodSettingsButton != null) {
mInputMethodSettingsButton.setEnabled(checked); mInputMethodSettingsButton.setEnabled(checked);
@@ -194,6 +201,7 @@ public class InputMethodPreference extends CheckBoxPreference {
mInputMethodPref.setBackgroundColor(0); mInputMethodPref.setBackgroundColor(0);
} }
} }
updateSummary();
} }
public static boolean startFragment( public static boolean startFragment(
@@ -211,7 +219,7 @@ public class InputMethodPreference extends CheckBoxPreference {
} }
} }
public String getSummaryString() { private String getSummaryString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true); final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
for (InputMethodSubtype subtype : subtypes) { for (InputMethodSubtype subtype : subtypes) {
@@ -225,7 +233,7 @@ public class InputMethodPreference extends CheckBoxPreference {
return builder.toString(); return builder.toString();
} }
public void updateSummary() { private void updateSummary() {
final String summary = getSummaryString(); final String summary = getSummaryString();
if (TextUtils.isEmpty(summary)) { if (TextUtils.isEmpty(summary)) {
return; return;
@@ -238,17 +246,21 @@ public class InputMethodPreference extends CheckBoxPreference {
* @param checked whether to check the box * @param checked whether to check the box
* @param save whether to save IME settings * @param save whether to save IME settings
*/ */
public void setChecked(boolean checked, boolean save) { private void setChecked(boolean checked, boolean save) {
final boolean wasChecked = isChecked();
super.setChecked(checked); super.setChecked(checked);
if (save) { if (save) {
saveImeSettings(); saveImeSettings();
InputMethodSettingValuesWrapper.getInstance(
getContext()).refreshAllInputMethodAndSubtypes();
if (wasChecked != checked && mOnImePreferenceChangeListener != null) {
mOnImePreferenceChangeListener.onPreferenceChange(this, checked);
}
} }
updateSummary();
} }
@Override public void setOnImePreferenceChangeListener(OnPreferenceChangeListener listener) {
public void setChecked(boolean checked) { mOnImePreferenceChangeListener = listener;
setChecked(checked, false);
} }
private void showSecurityWarnDialog(InputMethodInfo imi, final InputMethodPreference chkPref) { private void showSecurityWarnDialog(InputMethodInfo imi, final InputMethodPreference chkPref) {
@@ -285,8 +297,8 @@ public class InputMethodPreference extends CheckBoxPreference {
return super.compareTo(p); return super.compareTo(p);
} }
final InputMethodPreference imp = (InputMethodPreference) p; final InputMethodPreference imp = (InputMethodPreference) p;
final boolean priority0 = mIsSystemIme && mAlwaysChecked; final boolean priority0 = mIsSystemIme && mIsValidSystemNonAuxAsciiCapableIme;
final boolean priority1 = imp.mIsSystemIme && imp.mAlwaysChecked; final boolean priority1 = imp.mIsSystemIme && imp.mIsValidSystemNonAuxAsciiCapableIme;
if (priority0 == priority1) { if (priority0 == priority1) {
final CharSequence t0 = getTitle(); final CharSequence t0 = getTitle();
final CharSequence t1 = imp.getTitle(); final CharSequence t1 = imp.getTitle();

View File

@@ -109,24 +109,67 @@ public class InputMethodSettingValuesWrapper {
} }
public boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) { public boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
if (getInputMethodList().size() <= 1) { synchronized (mMethodMap) {
return true; if (mSettings.getEnabledInputMethodListLocked().size() <= 1) {
return true;
}
} }
final int enabledValidSystemNonAuxAsciiCapableImeCount =
getEnabledValidSystemNonAuxAsciiCapableImeCount(context);
if (enabledValidSystemNonAuxAsciiCapableImeCount > 1) {
return false;
}
if (enabledValidSystemNonAuxAsciiCapableImeCount == 1 && !isEnabledImi(imi)) {
return false;
}
if (!InputMethodUtils.isSystemIme(imi)) { if (!InputMethodUtils.isSystemIme(imi)) {
return false; return false;
} }
return isValidSystemNonAuxAsciiCapableIme(imi, context); return isValidSystemNonAuxAsciiCapableIme(imi, context);
} }
private static boolean isValidSystemNonAuxAsciiCapableIme( private int getEnabledValidSystemNonAuxAsciiCapableImeCount(Context context) {
InputMethodInfo imi, Context context) { int count = 0;
final List<InputMethodInfo> enabledImis;
synchronized(mMethodMap) {
enabledImis = mSettings.getEnabledInputMethodListLocked();
}
for (final InputMethodInfo imi : enabledImis) {
if (isValidSystemNonAuxAsciiCapableIme(imi, context)) {
++count;
}
}
if (count == 0) {
Log.w(TAG, "No \"enabledValidSystemNonAuxAsciiCapableIme\"s found.");
}
return count;
}
private boolean isEnabledImi(InputMethodInfo imi) {
final List<InputMethodInfo> enabledImis;
synchronized(mMethodMap) {
enabledImis = mSettings.getEnabledInputMethodListLocked();
}
for (final InputMethodInfo tempImi : enabledImis) {
if (tempImi.getId().equals(imi.getId())) {
return true;
}
}
return false;
}
public static boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi,
Context context) {
if (imi.isAuxiliaryIme()) { if (imi.isAuxiliaryIme()) {
return false; return false;
} }
if (InputMethodUtils.isValidSystemDefaultIme(true /* isSystemReady */, imi, context)) { if (InputMethodUtils.isValidSystemDefaultIme(true /* isSystemReady */, imi, context)) {
return true; return true;
} }
return InputMethodUtils.containsSubtypeOf( return InputMethodUtils.containsSubtypeOf(imi, ENGLISH_LOCALE.getLanguage(),
imi, ENGLISH_LOCALE.getLanguage(), null /* mode */); InputMethodUtils.SUBTYPE_MODE_KEYBOARD);
} }
} }