InputMethodSubtype.java revision 4f31353cb3b00c77c9420ef27ec949fd570ede3b
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;
307265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.List;
31ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
32ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok/**
33e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * This class is used to specify meta information of a subtype contained in an input method.
34e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * Subtype can describe locale (e.g. en_US, fr_FR...) and mode (e.g. voice, keyboard...), and is
35e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * used for IME switch and settings. The input method subtype allows the system to bring up the
36e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * specified subtype of the designated input method directly.
37ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok */
38ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokpublic final class InputMethodSubtype implements Parcelable {
399c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String TAG = InputMethodSubtype.class.getSimpleName();
409c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
419c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
429c4cc03a354922df08efacfc486ef0e80144d3easatok
439aabb95781bee6a44684a6f6feb155e115d24983satok    private final boolean mIsAuxiliary;
449aabb95781bee6a44684a6f6feb155e115d24983satok    private final int mSubtypeHashCode;
45ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final int mSubtypeIconResId;
469aabb95781bee6a44684a6f6feb155e115d24983satok    private final int mSubtypeNameResId;
47ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final String mSubtypeLocale;
489ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    private final String mSubtypeMode;
49ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final String mSubtypeExtraValue;
509c4cc03a354922df08efacfc486ef0e80144d3easatok    private HashMap<String, String> mExtraValueHashMapCache;
51ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
52ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
53ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * Constructor
54ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param nameId The name of the subtype
55ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param iconId The icon of the subtype
56ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param locale The locale supported by the subtype
57ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param modeId The mode supported by the subtype
58ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param extraValue The extra value of the subtype
59ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
609ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue) {
619aabb95781bee6a44684a6f6feb155e115d24983satok        this(nameId, iconId, locale, mode, extraValue, false);
629aabb95781bee6a44684a6f6feb155e115d24983satok    }
639aabb95781bee6a44684a6f6feb155e115d24983satok
649aabb95781bee6a44684a6f6feb155e115d24983satok    /**
659aabb95781bee6a44684a6f6feb155e115d24983satok     * Constructor
669aabb95781bee6a44684a6f6feb155e115d24983satok     * @param nameId The name of the subtype
679aabb95781bee6a44684a6f6feb155e115d24983satok     * @param iconId The icon of the subtype
689aabb95781bee6a44684a6f6feb155e115d24983satok     * @param locale The locale supported by the subtype
699aabb95781bee6a44684a6f6feb155e115d24983satok     * @param modeId The mode supported by the subtype
709aabb95781bee6a44684a6f6feb155e115d24983satok     * @param extraValue The extra value of the subtype
719aabb95781bee6a44684a6f6feb155e115d24983satok     * @param isAuxiliary true when this subtype is one shot subtype.
729aabb95781bee6a44684a6f6feb155e115d24983satok     */
739aabb95781bee6a44684a6f6feb155e115d24983satok    InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
749aabb95781bee6a44684a6f6feb155e115d24983satok            boolean isAuxiliary) {
75ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeNameResId = nameId;
76ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeIconResId = iconId;
77af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeLocale = locale != null ? locale : "";
78af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeMode = mode != null ? mode : "";
79af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeExtraValue = extraValue != null ? extraValue : "";
80ece92d34fcf273f68f33d2fd8e5764764fc0c66dsatok        mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
819aabb95781bee6a44684a6f6feb155e115d24983satok        mIsAuxiliary = isAuxiliary;
82ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
83ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
84ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    InputMethodSubtype(Parcel source) {
85af4bf400abab86baee44dacbcdf13444d06ee46esatok        String s;
86ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeNameResId = source.readInt();
87ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeIconResId = source.readInt();
88af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
89af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeLocale = s != null ? s : "";
90af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
91af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeMode = s != null ? s : "";
92af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
93af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeExtraValue = s != null ? s : "";
94ece92d34fcf273f68f33d2fd8e5764764fc0c66dsatok        mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
959aabb95781bee6a44684a6f6feb155e115d24983satok        mIsAuxiliary = (source.readInt() == 1);
96ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
97ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
98ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
99ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the name of the subtype
100ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
101ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int getNameResId() {
102ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeNameResId;
103ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
104ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
105ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
106ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the icon of the subtype
107ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
108ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int getIconResId() {
109ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeIconResId;
110ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
111ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
112ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
113ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the locale of the subtype
114ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
115ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public String getLocale() {
116ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeLocale;
117ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
118ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
119ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
120ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the mode of the subtype
121ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
1229ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    public String getMode() {
1239ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        return mSubtypeMode;
124ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
125ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
126ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
127ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the extra value of the subtype
128ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
129ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public String getExtraValue() {
130ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeExtraValue;
131ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
132ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
1339aabb95781bee6a44684a6f6feb155e115d24983satok    /**
1349aabb95781bee6a44684a6f6feb155e115d24983satok     * @return true if this subtype is one shot subtype. One shot subtype will not be shown in the
1359aabb95781bee6a44684a6f6feb155e115d24983satok     * ime switch list when this subtype is implicitly enabled. The framework will never
1369aabb95781bee6a44684a6f6feb155e115d24983satok     * switch the current ime to this subtype by switchToLastInputMethod in InputMethodManager.
1379aabb95781bee6a44684a6f6feb155e115d24983satok     */
1389aabb95781bee6a44684a6f6feb155e115d24983satok    public boolean isAuxiliary() {
1399aabb95781bee6a44684a6f6feb155e115d24983satok        return mIsAuxiliary;
1409aabb95781bee6a44684a6f6feb155e115d24983satok    }
1419aabb95781bee6a44684a6f6feb155e115d24983satok
1424f31353cb3b00c77c9420ef27ec949fd570ede3bsatok    /**
1434f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @param context Context will be used for getting Locale and PackageManager.
1444f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @param packageName The package name of the IME
1454f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @param appInfo The application info of the IME
1464f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
1474f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * can have only one %s in it. If there is, the %s part will be replaced with the locale's
1484f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * display name by the formatter. If there is not, this method simply returns the string
1494f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * specified by mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the
1504f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     * framework to generate an appropriate display name.
1514f31353cb3b00c77c9420ef27ec949fd570ede3bsatok     */
1524f31353cb3b00c77c9420ef27ec949fd570ede3bsatok    public CharSequence getDisplayName(
1534f31353cb3b00c77c9420ef27ec949fd570ede3bsatok            Context context, String packageName, ApplicationInfo appInfo) {
1544f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        final String locale = context.getResources().getConfiguration().locale.getDisplayName();
1554f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        if (mSubtypeNameResId == 0) {
1564f31353cb3b00c77c9420ef27ec949fd570ede3bsatok            return locale;
1574f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        }
1584f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        final String subtypeName = context.getPackageManager().getText(
1594f31353cb3b00c77c9420ef27ec949fd570ede3bsatok                packageName, mSubtypeNameResId, appInfo).toString();
1604f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        if (!TextUtils.isEmpty(subtypeName)) {
1614f31353cb3b00c77c9420ef27ec949fd570ede3bsatok            return String.format(subtypeName, locale);
1624f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        } else {
1634f31353cb3b00c77c9420ef27ec949fd570ede3bsatok            return locale;
1644f31353cb3b00c77c9420ef27ec949fd570ede3bsatok        }
1654f31353cb3b00c77c9420ef27ec949fd570ede3bsatok    }
1664f31353cb3b00c77c9420ef27ec949fd570ede3bsatok
1679c4cc03a354922df08efacfc486ef0e80144d3easatok    private HashMap<String, String> getExtraValueHashMap() {
1689c4cc03a354922df08efacfc486ef0e80144d3easatok        if (mExtraValueHashMapCache == null) {
1699c4cc03a354922df08efacfc486ef0e80144d3easatok            mExtraValueHashMapCache = new HashMap<String, String>();
1709c4cc03a354922df08efacfc486ef0e80144d3easatok            final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
1719c4cc03a354922df08efacfc486ef0e80144d3easatok            final int N = pairs.length;
1729c4cc03a354922df08efacfc486ef0e80144d3easatok            for (int i = 0; i < N; ++i) {
1739c4cc03a354922df08efacfc486ef0e80144d3easatok                final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
1749c4cc03a354922df08efacfc486ef0e80144d3easatok                if (pair.length == 1) {
1759c4cc03a354922df08efacfc486ef0e80144d3easatok                    mExtraValueHashMapCache.put(pair[0], null);
1769c4cc03a354922df08efacfc486ef0e80144d3easatok                } else if (pair.length > 1) {
1779c4cc03a354922df08efacfc486ef0e80144d3easatok                    if (pair.length > 2) {
1789c4cc03a354922df08efacfc486ef0e80144d3easatok                        Slog.w(TAG, "ExtraValue has two or more '='s");
1799c4cc03a354922df08efacfc486ef0e80144d3easatok                    }
1809c4cc03a354922df08efacfc486ef0e80144d3easatok                    mExtraValueHashMapCache.put(pair[0], pair[1]);
1819c4cc03a354922df08efacfc486ef0e80144d3easatok                }
1829c4cc03a354922df08efacfc486ef0e80144d3easatok            }
1839c4cc03a354922df08efacfc486ef0e80144d3easatok        }
1849c4cc03a354922df08efacfc486ef0e80144d3easatok        return mExtraValueHashMapCache;
1859c4cc03a354922df08efacfc486ef0e80144d3easatok    }
1869c4cc03a354922df08efacfc486ef0e80144d3easatok
1879c4cc03a354922df08efacfc486ef0e80144d3easatok    /**
1889c4cc03a354922df08efacfc486ef0e80144d3easatok     * The string of ExtraValue in subtype should be defined as follows:
1899c4cc03a354922df08efacfc486ef0e80144d3easatok     * example: key0,key1=value1,key2,key3,key4=value4
1909c4cc03a354922df08efacfc486ef0e80144d3easatok     * @param key the key of extra value
1919c4cc03a354922df08efacfc486ef0e80144d3easatok     * @return the subtype contains specified the extra value
1929c4cc03a354922df08efacfc486ef0e80144d3easatok     */
1939c4cc03a354922df08efacfc486ef0e80144d3easatok    public boolean containsExtraValueKey(String key) {
1949c4cc03a354922df08efacfc486ef0e80144d3easatok        return getExtraValueHashMap().containsKey(key);
1959c4cc03a354922df08efacfc486ef0e80144d3easatok    }
1969c4cc03a354922df08efacfc486ef0e80144d3easatok
1979c4cc03a354922df08efacfc486ef0e80144d3easatok    /**
1989c4cc03a354922df08efacfc486ef0e80144d3easatok     * The string of ExtraValue in subtype should be defined as follows:
1999c4cc03a354922df08efacfc486ef0e80144d3easatok     * example: key0,key1=value1,key2,key3,key4=value4
2009c4cc03a354922df08efacfc486ef0e80144d3easatok     * @param key the key of extra value
2019c4cc03a354922df08efacfc486ef0e80144d3easatok     * @return the value of the specified key
2029c4cc03a354922df08efacfc486ef0e80144d3easatok     */
2039c4cc03a354922df08efacfc486ef0e80144d3easatok    public String getExtraValueOf(String key) {
2049c4cc03a354922df08efacfc486ef0e80144d3easatok        return getExtraValueHashMap().get(key);
2059c4cc03a354922df08efacfc486ef0e80144d3easatok    }
2069c4cc03a354922df08efacfc486ef0e80144d3easatok
207ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
208ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int hashCode() {
209ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeHashCode;
210ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
211ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
212ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
213ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public boolean equals(Object o) {
214ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        if (o instanceof InputMethodSubtype) {
215ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            InputMethodSubtype subtype = (InputMethodSubtype) o;
216af4bf400abab86baee44dacbcdf13444d06ee46esatok            return (subtype.hashCode() == hashCode())
217af4bf400abab86baee44dacbcdf13444d06ee46esatok                && (subtype.getNameResId() == getNameResId())
218af4bf400abab86baee44dacbcdf13444d06ee46esatok                && (subtype.getMode().equals(getMode()))
219ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getIconResId() == getIconResId())
220ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getLocale().equals(getLocale()))
221ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getExtraValue().equals(getExtraValue()));
222ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
223ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return false;
224ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
225ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2269aabb95781bee6a44684a6f6feb155e115d24983satok    @Override
227ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int describeContents() {
228ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return 0;
229ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
230ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2319aabb95781bee6a44684a6f6feb155e115d24983satok    @Override
232ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public void writeToParcel(Parcel dest, int parcelableFlags) {
233ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeInt(mSubtypeNameResId);
234ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeInt(mSubtypeIconResId);
235ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeString(mSubtypeLocale);
2369ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        dest.writeString(mSubtypeMode);
237ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeString(mSubtypeExtraValue);
2389aabb95781bee6a44684a6f6feb155e115d24983satok        dest.writeInt(mIsAuxiliary ? 1 : 0);
239ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
240ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
241ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public static final Parcelable.Creator<InputMethodSubtype> CREATOR
242ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            = new Parcelable.Creator<InputMethodSubtype>() {
2439aabb95781bee6a44684a6f6feb155e115d24983satok        @Override
244ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public InputMethodSubtype createFromParcel(Parcel source) {
245ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            return new InputMethodSubtype(source);
246ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
247ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2489aabb95781bee6a44684a6f6feb155e115d24983satok        @Override
249ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public InputMethodSubtype[] newArray(int size) {
250ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            return new InputMethodSubtype[size];
251ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
252ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    };
253ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
254ece92d34fcf273f68f33d2fd8e5764764fc0c66dsatok    private static int hashCodeInternal(String locale, String mode, String extraValue) {
255ece92d34fcf273f68f33d2fd8e5764764fc0c66dsatok        return Arrays.hashCode(new Object[] {locale, mode, extraValue});
256ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2577265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok
2587265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    /**
2597265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * Sort the list of InputMethodSubtype
2607265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param context Context will be used for getting localized strings from IME
2617265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param flags Flags for the sort order
2627265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param imi InputMethodInfo of which subtypes are subject to be sorted
2637265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param subtypeList List of InputMethodSubtype which will be sorted
2647265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @return Sorted list of subtypes
2657265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @hide
2667265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     */
2677265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi,
2687265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            List<InputMethodSubtype> subtypeList) {
2697265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        if (imi == null) return subtypeList;
2707265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>(
2717265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                subtypeList);
2727265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>();
2737265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        int N = imi.getSubtypeCount();
2747265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        for (int i = 0; i < N; ++i) {
2757265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            InputMethodSubtype subtype = imi.getSubtypeAt(i);
2767265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            if (inputSubtypesSet.contains(subtype)) {
2777265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                sortedList.add(subtype);
2787265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                inputSubtypesSet.remove(subtype);
2797265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            }
2807265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        }
2817265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        // If subtypes in inputSubtypesSet remain, that means these subtypes are not
2827265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        // contained in imi, so the remaining subtypes will be appended.
2837265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        for (InputMethodSubtype subtype: inputSubtypesSet) {
2847265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            sortedList.add(subtype);
2857265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        }
2867265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        return sortedList;
2877265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    }
288af4bf400abab86baee44dacbcdf13444d06ee46esatok}
289