InputMethodSubtype.java revision 5df0631003392c416c9617458dc2814f9eaec317
1ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok/*
2ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * Copyright (C) 2010 The Android Open Source Project
3ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *
4ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * Licensed under the Apache License, Version 2.0 (the "License");
5ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * you may not use this file except in compliance with the License.
6ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * You may obtain a copy of the License at
7ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *
8ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *      http://www.apache.org/licenses/LICENSE-2.0
9ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *
10ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * Unless required by applicable law or agreed to in writing, software
11ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * distributed under the License is distributed on an "AS IS" BASIS,
12ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * See the License for the specific language governing permissions and
14ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * limitations under the License.
15ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok */
16ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
17ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokpackage android.view.inputmethod;
18ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
197265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport android.content.Context;
204f31353cb3b00c77c9420ef27ec949fd570ede3bsatokimport android.content.pm.ApplicationInfo;
21ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.os.Parcel;
22ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.os.Parcelable;
234f31353cb3b00c77c9420ef27ec949fd570ede3bsatokimport android.text.TextUtils;
249c4cc03a354922df08efacfc486ef0e80144d3easatokimport android.util.Slog;
25ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
267265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.ArrayList;
27ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport java.util.Arrays;
289c4cc03a354922df08efacfc486ef0e80144d3easatokimport java.util.HashMap;
297265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.HashSet;
3083e675f5ecf9f5615f3179ac102176faa3ae2596satokimport java.util.IllegalFormatException;
317265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.List;
32a9778d4d442db65344e32318b1fd43ab54898389satokimport java.util.Locale;
33ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
34ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok/**
359a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa * This class is used to specify meta information of a subtype contained in an input method editor
369a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa * (IME). Subtype can describe locale (e.g. en_US, fr_FR...) and mode (e.g. voice, keyboard...),
379a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa * and is used for IME switch and settings. The input method subtype allows the system to bring up
389a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa * the specified subtype of the designated IME directly.
3944b75030931d9c65c9e495a86d11d71da59b4429satok *
409a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa * <p>It should be defined in an XML resource file of the input method with the
415df0631003392c416c9617458dc2814f9eaec317Scott Main * <code>&lt;subtype&gt;</code> element, which resides within an {@code &lt;input-method>} element.
425df0631003392c416c9617458dc2814f9eaec317Scott Main * For more information, see the guide to
435df0631003392c416c9617458dc2814f9eaec317Scott Main * <a href="{@docRoot}guide/topics/text/creating-input-method.html">
4444b75030931d9c65c9e495a86d11d71da59b4429satok * Creating an Input Method</a>.</p>
455df0631003392c416c9617458dc2814f9eaec317Scott Main *
465df0631003392c416c9617458dc2814f9eaec317Scott Main * @see InputMethodInfo
475df0631003392c416c9617458dc2814f9eaec317Scott Main *
485df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_label
495df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_icon
505df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeLocale
515df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeMode
525df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeExtraValue
535df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_isAuxiliary
545df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_overridesImplicitlyEnabledSubtype
555df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_subtypeId
565df0631003392c416c9617458dc2814f9eaec317Scott Main * @attr ref android.R.styleable#InputMethod_Subtype_isAsciiCapable
57ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok */
58ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokpublic final class InputMethodSubtype implements Parcelable {
599c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String TAG = InputMethodSubtype.class.getSimpleName();
609c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
619c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
6283e675f5ecf9f5615f3179ac102176faa3ae2596satok    // TODO: remove this
6383e675f5ecf9f5615f3179ac102176faa3ae2596satok    private static final String EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
6483e675f5ecf9f5615f3179ac102176faa3ae2596satok            "UntranslatableReplacementStringInSubtypeName";
659c4cc03a354922df08efacfc486ef0e80144d3easatok
669aabb95781bee6a44684a6f6feb155e115d24983satok    private final boolean mIsAuxiliary;
67a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok    private final boolean mOverridesImplicitlyEnabledSubtype;
68dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    private final boolean mIsAsciiCapable;
699aabb95781bee6a44684a6f6feb155e115d24983satok    private final int mSubtypeHashCode;
70ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final int mSubtypeIconResId;
719aabb95781bee6a44684a6f6feb155e115d24983satok    private final int mSubtypeNameResId;
72e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka    private final int mSubtypeId;
73ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final String mSubtypeLocale;
749ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    private final String mSubtypeMode;
75ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final String mSubtypeExtraValue;
76e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok    private volatile HashMap<String, String> mExtraValueHashMapCache;
77ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
78ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
79dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * InputMethodSubtypeBuilder is a builder class of InputMethodSubtype.
80dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * This class is designed to be used with
81dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * {@link android.view.inputmethod.InputMethodManager#setAdditionalInputMethodSubtypes}.
82dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * The developer needs to be aware of what each parameter means.
83dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     */
84dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    public static class InputMethodSubtypeBuilder {
85dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
86dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param isAuxiliary should true when this subtype is auxiliary, false otherwise.
87dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * An auxiliary subtype has the following differences with a regular subtype:
88dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * - An auxiliary subtype cannot be chosen as the default IME in Settings.
89dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * - The framework will never switch to this subtype through
90dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         *   {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}.
91dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * Note that the subtype will still be available in the IME switcher.
92dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * The intent is to allow for IMEs to specify they are meant to be invoked temporarily
93dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * in a one-shot way, and to return to the previous IME once finished (e.g. voice input).
94dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
95dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setIsAuxiliary(boolean isAuxiliary) {
96dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mIsAuxiliary = isAuxiliary;
97dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
98dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
99dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private boolean mIsAuxiliary = false;
100dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
101dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
102dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param overridesImplicitlyEnabledSubtype should be true if this subtype should be
103dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * enabled by default if no other subtypes in the IME are enabled explicitly. Note that a
104dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * subtype with this parameter set will not be shown in the list of subtypes in each IME's
105dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * subtype enabler. A canonical use of this would be for an IME to supply an "automatic"
106dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * subtype that adapts to the current system language.
107dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
108dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setOverridesImplicitlyEnabledSubtype(
109dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                boolean overridesImplicitlyEnabledSubtype) {
110dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype;
111dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
112dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
113dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private boolean mOverridesImplicitlyEnabledSubtype = false;
114dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
115dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
116dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param isAsciiCapable should be true if this subtype is ASCII capable. If the subtype
117dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * is ASCII capable, it should guarantee that the user can input ASCII characters with
118dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * this subtype. This is important because many password fields only allow
119dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * ASCII-characters.
120dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
121dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setIsAsciiCapable(boolean isAsciiCapable) {
122dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mIsAsciiCapable = isAsciiCapable;
123dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
124dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
125dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private boolean mIsAsciiCapable = false;
126dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
127dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
128dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param subtypeIconResId is a resource ID of the subtype icon drawable.
129dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
130dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setSubtypeIconResId(int subtypeIconResId) {
131dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mSubtypeIconResId = subtypeIconResId;
132dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
133dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
134dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private int mSubtypeIconResId = 0;
135dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
136dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
137dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param subtypeNameResId is the resource ID of the subtype name string.
138dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * The string resource may have exactly one %s in it. If present,
139dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * the %s part will be replaced with the locale's display name by
140dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * the formatter. Please refer to {@link #getDisplayName} for details.
141dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
142dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setSubtypeNameResId(int subtypeNameResId) {
143dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mSubtypeNameResId = subtypeNameResId;
144dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
145dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
146dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private int mSubtypeNameResId = 0;
147dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
148dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
149dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param subtypeId is the unique ID for this subtype. The input method framework keeps
150dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * track of enabled subtypes by ID. When the IME package gets upgraded, enabled IDs will
151dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * stay enabled even if other attributes are different. If the ID is unspecified or 0,
152dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * Arrays.hashCode(new Object[] {locale, mode, extraValue,
153dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
154dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
155dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setSubtypeId(int subtypeId) {
156dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mSubtypeId = subtypeId;
157dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
158dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
159dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private int mSubtypeId = 0;
160dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
161dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
162dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param subtypeLocale is the locale supported by this subtype.
163dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
164dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setSubtypeLocale(String subtypeLocale) {
165dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mSubtypeLocale = subtypeLocale == null ? "" : subtypeLocale;
166dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
167dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
168dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private String mSubtypeLocale = "";
169dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
170dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
171dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param subtypeMode is the mode supported by this subtype.
172dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
173dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setSubtypeMode(String subtypeMode) {
174dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mSubtypeMode = subtypeMode == null ? "" : subtypeMode;
175dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
176dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
177dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private String mSubtypeMode = "";
178dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
179dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @param subtypeExtraValue is the extra value of the subtype. This string is free-form,
180dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * but the API supplies tools to deal with a key-value comma-separated list; see
181dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * {@link #containsExtraValueKey} and {@link #getExtraValueOf}.
182dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
183dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtypeBuilder setSubtypeExtraValue(String subtypeExtraValue) {
184dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            mSubtypeExtraValue = subtypeExtraValue == null ? "" : subtypeExtraValue;
185dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return this;
186dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
187dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        private String mSubtypeExtraValue = "";
188dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
189dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        /**
190dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         * @return InputMethodSubtype using parameters in this InputMethodSubtypeBuilder.
191dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         */
192dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        public InputMethodSubtype build() {
193dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            return new InputMethodSubtype(this);
194dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        }
195dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     }
196dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
197dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     private static InputMethodSubtypeBuilder getBuilder(int nameId, int iconId, String locale,
198dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka             String mode, String extraValue, boolean isAuxiliary,
199dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka             boolean overridesImplicitlyEnabledSubtype, int id, boolean isAsciiCapable) {
200dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
201dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mSubtypeNameResId = nameId;
202dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mSubtypeIconResId = iconId;
203dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mSubtypeLocale = locale;
204dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mSubtypeMode = mode;
205dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mSubtypeExtraValue = extraValue;
206dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mIsAuxiliary = isAuxiliary;
207dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype;
208dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mSubtypeId = id;
209dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         builder.mIsAsciiCapable = isAsciiCapable;
210dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka         return builder;
211dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     }
212dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
213dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    /**
214e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * Constructor with no subtype ID specified, overridesImplicitlyEnabledSubtype not specified.
215dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * Arguments for this constructor have the same meanings as
216dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean,
217dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * boolean, int)} except "id" and "overridesImplicitlyEnabledSubtype".
2183889e492bcad3c6f565d30da4e02d0dcde09d084satok     * @hide
219ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
220a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok    public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
221a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            boolean isAuxiliary) {
2228b83a7297680911d666546ee0b3a464514dc2c27Ken Wakasa        this(nameId, iconId, locale, mode, extraValue, isAuxiliary, false);
2239aabb95781bee6a44684a6f6feb155e115d24983satok    }
2249aabb95781bee6a44684a6f6feb155e115d24983satok
2259aabb95781bee6a44684a6f6feb155e115d24983satok    /**
226e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * Constructor with no subtype ID specified.
227dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * @deprecated use {@link InputMethodSubtypeBuilder} instead.
228dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * Arguments for this constructor have the same meanings as
229dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean,
230dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * boolean, int)} except "id".
2319aabb95781bee6a44684a6f6feb155e115d24983satok     */
232a9778d4d442db65344e32318b1fd43ab54898389satok    public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
233a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
234e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        this(nameId, iconId, locale, mode, extraValue, isAuxiliary,
235e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                overridesImplicitlyEnabledSubtype, 0);
236e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka    }
237e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka
238e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka    /**
239e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * Constructor.
240dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * @deprecated use {@link InputMethodSubtypeBuilder} instead.
241dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * "isAsciiCapable" is "false" in this constructor.
242e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param nameId Resource ID of the subtype name string. The string resource may have exactly
243e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * one %s in it. If there is, the %s part will be replaced with the locale's display name by
244e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * the formatter. Please refer to {@link #getDisplayName} for details.
245e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param iconId Resource ID of the subtype icon drawable.
246e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param locale The locale supported by the subtype
247e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param mode The mode supported by the subtype
248e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param extraValue The extra value of the subtype. This string is free-form, but the API
249e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * supplies tools to deal with a key-value comma-separated list; see
250e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * {@link #containsExtraValueKey} and {@link #getExtraValueOf}.
251e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param isAuxiliary true when this subtype is auxiliary, false otherwise. An auxiliary
252e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * subtype will not be shown in the list of enabled IMEs for choosing the current IME in
253e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * the Settings even when this subtype is enabled. Please note that this subtype will still
254e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * be shown in the list of IMEs in the IME switcher to allow the user to tentatively switch
255e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * to this subtype while an IME is shown. The framework will never switch the current IME to
256e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * this subtype by {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}.
257e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * The intent of having this flag is to allow for IMEs that are invoked in a one-shot way as
258e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * auxiliary input mode, and return to the previous IME once it is finished (e.g. voice input).
259e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param overridesImplicitlyEnabledSubtype true when this subtype should be enabled by default
260e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * if no other subtypes in the IME are enabled explicitly. Note that a subtype with this
261e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * parameter being true will not be shown in the list of subtypes in each IME's subtype enabler.
262e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * Having an "automatic" subtype is an example use of this flag.
263e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * @param id The unique ID for the subtype. The input method framework keeps track of enabled
264e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * subtypes by ID. When the IME package gets upgraded, enabled IDs will stay enabled even if
265e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * other attributes are different. If the ID is unspecified or 0,
266e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * Arrays.hashCode(new Object[] {locale, mode, extraValue,
267e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
268e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka     */
269e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka    public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
270e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) {
271dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        this(getBuilder(nameId, iconId, locale, mode, extraValue, isAuxiliary,
272dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                overridesImplicitlyEnabledSubtype, id, false));
273dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    }
274dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
275dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    /**
276dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * Constructor.
277dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * @param builder Builder for InputMethodSubtype
278dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     */
279dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    private InputMethodSubtype(InputMethodSubtypeBuilder builder) {
280dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeNameResId = builder.mSubtypeNameResId;
281dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeIconResId = builder.mSubtypeIconResId;
282dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeLocale = builder.mSubtypeLocale;
283dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeMode = builder.mSubtypeMode;
284dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeExtraValue = builder.mSubtypeExtraValue;
285dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mIsAuxiliary = builder.mIsAuxiliary;
286dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mOverridesImplicitlyEnabledSubtype = builder.mOverridesImplicitlyEnabledSubtype;
287dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeId = builder.mSubtypeId;
288dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mIsAsciiCapable = builder.mIsAsciiCapable;
289e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        // If hashCode() of this subtype is 0 and you want to specify it as an id of this subtype,
290e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        // just specify 0 as this subtype's id. Then, this subtype's id is treated as 0.
291dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mSubtypeHashCode = mSubtypeId != 0 ? mSubtypeId : hashCodeInternal(mSubtypeLocale,
292dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                mSubtypeMode, mSubtypeExtraValue, mIsAuxiliary, mOverridesImplicitlyEnabledSubtype,
293dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                mIsAsciiCapable);
294ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
295ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
296ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    InputMethodSubtype(Parcel source) {
297af4bf400abab86baee44dacbcdf13444d06ee46esatok        String s;
298ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeNameResId = source.readInt();
299ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeIconResId = source.readInt();
300af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
301af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeLocale = s != null ? s : "";
302af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
303af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeMode = s != null ? s : "";
304af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
305af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeExtraValue = s != null ? s : "";
3069aabb95781bee6a44684a6f6feb155e115d24983satok        mIsAuxiliary = (source.readInt() == 1);
307a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok        mOverridesImplicitlyEnabledSubtype = (source.readInt() == 1);
308e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        mSubtypeHashCode = source.readInt();
309e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        mSubtypeId = source.readInt();
310dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        mIsAsciiCapable = (source.readInt() == 1);
311ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
312ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
313ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3149a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return Resource ID of the subtype name string.
315ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
316ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int getNameResId() {
317ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeNameResId;
318ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
319ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
320ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3219a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return Resource ID of the subtype icon drawable.
322ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
323ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int getIconResId() {
324ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeIconResId;
325ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
326ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
327ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3289a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return The locale of the subtype. This method returns the "locale" string parameter passed
3299a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * to the constructor.
330ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
331ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public String getLocale() {
332ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeLocale;
333ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
334ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
335ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3369a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return The mode of the subtype.
337ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
3389ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    public String getMode() {
3399ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        return mSubtypeMode;
340ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
341ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
342ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3439a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return The extra value of the subtype.
344ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
345ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public String getExtraValue() {
346ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeExtraValue;
347ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
348ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3499aabb95781bee6a44684a6f6feb155e115d24983satok    /**
3509a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return true if this subtype is auxiliary, false otherwise. An auxiliary subtype will not be
3519a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * shown in the list of enabled IMEs for choosing the current IME in the Settings even when this
3529a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * subtype is enabled. Please note that this subtype will still be shown in the list of IMEs in
3539a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * the IME switcher to allow the user to tentatively switch to this subtype while an IME is
3549a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * shown. The framework will never switch the current IME to this subtype by
3559a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}.
3569a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * The intent of having this flag is to allow for IMEs that are invoked in a one-shot way as
3579a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * auxiliary input mode, and return to the previous IME once it is finished (e.g. voice input).
3589aabb95781bee6a44684a6f6feb155e115d24983satok     */
3599aabb95781bee6a44684a6f6feb155e115d24983satok    public boolean isAuxiliary() {
3609aabb95781bee6a44684a6f6feb155e115d24983satok        return mIsAuxiliary;
3619aabb95781bee6a44684a6f6feb155e115d24983satok    }
3629aabb95781bee6a44684a6f6feb155e115d24983satok
3634f31353cb3b00c77c9420ef27ec949fd570ede3bsatok    /**
3649a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return true when this subtype will be enabled by default if no other subtypes in the IME
3659a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * are enabled explicitly, false otherwise. Note that a subtype with this method returning true
3669a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * will not be shown in the list of subtypes in each IME's subtype enabler. Having an
3679a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * "automatic" subtype is an example use of this flag.
368a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok     */
369a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok    public boolean overridesImplicitlyEnabledSubtype() {
370a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok        return mOverridesImplicitlyEnabledSubtype;
371a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok    }
372a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok
373a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok    /**
374dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * @return true if this subtype is Ascii capable, false otherwise. If the subtype is ASCII
375dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * capable, it should guarantee that the user can input ASCII characters with this subtype.
376dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     * This is important because many password fields only allow ASCII-characters.
377dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka     */
378dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    public boolean isAsciiCapable() {
379dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        return mIsAsciiCapable;
380dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    }
381dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka
382dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka    /**
3834f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @param context Context will be used for getting Locale and PackageManager.
3844f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @param packageName The package name of the IME
3854f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @param appInfo The application info of the IME
3864f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
3879a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * may have exactly one %s in it. If there is, the %s part will be replaced with the locale's
3889a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * display name by the formatter. If there is not, this method returns the string specified by
3899a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the framework to
3909a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * generate an appropriate display name.
3914f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     */
3924f31353cb3b00c77c9420ef27ec949fd570ede3bsatok    public CharSequence getDisplayName(
3934f31353cb3b00c77c9420ef27ec949fd570ede3bsatok            Context context, String packageName, ApplicationInfo appInfo) {
394a9778d4d442db65344e32318b1fd43ab54898389satok        final Locale locale = constructLocaleFromString(mSubtypeLocale);
395a9778d4d442db65344e32318b1fd43ab54898389satok        final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
3964f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        if (mSubtypeNameResId == 0) {
397a9778d4d442db65344e32318b1fd43ab54898389satok            return localeStr;
3984f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        }
39935412d63ee59b99a43725e466c5deef52b2324dfsatok        final CharSequence subtypeName = context.getPackageManager().getText(
40035412d63ee59b99a43725e466c5deef52b2324dfsatok                packageName, mSubtypeNameResId, appInfo);
4014f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        if (!TextUtils.isEmpty(subtypeName)) {
40283e675f5ecf9f5615f3179ac102176faa3ae2596satok            final String replacementString =
40383e675f5ecf9f5615f3179ac102176faa3ae2596satok                    containsExtraValueKey(EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
40483e675f5ecf9f5615f3179ac102176faa3ae2596satok                            ? getExtraValueOf(EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
40583e675f5ecf9f5615f3179ac102176faa3ae2596satok                            : localeStr;
40683e675f5ecf9f5615f3179ac102176faa3ae2596satok            try {
40783e675f5ecf9f5615f3179ac102176faa3ae2596satok                return String.format(
40883e675f5ecf9f5615f3179ac102176faa3ae2596satok                        subtypeName.toString(), replacementString != null ? replacementString : "");
40983e675f5ecf9f5615f3179ac102176faa3ae2596satok            } catch (IllegalFormatException e) {
41083e675f5ecf9f5615f3179ac102176faa3ae2596satok                Slog.w(TAG, "Found illegal format in subtype name("+ subtypeName + "): " + e);
41183e675f5ecf9f5615f3179ac102176faa3ae2596satok                return "";
41283e675f5ecf9f5615f3179ac102176faa3ae2596satok            }
4134f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        } else {
414a9778d4d442db65344e32318b1fd43ab54898389satok            return localeStr;
4154f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        }
4164f31353cb3b00c77c9420ef27ec949fd570ede3bsatok    }
4174f31353cb3b00c77c9420ef27ec949fd570ede3bsatok
4189c4cc03a354922df08efacfc486ef0e80144d3easatok    private HashMap<String, String> getExtraValueHashMap() {
4199c4cc03a354922df08efacfc486ef0e80144d3easatok        if (mExtraValueHashMapCache == null) {
420e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok            synchronized(this) {
421e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                if (mExtraValueHashMapCache == null) {
422e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                    mExtraValueHashMapCache = new HashMap<String, String>();
423e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                    final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
424e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                    final int N = pairs.length;
425e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                    for (int i = 0; i < N; ++i) {
426e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                        final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
427e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                        if (pair.length == 1) {
428e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                            mExtraValueHashMapCache.put(pair[0], null);
429e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                        } else if (pair.length > 1) {
430e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                            if (pair.length > 2) {
431e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                                Slog.w(TAG, "ExtraValue has two or more '='s");
432e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                            }
433e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                            mExtraValueHashMapCache.put(pair[0], pair[1]);
434e52eb4e289bf8d7b04582803b0d0f9ab7399c1afsatok                        }
4359c4cc03a354922df08efacfc486ef0e80144d3easatok                    }
4369c4cc03a354922df08efacfc486ef0e80144d3easatok                }
4379c4cc03a354922df08efacfc486ef0e80144d3easatok            }
4389c4cc03a354922df08efacfc486ef0e80144d3easatok        }
4399c4cc03a354922df08efacfc486ef0e80144d3easatok        return mExtraValueHashMapCache;
4409c4cc03a354922df08efacfc486ef0e80144d3easatok    }
4419c4cc03a354922df08efacfc486ef0e80144d3easatok
4429c4cc03a354922df08efacfc486ef0e80144d3easatok    /**
4439c4cc03a354922df08efacfc486ef0e80144d3easatok     * The string of ExtraValue in subtype should be defined as follows:
4449c4cc03a354922df08efacfc486ef0e80144d3easatok     * example: key0,key1=value1,key2,key3,key4=value4
4459a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @param key The key of extra value
4469a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return The subtype contains specified the extra value
4479c4cc03a354922df08efacfc486ef0e80144d3easatok     */
4489c4cc03a354922df08efacfc486ef0e80144d3easatok    public boolean containsExtraValueKey(String key) {
4499c4cc03a354922df08efacfc486ef0e80144d3easatok        return getExtraValueHashMap().containsKey(key);
4509c4cc03a354922df08efacfc486ef0e80144d3easatok    }
4519c4cc03a354922df08efacfc486ef0e80144d3easatok
4529c4cc03a354922df08efacfc486ef0e80144d3easatok    /**
4539c4cc03a354922df08efacfc486ef0e80144d3easatok     * The string of ExtraValue in subtype should be defined as follows:
4549c4cc03a354922df08efacfc486ef0e80144d3easatok     * example: key0,key1=value1,key2,key3,key4=value4
4559a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @param key The key of extra value
4569a74476c0ab1aaa59e9aed6ecdeba43d5b4d3495Ken Wakasa     * @return The value of the specified key
4579c4cc03a354922df08efacfc486ef0e80144d3easatok     */
4589c4cc03a354922df08efacfc486ef0e80144d3easatok    public String getExtraValueOf(String key) {
4599c4cc03a354922df08efacfc486ef0e80144d3easatok        return getExtraValueHashMap().get(key);
4609c4cc03a354922df08efacfc486ef0e80144d3easatok    }
4619c4cc03a354922df08efacfc486ef0e80144d3easatok
462ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
463ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int hashCode() {
464ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeHashCode;
465ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
466ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
467ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
468ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public boolean equals(Object o) {
469ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        if (o instanceof InputMethodSubtype) {
470ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            InputMethodSubtype subtype = (InputMethodSubtype) o;
471e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka            if (subtype.mSubtypeId != 0 || mSubtypeId != 0) {
472e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return (subtype.hashCode() == hashCode());
473e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka            }
474af4bf400abab86baee44dacbcdf13444d06ee46esatok            return (subtype.hashCode() == hashCode())
475af4bf400abab86baee44dacbcdf13444d06ee46esatok                && (subtype.getNameResId() == getNameResId())
476af4bf400abab86baee44dacbcdf13444d06ee46esatok                && (subtype.getMode().equals(getMode()))
477ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getIconResId() == getIconResId())
478ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getLocale().equals(getLocale()))
479a9778d4d442db65344e32318b1fd43ab54898389satok                && (subtype.getExtraValue().equals(getExtraValue()))
480dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                && (subtype.isAuxiliary() == isAuxiliary())
481dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                && (subtype.isAsciiCapable() == isAsciiCapable());
482ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
483ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return false;
484ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
485ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
4869aabb95781bee6a44684a6f6feb155e115d24983satok    @Override
487ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int describeContents() {
488ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return 0;
489ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
490ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
4919aabb95781bee6a44684a6f6feb155e115d24983satok    @Override
492ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public void writeToParcel(Parcel dest, int parcelableFlags) {
493ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeInt(mSubtypeNameResId);
494ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeInt(mSubtypeIconResId);
495ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeString(mSubtypeLocale);
4969ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        dest.writeString(mSubtypeMode);
497ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeString(mSubtypeExtraValue);
4989aabb95781bee6a44684a6f6feb155e115d24983satok        dest.writeInt(mIsAuxiliary ? 1 : 0);
499a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok        dest.writeInt(mOverridesImplicitlyEnabledSubtype ? 1 : 0);
500e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        dest.writeInt(mSubtypeHashCode);
501e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        dest.writeInt(mSubtypeId);
502dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka        dest.writeInt(mIsAsciiCapable ? 1 : 0);
503ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
504ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
505ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public static final Parcelable.Creator<InputMethodSubtype> CREATOR
506ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            = new Parcelable.Creator<InputMethodSubtype>() {
5079aabb95781bee6a44684a6f6feb155e115d24983satok        @Override
508ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public InputMethodSubtype createFromParcel(Parcel source) {
509ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            return new InputMethodSubtype(source);
510ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
511ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
5129aabb95781bee6a44684a6f6feb155e115d24983satok        @Override
513ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public InputMethodSubtype[] newArray(int size) {
514ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            return new InputMethodSubtype[size];
515ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
516ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    };
517ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
518a9778d4d442db65344e32318b1fd43ab54898389satok    private static Locale constructLocaleFromString(String localeStr) {
519a9778d4d442db65344e32318b1fd43ab54898389satok        if (TextUtils.isEmpty(localeStr))
520a9778d4d442db65344e32318b1fd43ab54898389satok            return null;
521a9778d4d442db65344e32318b1fd43ab54898389satok        String[] localeParams = localeStr.split("_", 3);
522a9778d4d442db65344e32318b1fd43ab54898389satok        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
523a9778d4d442db65344e32318b1fd43ab54898389satok        // because localeStr is not empty.
524a9778d4d442db65344e32318b1fd43ab54898389satok        if (localeParams.length == 1) {
525a9778d4d442db65344e32318b1fd43ab54898389satok            return new Locale(localeParams[0]);
526a9778d4d442db65344e32318b1fd43ab54898389satok        } else if (localeParams.length == 2) {
527a9778d4d442db65344e32318b1fd43ab54898389satok            return new Locale(localeParams[0], localeParams[1]);
528a9778d4d442db65344e32318b1fd43ab54898389satok        } else if (localeParams.length == 3) {
529a9778d4d442db65344e32318b1fd43ab54898389satok            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
530a9778d4d442db65344e32318b1fd43ab54898389satok        }
531a9778d4d442db65344e32318b1fd43ab54898389satok        return null;
532a9778d4d442db65344e32318b1fd43ab54898389satok    }
533a9778d4d442db65344e32318b1fd43ab54898389satok
534a9778d4d442db65344e32318b1fd43ab54898389satok    private static int hashCodeInternal(String locale, String mode, String extraValue,
535dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
536dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka            boolean isAsciiCapable) {
537a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok        return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary,
538dc8abf6cee0bcf44e2cad8155f0c151105d46471Satoshi Kataoka                overridesImplicitlyEnabledSubtype, isAsciiCapable});
539ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
5407265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok
5417265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    /**
5427265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * Sort the list of InputMethodSubtype
5437265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param context Context will be used for getting localized strings from IME
5447265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param flags Flags for the sort order
5457265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param imi InputMethodInfo of which subtypes are subject to be sorted
5467265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param subtypeList List of InputMethodSubtype which will be sorted
5477265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @return Sorted list of subtypes
5487265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @hide
5497265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     */
5507265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi,
5517265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            List<InputMethodSubtype> subtypeList) {
5527265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        if (imi == null) return subtypeList;
5537265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>(
5547265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                subtypeList);
5557265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>();
5567265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        int N = imi.getSubtypeCount();
5577265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        for (int i = 0; i < N; ++i) {
5587265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            InputMethodSubtype subtype = imi.getSubtypeAt(i);
5597265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            if (inputSubtypesSet.contains(subtype)) {
5607265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                sortedList.add(subtype);
5617265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                inputSubtypesSet.remove(subtype);
5627265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            }
5637265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        }
5647265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        // If subtypes in inputSubtypesSet remain, that means these subtypes are not
5657265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        // contained in imi, so the remaining subtypes will be appended.
5667265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        for (InputMethodSubtype subtype: inputSubtypesSet) {
5677265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            sortedList.add(subtype);
5687265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        }
5697265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        return sortedList;
5707265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    }
571af4bf400abab86baee44dacbcdf13444d06ee46esatok}
572