summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/InputMethodManagerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/InputMethodManagerService.java')
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java155
1 files changed, 133 insertions, 22 deletions
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index e14345b..b2cc6bd 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -55,6 +55,7 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.Message;
import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -120,6 +121,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// If IME doesn't support the system locale, the default subtype will be the first defined one.
private static final int DEFAULT_SUBTYPE_ID = 0;
+ private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
+ private static final String SUBTYPE_MODE_VOICE = "voice";
+
final Context mContext;
final Handler mHandler;
final InputMethodSettings mSettings;
@@ -235,6 +239,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*/
private InputMethodSubtype mCurrentSubtype;
+ // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
+ private List<Pair<InputMethodInfo, InputMethodSubtype>> mShortcutInputMethodsAndSubtypes;
+ // This list is used for returning the pairs of InputMethodInfo and InputMethodSubtype through
+ // aidl. This list has imi1, subtype1 imi2, subtype2...
+ private List mShortcutInputMethodsAndSubtypesObjectList;
/**
* Set to true if our ServiceConnection is currently actively bound to
@@ -983,6 +992,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurMethodId = null;
unbindCurrentMethodLocked(true);
}
+ mShortcutInputMethodsAndSubtypes = null;
} else {
// There is no longer an input method set, so stop any current one.
mCurMethodId = null;
@@ -1910,25 +1920,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return NOT_A_SUBTYPE_ID;
}
- // If there are no selected subtypes, tries finding the most applicable one according to the
- // current system locale
- private int findApplicableSubtypeLocked(String id) {
- InputMethodInfo imi = mMethodMap.get(id);
- if (imi == null) {
- return NOT_A_SUBTYPE_ID;
- }
- ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
+ /**
+ * If there are no selected subtypes, tries finding the most applicable one according to the
+ * given locale.
+ * @param subtypes this function will search the most applicable subtype in subtypes
+ * @param mode subtypes will be filtered by mode
+ * @param locale subtypes will be filtered by locale
+ * @param defaultSubtypeId if this function can't find the most applicable subtype, it will
+ * return defaultSubtypeId
+ * @return the most applicable subtypeId
+ */
+ private int findLastResortApplicableSubtypeLocked(
+ List<InputMethodSubtype> subtypes, String mode, String locale, int defaultSubtypeId) {
if (subtypes == null || subtypes.size() == 0) {
return NOT_A_SUBTYPE_ID;
}
- final String locale = mContext.getResources().getConfiguration().locale.toString();
+ if (TextUtils.isEmpty(locale)) {
+ locale = mContext.getResources().getConfiguration().locale.toString();
+ }
final String language = locale.substring(0, 2);
boolean partialMatchFound = false;
- int applicableSubtypeId = DEFAULT_SUBTYPE_ID;
+ int applicableSubtypeId = defaultSubtypeId;
for (int i = 0; i < subtypes.size(); ++i) {
final String subtypeLocale = subtypes.get(i).getLocale();
- // An applicable subtype should be a keyboard subtype
- if (subtypes.get(i).getMode().equalsIgnoreCase("keyboard")) {
+ // An applicable subtype should match "mode".
+ if (subtypes.get(i).getMode().equalsIgnoreCase(mode)) {
if (locale.equals(subtypeLocale)) {
// Exact match (e.g. system locale is "en_US" and subtype locale is "en_US")
applicableSubtypeId = i;
@@ -1950,34 +1966,129 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return applicableSubtypeId;
}
+ // If there are no selected shortcuts, tries finding the most applicable ones.
+ private Pair<InputMethodInfo, InputMethodSubtype>
+ findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
+ List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
+ InputMethodInfo mostApplicableIMI = null;
+ int mostApplicableSubtypeId = NOT_A_SUBTYPE_ID;
+ boolean foundInSystemIME = false;
+
+ // Search applicable subtype for each InputMethodInfo
+ for (InputMethodInfo imi: imis) {
+ int subtypeId = NOT_A_SUBTYPE_ID;
+ if (mCurrentSubtype != null) {
+ // 1. Search with the current subtype's locale and the enabled subtypes
+ subtypeId = findLastResortApplicableSubtypeLocked(
+ mSettings.getEnabledInputMethodSubtypeListLocked(
+ imi), mode, mCurrentSubtype.getLocale(), NOT_A_SUBTYPE_ID);
+ if (subtypeId == NOT_A_SUBTYPE_ID) {
+ // 2. Search with the current subtype's locale and all subtypes
+ subtypeId = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
+ mode, mCurrentSubtype.getLocale(), NOT_A_SUBTYPE_ID);
+ }
+ }
+ // 3. Search with the system locale and the enabled subtypes
+ if (subtypeId == NOT_A_SUBTYPE_ID) {
+ subtypeId = findLastResortApplicableSubtypeLocked(
+ mSettings.getEnabledInputMethodSubtypeListLocked(
+ imi), mode, null, NOT_A_SUBTYPE_ID);
+ }
+ if (subtypeId == NOT_A_SUBTYPE_ID) {
+ // 4. Search with the system locale and all subtypes
+ subtypeId = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
+ mode, null, NOT_A_SUBTYPE_ID);
+ }
+ if (subtypeId != NOT_A_SUBTYPE_ID) {
+ if (imi.getId().equals(mCurMethodId)) {
+ // The current input method is the most applicable IME.
+ mostApplicableIMI = imi;
+ mostApplicableSubtypeId = subtypeId;
+ break;
+ } else if ((imi.getServiceInfo().applicationInfo.flags
+ & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ // The system input method is 2nd applicable IME.
+ mostApplicableIMI = imi;
+ mostApplicableSubtypeId = subtypeId;
+ foundInSystemIME = true;
+ } else if (!foundInSystemIME) {
+ mostApplicableIMI = imi;
+ mostApplicableSubtypeId = subtypeId;
+ }
+ }
+ }
+ if (DEBUG) {
+ Slog.w(TAG, "Most applicable shortcut input method subtype was:"
+ + mostApplicableIMI.getId() + "," + mostApplicableSubtypeId);
+ }
+ if (mostApplicableIMI != null && mostApplicableSubtypeId != NOT_A_SUBTYPE_ID) {
+ ArrayList<Parcelable> ret = new ArrayList<Parcelable>(2);
+ return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
+ mostApplicableIMI.getSubtypes().get(mostApplicableSubtypeId));
+ } else {
+ return null;
+ }
+ }
+
/**
* @return Return the current subtype of this input method.
*/
public InputMethodSubtype getCurrentInputMethodSubtype() {
+ boolean subtypeIsSelected = false;
+ try {
+ subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE) != NOT_A_SUBTYPE_ID;
+ } catch (SettingNotFoundException e) {
+ }
synchronized (mMethodMap) {
- boolean subtypeIsSelected = false;
- try {
- subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE) != NOT_A_SUBTYPE_ID;
- } catch (SettingNotFoundException e) {
- }
if (!subtypeIsSelected || mCurrentSubtype == null) {
- String lastInputMethodId =
- Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD);
+ String lastInputMethodId = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
int subtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId);
if (subtypeId == NOT_A_SUBTYPE_ID) {
- subtypeId = findApplicableSubtypeLocked(lastInputMethodId);
+ InputMethodInfo imi = mMethodMap.get(lastInputMethodId);
+ if (imi != null) {
+ // If there are no selected subtypes, the framework will try to find
+ // the most applicable subtype from all subtypes whose mode is
+ // SUBTYPE_MODE_KEYBOARD. This is an exceptional case, so we will hardcode
+ // the mode.
+ subtypeId = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
+ SUBTYPE_MODE_KEYBOARD, null, DEFAULT_SUBTYPE_ID);
+ }
}
if (subtypeId != NOT_A_SUBTYPE_ID) {
mCurrentSubtype =
mMethodMap.get(lastInputMethodId).getSubtypes().get(subtypeId);
+ } else {
+ mCurrentSubtype = null;
}
}
return mCurrentSubtype;
}
}
+ // TODO: We should change the return type from List to List<Parcelable>
+ public List getShortcutInputMethodsAndSubtypes() {
+ synchronized (mMethodMap) {
+ if (mShortcutInputMethodsAndSubtypesObjectList != null) {
+ // If there are no selected shortcut subtypes, the framework will try to find
+ // the most applicable subtype from all subtypes whose mode is
+ // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
+ mShortcutInputMethodsAndSubtypes =
+ new ArrayList<Pair<InputMethodInfo, InputMethodSubtype>>();
+ mShortcutInputMethodsAndSubtypes.add(
+ findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
+ SUBTYPE_MODE_VOICE));
+ mShortcutInputMethodsAndSubtypesObjectList = new ArrayList<Parcelable>();
+ for (Pair ime: mShortcutInputMethodsAndSubtypes) {
+ mShortcutInputMethodsAndSubtypesObjectList.add(ime.first);
+ mShortcutInputMethodsAndSubtypesObjectList.add(ime.second);
+ }
+ }
+ return mShortcutInputMethodsAndSubtypesObjectList;
+ }
+ }
+
public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
synchronized (mMethodMap) {
if (subtype != null && mCurMethodId != null) {