From dc8abf6cee0bcf44e2cad8155f0c151105d46471 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Tue, 12 Mar 2013 14:40:04 +0900 Subject: Cleanup InputMethodSubtype and add "isAsciiCapable". Bug: 8364845 Change-Id: Ic3ace4b6e0432d56696bcbc0be336aec1dc744a5 --- api/current.txt | 20 +- .../android/view/inputmethod/InputMethodInfo.java | 39 ++-- .../view/inputmethod/InputMethodSubtype.java | 233 ++++++++++++++++----- core/res/res/values/attrs.xml | 5 + core/res/res/values/public.xml | 1 + 5 files changed, 227 insertions(+), 71 deletions(-) diff --git a/api/current.txt b/api/current.txt index f3aff2b..3fe602c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -605,6 +605,7 @@ package android { field public static final int installLocation = 16843447; // 0x10102b7 field public static final int interpolator = 16843073; // 0x1010141 field public static final int isAlwaysSyncable = 16843571; // 0x1010333 + field public static final int isAsciiCapable = 16843750; // 0x10103e6 field public static final int isAuxiliary = 16843647; // 0x101037f field public static final int isDefault = 16843297; // 0x1010221 field public static final int isIndicator = 16843079; // 0x1010147 @@ -28908,8 +28909,8 @@ package android.view.inputmethod { } public final class InputMethodSubtype implements android.os.Parcelable { - ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean); - ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean, int); + ctor public deprecated InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean); + ctor public deprecated InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean, int); 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); @@ -28919,12 +28920,27 @@ package android.view.inputmethod { method public java.lang.String getLocale(); method public java.lang.String getMode(); method public int getNameResId(); + method public boolean isAsciiCapable(); 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; } + public static class InputMethodSubtype.InputMethodSubtypeBuilder { + ctor public InputMethodSubtype.InputMethodSubtypeBuilder(); + method public android.view.inputmethod.InputMethodSubtype build(); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setIsAsciiCapable(boolean); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setIsAuxiliary(boolean); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setOverridesImplicitlyEnabledSubtype(boolean); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeExtraValue(java.lang.String); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeIconResId(int); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeId(int); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeLocale(java.lang.String); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeMode(java.lang.String); + method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeNameResId(int); + } + } package android.view.textservice { diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 54c2ba5..5f2b049 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -36,6 +36,7 @@ import android.util.AttributeSet; import android.util.Printer; import android.util.Slog; import android.util.Xml; +import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import java.io.IOException; import java.util.ArrayList; @@ -162,24 +163,26 @@ public final class InputMethodInfo implements Parcelable { } final TypedArray a = res.obtainAttributes( attrs, com.android.internal.R.styleable.InputMethod_Subtype); - InputMethodSubtype subtype = new InputMethodSubtype( - a.getResourceId(com.android.internal.R.styleable - .InputMethod_Subtype_label, 0), - a.getResourceId(com.android.internal.R.styleable - .InputMethod_Subtype_icon, 0), - a.getString(com.android.internal.R.styleable - .InputMethod_Subtype_imeSubtypeLocale), - a.getString(com.android.internal.R.styleable - .InputMethod_Subtype_imeSubtypeMode), - a.getString(com.android.internal.R.styleable - .InputMethod_Subtype_imeSubtypeExtraValue), - a.getBoolean(com.android.internal.R.styleable - .InputMethod_Subtype_isAuxiliary, false), - a.getBoolean(com.android.internal.R.styleable - .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false), - a.getInt(com.android.internal.R.styleable - .InputMethod_Subtype_subtypeId, 0 /* use Arrays.hashCode */) - ); + final InputMethodSubtype subtype = new InputMethodSubtypeBuilder() + .setSubtypeNameResId(a.getResourceId(com.android.internal.R.styleable + .InputMethod_Subtype_label, 0)) + .setSubtypeIconResId(a.getResourceId(com.android.internal.R.styleable + .InputMethod_Subtype_icon, 0)) + .setSubtypeLocale(a.getString(com.android.internal.R.styleable + .InputMethod_Subtype_imeSubtypeLocale)) + .setSubtypeMode(a.getString(com.android.internal.R.styleable + .InputMethod_Subtype_imeSubtypeMode)) + .setSubtypeExtraValue(a.getString(com.android.internal.R.styleable + .InputMethod_Subtype_imeSubtypeExtraValue)) + .setIsAuxiliary(a.getBoolean(com.android.internal.R.styleable + .InputMethod_Subtype_isAuxiliary, false)) + .setOverridesImplicitlyEnabledSubtype(a.getBoolean( + com.android.internal.R.styleable + .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false)) + .setSubtypeId(a.getInt(com.android.internal.R.styleable + .InputMethod_Subtype_subtypeId, 0 /* use Arrays.hashCode */)) + .setIsAsciiCapable(a.getBoolean(com.android.internal.R.styleable + .InputMethod_Subtype_isAsciiCapable, false)).build(); if (!subtype.isAuxiliary()) { mIsAuxIme = false; } diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java index 7895e6f..88b2977 100644 --- a/core/java/android/view/inputmethod/InputMethodSubtype.java +++ b/core/java/android/view/inputmethod/InputMethodSubtype.java @@ -52,6 +52,7 @@ public final class InputMethodSubtype implements Parcelable { private final boolean mIsAuxiliary; private final boolean mOverridesImplicitlyEnabledSubtype; + private final boolean mIsAsciiCapable; private final int mSubtypeHashCode; private final int mSubtypeIconResId; private final int mSubtypeNameResId; @@ -62,24 +63,145 @@ public final class InputMethodSubtype implements Parcelable { private volatile HashMap mExtraValueHashMapCache; /** + * InputMethodSubtypeBuilder is a builder class of InputMethodSubtype. + * This class is designed to be used with + * {@link android.view.inputmethod.InputMethodManager#setAdditionalInputMethodSubtypes}. + * The developer needs to be aware of what each parameter means. + */ + public static class InputMethodSubtypeBuilder { + /** + * @param isAuxiliary should true when this subtype is auxiliary, false otherwise. + * An auxiliary subtype has the following differences with a regular subtype: + * - An auxiliary subtype cannot be chosen as the default IME in Settings. + * - The framework will never switch to this subtype through + * {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}. + * Note that the subtype will still be available in the IME switcher. + * The intent is to allow for IMEs to specify they are meant to be invoked temporarily + * in a one-shot way, and to return to the previous IME once finished (e.g. voice input). + */ + public InputMethodSubtypeBuilder setIsAuxiliary(boolean isAuxiliary) { + mIsAuxiliary = isAuxiliary; + return this; + } + private boolean mIsAuxiliary = false; + + /** + * @param overridesImplicitlyEnabledSubtype should be true if this subtype should be + * enabled by default if no other subtypes in the IME are enabled explicitly. Note that a + * subtype with this parameter set will not be shown in the list of subtypes in each IME's + * subtype enabler. A canonical use of this would be for an IME to supply an "automatic" + * subtype that adapts to the current system language. + */ + public InputMethodSubtypeBuilder setOverridesImplicitlyEnabledSubtype( + boolean overridesImplicitlyEnabledSubtype) { + mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype; + return this; + } + private boolean mOverridesImplicitlyEnabledSubtype = false; + + /** + * @param isAsciiCapable should be true if this subtype is ASCII capable. If the subtype + * is ASCII capable, it should guarantee that the user can input ASCII characters with + * this subtype. This is important because many password fields only allow + * ASCII-characters. + */ + public InputMethodSubtypeBuilder setIsAsciiCapable(boolean isAsciiCapable) { + mIsAsciiCapable = isAsciiCapable; + return this; + } + private boolean mIsAsciiCapable = false; + + /** + * @param subtypeIconResId is a resource ID of the subtype icon drawable. + */ + public InputMethodSubtypeBuilder setSubtypeIconResId(int subtypeIconResId) { + mSubtypeIconResId = subtypeIconResId; + return this; + } + private int mSubtypeIconResId = 0; + + /** + * @param subtypeNameResId is the resource ID of the subtype name string. + * The string resource may have exactly one %s in it. If present, + * the %s part will be replaced with the locale's display name by + * the formatter. Please refer to {@link #getDisplayName} for details. + */ + public InputMethodSubtypeBuilder setSubtypeNameResId(int subtypeNameResId) { + mSubtypeNameResId = subtypeNameResId; + return this; + } + private int mSubtypeNameResId = 0; + + /** + * @param subtypeId is the unique ID for this subtype. The input method framework keeps + * track of enabled subtypes by ID. When the IME package gets upgraded, enabled IDs will + * stay enabled even if other attributes are different. If the ID is unspecified or 0, + * Arrays.hashCode(new Object[] {locale, mode, extraValue, + * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead. + */ + public InputMethodSubtypeBuilder setSubtypeId(int subtypeId) { + mSubtypeId = subtypeId; + return this; + } + private int mSubtypeId = 0; + + /** + * @param subtypeLocale is the locale supported by this subtype. + */ + public InputMethodSubtypeBuilder setSubtypeLocale(String subtypeLocale) { + mSubtypeLocale = subtypeLocale == null ? "" : subtypeLocale; + return this; + } + private String mSubtypeLocale = ""; + + /** + * @param subtypeMode is the mode supported by this subtype. + */ + public InputMethodSubtypeBuilder setSubtypeMode(String subtypeMode) { + mSubtypeMode = subtypeMode == null ? "" : subtypeMode; + return this; + } + private String mSubtypeMode = ""; + /** + * @param subtypeExtraValue is the extra value of the subtype. This string is free-form, + * but the API supplies tools to deal with a key-value comma-separated list; see + * {@link #containsExtraValueKey} and {@link #getExtraValueOf}. + */ + public InputMethodSubtypeBuilder setSubtypeExtraValue(String subtypeExtraValue) { + mSubtypeExtraValue = subtypeExtraValue == null ? "" : subtypeExtraValue; + return this; + } + private String mSubtypeExtraValue = ""; + + /** + * @return InputMethodSubtype using parameters in this InputMethodSubtypeBuilder. + */ + public InputMethodSubtype build() { + return new InputMethodSubtype(this); + } + } + + private static InputMethodSubtypeBuilder getBuilder(int nameId, int iconId, String locale, + String mode, String extraValue, boolean isAuxiliary, + boolean overridesImplicitlyEnabledSubtype, int id, boolean isAsciiCapable) { + final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder(); + builder.mSubtypeNameResId = nameId; + builder.mSubtypeIconResId = iconId; + builder.mSubtypeLocale = locale; + builder.mSubtypeMode = mode; + builder.mSubtypeExtraValue = extraValue; + builder.mIsAuxiliary = isAuxiliary; + builder.mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype; + builder.mSubtypeId = id; + builder.mIsAsciiCapable = isAsciiCapable; + return builder; + } + + /** * Constructor with no subtype ID specified, overridesImplicitlyEnabledSubtype not specified. - * @param nameId Resource ID of the subtype name string. The string resource may have exactly - * one %s in it. If there is, the %s part will be replaced with the locale's display name by - * the formatter. Please refer to {@link #getDisplayName} for details. - * @param iconId Resource ID of the subtype icon drawable. - * @param locale The locale supported by the subtype - * @param mode The mode supported by the subtype - * @param extraValue The extra value of the subtype. This string is free-form, but the API - * supplies tools to deal with a key-value comma-separated list; see - * {@link #containsExtraValueKey} and {@link #getExtraValueOf}. - * @param isAuxiliary true when this subtype is auxiliary, false otherwise. An auxiliary - * subtype will not be shown in the list of enabled IMEs for choosing the current IME in - * the Settings even when this subtype is enabled. Please note that this subtype will still - * be shown in the list of IMEs in the IME switcher to allow the user to tentatively switch - * to this subtype while an IME is shown. The framework will never switch the current IME to - * this subtype by {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}. - * The intent of having this flag is to allow for IMEs that are invoked in a one-shot way as - * auxiliary input mode, and return to the previous IME once it is finished (e.g. voice input). + * Arguments for this constructor have the same meanings as + * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean, + * boolean, int)} except "id" and "overridesImplicitlyEnabledSubtype". * @hide */ public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue, @@ -89,27 +211,10 @@ public final class InputMethodSubtype implements Parcelable { /** * Constructor with no subtype ID specified. - * @param nameId Resource ID of the subtype name string. The string resource may have exactly - * one %s in it. If there is, the %s part will be replaced with the locale's display name by - * the formatter. Please refer to {@link #getDisplayName} for details. - * @param iconId Resource ID of the subtype icon drawable. - * @param locale The locale supported by the subtype - * @param mode The mode supported by the subtype - * @param extraValue The extra value of the subtype. This string is free-form, but the API - * supplies tools to deal with a key-value comma-separated list; see - * {@link #containsExtraValueKey} and {@link #getExtraValueOf}. - * @param isAuxiliary true when this subtype is auxiliary, false otherwise. An auxiliary - * subtype will not be shown in the list of enabled IMEs for choosing the current IME in - * the Settings even when this subtype is enabled. Please note that this subtype will still - * be shown in the list of IMEs in the IME switcher to allow the user to tentatively switch - * to this subtype while an IME is shown. The framework will never switch the current IME to - * this subtype by {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}. - * The intent of having this flag is to allow for IMEs that are invoked in a one-shot way as - * auxiliary input mode, and return to the previous IME once it is finished (e.g. voice input). - * @param overridesImplicitlyEnabledSubtype true when this subtype should be enabled by default - * if no other subtypes in the IME are enabled explicitly. Note that a subtype with this - * parameter being true will not be shown in the list of subtypes in each IME's subtype enabler. - * Having an "automatic" subtype is an example use of this flag. + * @deprecated use {@link InputMethodSubtypeBuilder} instead. + * Arguments for this constructor have the same meanings as + * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean, + * boolean, int)} except "id". */ public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) { @@ -119,6 +224,8 @@ public final class InputMethodSubtype implements Parcelable { /** * Constructor. + * @deprecated use {@link InputMethodSubtypeBuilder} instead. + * "isAsciiCapable" is "false" in this constructor. * @param nameId Resource ID of the subtype name string. The string resource may have exactly * one %s in it. If there is, the %s part will be replaced with the locale's display name by * the formatter. Please refer to {@link #getDisplayName} for details. @@ -148,18 +255,29 @@ public final class InputMethodSubtype implements Parcelable { */ public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) { - mSubtypeNameResId = nameId; - mSubtypeIconResId = iconId; - mSubtypeLocale = locale != null ? locale : ""; - mSubtypeMode = mode != null ? mode : ""; - mSubtypeExtraValue = extraValue != null ? extraValue : ""; - mIsAuxiliary = isAuxiliary; - mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype; + this(getBuilder(nameId, iconId, locale, mode, extraValue, isAuxiliary, + overridesImplicitlyEnabledSubtype, id, false)); + } + + /** + * Constructor. + * @param builder Builder for InputMethodSubtype + */ + private InputMethodSubtype(InputMethodSubtypeBuilder builder) { + mSubtypeNameResId = builder.mSubtypeNameResId; + mSubtypeIconResId = builder.mSubtypeIconResId; + mSubtypeLocale = builder.mSubtypeLocale; + mSubtypeMode = builder.mSubtypeMode; + mSubtypeExtraValue = builder.mSubtypeExtraValue; + mIsAuxiliary = builder.mIsAuxiliary; + mOverridesImplicitlyEnabledSubtype = builder.mOverridesImplicitlyEnabledSubtype; + mSubtypeId = builder.mSubtypeId; + mIsAsciiCapable = builder.mIsAsciiCapable; // If hashCode() of this subtype is 0 and you want to specify it as an id of this subtype, // just specify 0 as this subtype's id. Then, this subtype's id is treated as 0. - mSubtypeHashCode = id != 0 ? id : hashCodeInternal(mSubtypeLocale, mSubtypeMode, - mSubtypeExtraValue, mIsAuxiliary, mOverridesImplicitlyEnabledSubtype); - mSubtypeId = id; + mSubtypeHashCode = mSubtypeId != 0 ? mSubtypeId : hashCodeInternal(mSubtypeLocale, + mSubtypeMode, mSubtypeExtraValue, mIsAuxiliary, mOverridesImplicitlyEnabledSubtype, + mIsAsciiCapable); } InputMethodSubtype(Parcel source) { @@ -176,6 +294,7 @@ public final class InputMethodSubtype implements Parcelable { mOverridesImplicitlyEnabledSubtype = (source.readInt() == 1); mSubtypeHashCode = source.readInt(); mSubtypeId = source.readInt(); + mIsAsciiCapable = (source.readInt() == 1); } /** @@ -239,6 +358,15 @@ public final class InputMethodSubtype implements Parcelable { } /** + * @return true if this subtype is Ascii capable, false otherwise. If the subtype is ASCII + * capable, it should guarantee that the user can input ASCII characters with this subtype. + * This is important because many password fields only allow ASCII-characters. + */ + public boolean isAsciiCapable() { + return mIsAsciiCapable; + } + + /** * @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 @@ -336,7 +464,8 @@ public final class InputMethodSubtype implements Parcelable { && (subtype.getIconResId() == getIconResId()) && (subtype.getLocale().equals(getLocale())) && (subtype.getExtraValue().equals(getExtraValue())) - && (subtype.isAuxiliary() == isAuxiliary()); + && (subtype.isAuxiliary() == isAuxiliary()) + && (subtype.isAsciiCapable() == isAsciiCapable()); } return false; } @@ -357,6 +486,7 @@ public final class InputMethodSubtype implements Parcelable { dest.writeInt(mOverridesImplicitlyEnabledSubtype ? 1 : 0); dest.writeInt(mSubtypeHashCode); dest.writeInt(mSubtypeId); + dest.writeInt(mIsAsciiCapable ? 1 : 0); } public static final Parcelable.Creator CREATOR @@ -389,9 +519,10 @@ public final class InputMethodSubtype implements Parcelable { } private static int hashCodeInternal(String locale, String mode, String extraValue, - boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) { + boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, + boolean isAsciiCapable) { return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary, - overridesImplicitlyEnabledSubtype}); + overridesImplicitlyEnabledSubtype, isAsciiCapable}); } /** diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 15edacd..4cad232 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2407,6 +2407,11 @@ constructor or 0. Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead. --> + +