Add an option for the implicitly selected subtype
Bug: 5057886
Change-Id: Iddde4724891501b4f18cade6a3d2c64b6124e58a
diff --git a/api/current.txt b/api/current.txt
index 27787b5..c35ffda 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -709,6 +709,7 @@
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
+ field public static final int overridesImplicitlyEnabledSubtype = 16843696; // 0x10103b0
field public static final int packageNames = 16843649; // 0x1010381
field public static final int padding = 16842965; // 0x10100d5
field public static final int paddingBottom = 16842969; // 0x10100d9
@@ -24531,6 +24532,7 @@
}
public final class InputMethodSubtype implements android.os.Parcelable {
+ ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean);
method public boolean containsExtraValueKey(java.lang.String);
method public int describeContents();
method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
@@ -24541,6 +24543,7 @@
method public java.lang.String getMode();
method public int getNameResId();
method public boolean isAuxiliary();
+ method public boolean overridesImplicitlyEnabledSubtype();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 4ec4ff9..0119d03 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -164,7 +164,9 @@
a.getString(com.android.internal.R.styleable
.InputMethod_Subtype_imeSubtypeExtraValue),
a.getBoolean(com.android.internal.R.styleable
- .InputMethod_Subtype_isAuxiliary, false));
+ .InputMethod_Subtype_isAuxiliary, false),
+ a.getBoolean(com.android.internal.R.styleable
+ .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false));
mSubtypes.add(subtype);
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 8c51680..5670432 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -42,6 +42,7 @@
private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
private final boolean mIsAuxiliary;
+ private final boolean mOverridesImplicitlyEnabledSubtype;
private final int mSubtypeHashCode;
private final int mSubtypeIconResId;
private final int mSubtypeNameResId;
@@ -57,11 +58,12 @@
* @param locale The locale supported by the subtype
* @param mode The mode supported by the subtype
* @param extraValue The extra value of the subtype
+ * @param isAuxiliary true when this subtype is one shot subtype.
* @hide
*/
- public InputMethodSubtype(
- int nameId, int iconId, String locale, String mode, String extraValue) {
- this(nameId, iconId, locale, mode, extraValue, false);
+ public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
+ boolean isAuxiliary) {
+ this(nameId, iconId, locale, mode, extraValue, false, false);
}
/**
@@ -72,18 +74,21 @@
* @param mode The mode supported by the subtype
* @param extraValue The extra value of the subtype
* @param isAuxiliary true when this subtype is one shot subtype.
- * @hide
+ * @param overridesImplicitlyEnabledSubtype true when this subtype should be selected by default
+ * if no other subtypes are selected explicitly. Note that a subtype with this parameter being
+ * true will not be shown in the subtypes list.
*/
public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
- boolean isAuxiliary) {
+ boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
mSubtypeNameResId = nameId;
mSubtypeIconResId = iconId;
mSubtypeLocale = locale != null ? locale : "";
mSubtypeMode = mode != null ? mode : "";
mSubtypeExtraValue = extraValue != null ? extraValue : "";
mIsAuxiliary = isAuxiliary;
+ mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype;
mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
- mIsAuxiliary);
+ mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
}
InputMethodSubtype(Parcel source) {
@@ -97,8 +102,9 @@
s = source.readString();
mSubtypeExtraValue = s != null ? s : "";
mIsAuxiliary = (source.readInt() == 1);
+ mOverridesImplicitlyEnabledSubtype = (source.readInt() == 1);
mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
- mIsAuxiliary);
+ mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
}
/**
@@ -146,6 +152,14 @@
}
/**
+ * @return true when this subtype is selected by default if no other subtypes are selected
+ * explicitly. Note that a subtype that returns true will not be shown in the subtypes list.
+ */
+ public boolean overridesImplicitlyEnabledSubtype() {
+ return mOverridesImplicitlyEnabledSubtype;
+ }
+
+ /**
* @param context Context will be used for getting Locale and PackageManager.
* @param packageName The package name of the IME
* @param appInfo The application info of the IME
@@ -244,6 +258,7 @@
dest.writeString(mSubtypeMode);
dest.writeString(mSubtypeExtraValue);
dest.writeInt(mIsAuxiliary ? 1 : 0);
+ dest.writeInt(mOverridesImplicitlyEnabledSubtype ? 1 : 0);
}
public static final Parcelable.Creator<InputMethodSubtype> CREATOR
@@ -276,8 +291,9 @@
}
private static int hashCodeInternal(String locale, String mode, String extraValue,
- boolean isAuxiliary) {
- return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary});
+ boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
+ return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary,
+ overridesImplicitlyEnabledSubtype});
}
/**
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b50c063..0bf5b0a 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2237,6 +2237,10 @@
InputMethodManager#switchToLastInputMethod will ignore auxiliary subtypes when it
chooses a target subtype. -->
<attr name="isAuxiliary" format="boolean" />
+ <!-- Set true when this subtype should be selected by default if no other subtypes are
+ selected explicitly. Note that a subtype with this parameter being true will
+ not be shown in the subtypes list. -->
+ <attr name="overridesImplicitlyEnabledSubtype" format="boolean" />
<!-- The extra value of the subtype. This string can be any string and will be passed to
the IME when the framework calls the IME with the subtype. -->
<attr name="imeSubtypeExtraValue" format="string" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6988f6b..bc2b907 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2010,4 +2010,5 @@
<public type="attr" name="targetDescriptions" />
<public type="attr" name="directionDescriptions" />
+ <public type="attr" name="overridesImplicitlyEnabledSubtype" />
</resources>
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index bb831f5..6aa95c1 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -655,7 +655,7 @@
List<InputMethodSubtype> enabledSubtypes =
mSettings.getEnabledInputMethodSubtypeListLocked(imi);
if (allowsImplicitlySelectedSubtypes && enabledSubtypes.isEmpty()) {
- enabledSubtypes = getApplicableSubtypesLocked(mRes, getSubtypes(imi));
+ enabledSubtypes = getImplicitlyApplicableSubtypesLocked(mRes, imi);
}
return InputMethodSubtype.sort(mContext, 0, imi, enabledSubtypes);
}
@@ -1903,6 +1903,20 @@
return subtypes;
}
+
+ private static ArrayList<InputMethodSubtype> getOverridingImplicitlyEnabledSubtypes(
+ InputMethodInfo imi, String mode) {
+ ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int i = 0; i < subtypeCount; ++i) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ if (subtype.overridesImplicitlyEnabledSubtype() && subtype.getMode().equals(mode)) {
+ subtypes.add(subtype);
+ }
+ }
+ return subtypes;
+ }
+
private boolean chooseNewDefaultIMELocked() {
List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
if (enabled != null && enabled.size() > 0) {
@@ -2357,8 +2371,9 @@
return NOT_A_SUBTYPE_ID;
}
- private static ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
- Resources res, List<InputMethodSubtype> subtypes) {
+ private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
+ Resources res, InputMethodInfo imi) {
+ final List<InputMethodSubtype> subtypes = getSubtypes(imi);
final String systemLocale = res.getConfiguration().locale.toString();
if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
@@ -2366,6 +2381,19 @@
final int N = subtypes.size();
boolean containsKeyboardSubtype = false;
for (int i = 0; i < N; ++i) {
+ // scan overriding implicitly enabled subtypes.
+ InputMethodSubtype subtype = subtypes.get(i);
+ if (subtype.overridesImplicitlyEnabledSubtype()) {
+ final String mode = subtype.getMode();
+ if (!applicableModeAndSubtypesMap.containsKey(mode)) {
+ applicableModeAndSubtypesMap.put(mode, subtype);
+ }
+ }
+ }
+ if (applicableModeAndSubtypesMap.size() > 0) {
+ return new ArrayList<InputMethodSubtype>(applicableModeAndSubtypesMap.values());
+ }
+ for (int i = 0; i < N; ++i) {
InputMethodSubtype subtype = subtypes.get(i);
final String locale = subtype.getLocale();
final String mode = subtype.getMode();
@@ -2489,16 +2517,21 @@
subtype = findLastResortApplicableSubtypeLocked(
mRes, enabledSubtypes, mode, null, true);
}
+ final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
+ getOverridingImplicitlyEnabledSubtypes(imi, mode);
+ final ArrayList<InputMethodSubtype> subtypesForSearch =
+ overridingImplicitlyEnabledSubtypes.isEmpty()
+ ? getSubtypes(imi) : overridingImplicitlyEnabledSubtypes;
// 4. Search by the current subtype's locale from all subtypes.
if (subtype == null && mCurrentSubtype != null) {
subtype = findLastResortApplicableSubtypeLocked(
- mRes, getSubtypes(imi), mode, mCurrentSubtype.getLocale(), false);
+ mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
}
// 5. Search by the system locale from all subtypes.
// 6. Search the first enabled subtype matched with mode from all subtypes.
if (subtype == null) {
subtype = findLastResortApplicableSubtypeLocked(
- mRes, getSubtypes(imi), mode, null, true);
+ mRes, subtypesForSearch, mode, null, true);
}
if (subtype != null) {
if (imiId.equals(mCurMethodId)) {
@@ -2945,12 +2978,12 @@
if (explicitlyEnabledSubtypes.size() == 0) {
// If there are no explicitly enabled subtypes, applicable subtypes are
// enabled implicitly.
- InputMethodInfo ime = mMethodMap.get(imeId);
+ InputMethodInfo imi = mMethodMap.get(imeId);
// If IME is enabled and no subtypes are enabled, applicable subtypes
// are enabled implicitly, so needs to treat them to be enabled.
- if (ime != null && ime.getSubtypeCount() > 0) {
+ if (imi != null && imi.getSubtypeCount() > 0) {
List<InputMethodSubtype> implicitlySelectedSubtypes =
- getApplicableSubtypesLocked(mRes, getSubtypes(ime));
+ getImplicitlyApplicableSubtypesLocked(mRes, imi);
if (implicitlySelectedSubtypes != null) {
final int N = implicitlySelectedSubtypes.size();
for (int i = 0; i < N; ++i) {