InputMethodUtilsTest.java revision 2a099bcd6fe974bad47363c214a7bb327484aff8
1f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka/*
2f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * Copyright (C) 2013 The Android Open Source Project
3f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka *
4f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License");
5f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * you may not use this file except in compliance with the License.
6f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * You may obtain a copy of the License at
7f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka *
8f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka *      http://www.apache.org/licenses/LICENSE-2.0
9f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka *
10f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software
11f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS,
12f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * See the License for the specific language governing permissions and
14f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka * limitations under the License.
15f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka */
16f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
1735f743713dfeb4e9138fee0f7bb6a7ee1da53521Yohei Yukawapackage com.android.internal.inputmethod;
18f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
19f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.content.Context;
20f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.content.pm.ApplicationInfo;
21f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.content.pm.ResolveInfo;
22f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.content.pm.ServiceInfo;
2335f743713dfeb4e9138fee0f7bb6a7ee1da53521Yohei Yukawaimport android.os.Parcel;
24f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.test.InstrumentationTestCase;
25f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.test.suitebuilder.annotation.SmallTest;
262028ddaa5024dfc9844376f2032115aee360155aSeigo Nonakaimport android.util.ArrayMap;
272028ddaa5024dfc9844376f2032115aee360155aSeigo Nonakaimport android.util.ArraySet;
28f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport android.view.inputmethod.InputMethodInfo;
29443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawaimport android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
302028ddaa5024dfc9844376f2032115aee360155aSeigo Nonakaimport android.view.inputmethod.InputMethodSubtype;
31f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
32f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport java.util.ArrayList;
33f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataokaimport java.util.List;
34bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawaimport java.util.Locale;
35b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawaimport java.util.Objects;
36f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
3735f743713dfeb4e9138fee0f7bb6a7ee1da53521Yohei Yukawapublic class InputMethodUtilsTest extends InstrumentationTestCase {
38f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    private static final boolean IS_AUX = true;
39f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    private static final boolean IS_DEFAULT = true;
40e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true;
41cfcbddaff269cbb35192c21e557d34aece2f3d6cYohei Yukawa    private static final boolean IS_ASCII_CAPABLE = true;
42e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final boolean IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = true;
43bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa    private static final boolean IS_SYSTEM_READY = true;
44e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_EN = new Locale("en");
45bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa    private static final Locale LOCALE_EN_US = new Locale("en", "US");
46d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa    private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
47d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa    private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
48e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_FI = new Locale("fi");
49e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_FI_FI = new Locale("fi", "FI");
50e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_FIL = new Locale("fil");
51e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH");
52e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_FR = new Locale("fr");
53e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_FR_CA = new Locale("fr", "CA");
54d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa    private static final Locale LOCALE_HI = new Locale("hi");
55174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    private static final Locale LOCALE_JA = new Locale("ja");
5659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
57b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa    private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN");
58b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa    private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW");
59e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_IN = new Locale("in");
60e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final Locale LOCALE_ID = new Locale("id");
61174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    private static final Locale LOCALE_TH = new Locale("ht");
62174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    private static final Locale LOCALE_TH_TH = new Locale("ht", "TH");
63174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
6459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
6559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    private static final String SUBTYPE_MODE_VOICE = "voice";
66e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final String SUBTYPE_MODE_ANY = null;
67e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
68e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
69e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static final String EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
70e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            "EnabledWhenDefaultIsNotAsciiCapable";
71f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
72f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    @SmallTest
7359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    public void testVoiceImes() throws Exception {
7459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: en_US
75b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
76b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
77b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
78b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme");
79b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
80b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
81b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
82b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
83b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "DummyNonDefaultAutoVoiceIme1");
84d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa
8559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: en_GB
86b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
87b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
88b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
89b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme");
90b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
91b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
92b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
93b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
94b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "DummyNonDefaultAutoVoiceIme1");
95d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa
9659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: ja_JP
97b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
98b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
99b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
100b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme");
101b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
102b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
103b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
104b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
105b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "DummyNonDefaultAutoVoiceIme1");
106f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    }
107f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
108f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    @SmallTest
10959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    public void testKeyboardImes() throws Exception {
11059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: en_US
111b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US,
112b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
113b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US,
114b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.latin",
115b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.voice");
11659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
11759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: en_GB
118b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB,
119b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
120b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB,
121b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.latin",
122b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.voice");
12359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
12459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: en_IN
125b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN,
126b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
127b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN,
128b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.hindi",
129b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
13059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
13159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: hi
132b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI,
133b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
134b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI,
135b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.hindi",
136b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
13759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
13859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // locale: ja_JP
139b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP,
140b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
141b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP,
142b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.japanese",
143b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.voice");
144b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa
145b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        // locale: zh_CN
146b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN,
147b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
148b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN,
149b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.pinyin",
150b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.voice");
151b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa
152b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        // locale: zh_TW
153b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        // Note: In this case, no IME is suitable for the system locale. Hence we will pick up a
154b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        // fallback IME regardless of the "default" attribute.
155b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW,
156b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
157b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW,
158b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                IS_SYSTEM_READY, "com.android.apps.inputmethod.latin",
159b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                "com.android.apps.inputmethod.voice");
160f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    }
161f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
162589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa    @SmallTest
163589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa    public void testParcelable() throws Exception {
164b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        final ArrayList<InputMethodInfo> originalList = getSamplePreinstalledImes("en-rUS");
165589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        final List<InputMethodInfo> clonedList = cloneViaParcel(originalList);
166589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        assertNotNull(clonedList);
167c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        final List<InputMethodInfo> clonedClonedList = cloneViaParcel(clonedList);
168c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        assertNotNull(clonedClonedList);
169589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        assertEquals(originalList, clonedList);
170c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        assertEquals(clonedList, clonedClonedList);
171c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        assertEquals(originalList.size(), clonedList.size());
172c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        assertEquals(clonedList.size(), clonedClonedList.size());
173589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        for (int imeIndex = 0; imeIndex < originalList.size(); ++imeIndex) {
174c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa            verifyEquality(originalList.get(imeIndex), clonedList.get(imeIndex));
175c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa            verifyEquality(clonedList.get(imeIndex), clonedClonedList.get(imeIndex));
176589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        }
177589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa    }
178589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa
179e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    @SmallTest
180e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    public void testGetImplicitlyApplicableSubtypesLocked() throws Exception {
181e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
182e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
183e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
184e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
185e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
186e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
187e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA",
188e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
189e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
190e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA",
191e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
192e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
193e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
194e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
195e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
196e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
197e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
198e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
199e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
200e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
201e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
202e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto",
203e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
204e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
205e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
206e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
207e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
208e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
209e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
210e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                        !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
211e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                        IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
212e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 =
213e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
214e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                        !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
215e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                        IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
216e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
217e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that an automatic subtype (overridesImplicitlyEnabledSubtype:true) is
218e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // selected no matter what locale is specified.
219e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
220e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
221e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
222e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnGB);
223e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);
224e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
225e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(autoSubtype);  // overridesImplicitlyEnabledSubtype == true
226e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
227e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
228e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
229e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
230e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
231e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
232e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
233e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
234e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
235e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(autoSubtype, result.get(0));
236e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
237e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
238e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that a subtype whose locale is exactly equal to the specified locale is
239e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // selected as long as there is no no automatic subtype
240e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // (overridesImplicitlyEnabledSubtype:true) in the given list.
241e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
242e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
243e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);  // locale == "en_US"
244e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnGB);
245e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);
246e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
247e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
248e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
249e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
250e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
251e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
252e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
253e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
254e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
255e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
256e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoEnUS, result.get(0));
257e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
258e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
259e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that a subtype whose locale is exactly equal to the specified locale is
260e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // selected as long as there is no automatic subtype
261e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // (overridesImplicitlyEnabledSubtype:true) in the given list.
262e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
263e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
264e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
265e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnGB); // locale == "en_GB"
266e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);
267e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
268e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
269e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
270e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
271e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
272e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
273e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
274e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_GB, imi);
275e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
276e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoEnGB, result.get(0));
277e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
278e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
279e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and
280e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // any subtype whose locale is exactly equal to the specified locale in the given list,
281e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // try to find a subtype whose language is equal to the language part of the given locale.
282e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Here make sure that a subtype (locale: "fr_CA") can be found with locale: "fr".
283e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
284e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
285e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFrCA);  // locale == "fr_CA"
286e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);
287e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
288e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
289e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
290e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
291e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
292e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
293e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
294e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
295e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR, imi);
296e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
297e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoFrCA, result.get(0));
298e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
299e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA".
300e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
301e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
302e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFr);  // locale == "fr"
303e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);
304e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
305e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
306e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
307e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
308e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
309e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
310e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
311e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
312e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR_CA, imi);
313e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
314e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoFrCA, result.get(0));
315e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
316e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
317e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its
318e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // extra value is selected if and only if all other selected IMEs are not AsciiCapable.
319e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
320e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
321e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
322e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);    // not ASCII capable
323e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
324e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
325e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
326e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
327e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
328e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
329e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
330e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_JA_JP, imi);
331e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(3, result.size());
332e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoJa, result.get(0));
333e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1));
334e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
335e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
336e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
337e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that 3-letter language code can be handled.
338e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
339e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
340e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
341e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
342e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
343e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
344e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
345e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
346e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
347e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FIL_PH, imi);
348e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
349e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoFil, result.get(0));
350e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
351e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
352e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that we never end up matching "fi" (finnish) with "fil" (filipino).
353e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Also make sure that the first subtype will be used as the last-resort candidate.
354e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
355e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
356e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoJa);
357e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
358e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
359e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
360e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
361e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
362e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
363e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
364e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FI, imi);
365e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
366e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoJa, result.get(0));
367e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
368e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
369e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that "in" and "id" conversion is taken into account.
370e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
371e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
372e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoIn);
373e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
374e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
375e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
376e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
377e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
378e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
379e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
380e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
381e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoIn, result.get(0));
382e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
383e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
384e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
385e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoIn);
386e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
387e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
388e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
389e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
390e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
391e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
392e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
393e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
394e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoIn, result.get(0));
395e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
396e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
397e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
398e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoId);
399e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
400e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
401e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
402e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
403e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
404e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
405e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
406e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
407e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoId, result.get(0));
408e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
409e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
410e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
411e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoId);
412e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
413e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
414e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
415e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
416e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
417e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> result =
418e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
419e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertEquals(1, result.size());
420e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(nonAutoId, result.get(0));
421e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
422e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    }
423e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
424e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    @SmallTest
425e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    public void testContainsSubtypeOf() throws Exception {
426e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
427e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
428e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
429e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
430e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
431e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
432e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
433e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
434e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
435e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH",
436e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
437e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
438e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
439e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
440e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
441e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
442e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
443e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
444e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
445e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final boolean CHECK_COUNTRY = true;
446e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
447e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
448e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
449e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
450e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
451e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
452e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
453e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
454e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
455e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY,
456e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
457e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, CHECK_COUNTRY,
458e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
459e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
460e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
461e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
462e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
463e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
464e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_VOICE));
465e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
466e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_VOICE));
467e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
468e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_ANY));
469e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
470e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_ANY));
471e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
472e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, !CHECK_COUNTRY,
473e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
474e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, CHECK_COUNTRY,
475e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
476e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
477e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
478e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that 3-letter language code ("fil") can be handled.
479e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
480e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
481e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFil);
482e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
483e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
484e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
485e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
486e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
487e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
488e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY,
489e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
490e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY,
491e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
492e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY,
493e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
494e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
495e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY,
496e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
497e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY,
498e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
499e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY,
500e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
501e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY,
502e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
503e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
504e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
505e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that 3-letter language code ("fil_PH") can be handled.
506e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
507e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
508e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoFilPH);
509e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
510e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
511e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
512e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
513e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
514e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
515e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY,
516e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
517e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY,
518e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
519e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY,
520e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
521e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
522e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY,
523e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
524e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY,
525e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
526e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY,
527e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
528e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY,
529e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
530e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
531e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
532e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that a subtype whose locale is "in" can be queried with "id".
533e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
534e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
535e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoIn);
536e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
537e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
538e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
539e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
540e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
541e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
542e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
543e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
544e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
545e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
546e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
547e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
548e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
549e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
550e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
551e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // Make sure that a subtype whose locale is "id" can be queried with "in".
552e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        {
553e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
554e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoId);
555e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(nonAutoEnUS);
556e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final InputMethodInfo imi = createDummyInputMethodInfo(
557e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin",
558e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
559e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    subtypes);
560e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
561e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
562f487e0e395a4e49f28c6448339d57357667756c6Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
563e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
564e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
565e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
566f487e0e395a4e49f28c6448339d57357667756c6Yohei Yukawa            assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
567e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    SUBTYPE_MODE_KEYBOARD));
568e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
569e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    }
570e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
571e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private ArrayList<InputMethodSubtype> callGetImplicitlyApplicableSubtypesLockedWithLocale(
572e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            final Locale locale, final InputMethodInfo imi) {
573e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final Context context = getInstrumentation().getTargetContext();
574e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final Locale initialLocale = context.getResources().getConfiguration().locale;
575e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        try {
576e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            context.getResources().getConfiguration().setLocale(locale);
577e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            return InputMethodUtils.getImplicitlyApplicableSubtypesLocked(context.getResources(),
578e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    imi);
579e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        } finally {
580e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            context.getResources().getConfiguration().setLocale(initialLocale);
581e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
582e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    }
583e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
58459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes,
585b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) {
58659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        final Context context = getInstrumentation().getTargetContext();
587e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesWithLocale(
588b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                context, isSystemReady, preinstalledImes, systemLocale));
589b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        assertEquals(expectedImeNames.length, actualImeNames.length);
590b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        for (int i = 0; i < expectedImeNames.length; ++i) {
591b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            assertEquals(expectedImeNames[i], actualImeNames[i]);
592b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        }
59359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    }
59459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
595589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa    private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) {
596589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        Parcel p = null;
597589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        try {
598589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa            p = Parcel.obtain();
599589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa            p.writeTypedList(list);
600589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa            p.setDataPosition(0);
601589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa            return p.createTypedArrayList(InputMethodInfo.CREATOR);
602589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        } finally {
603589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa            if (p != null) {
604589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa                p.recycle();
605589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa            }
606589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa        }
607589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa    }
608589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa
609e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesWithLocale(
610bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa            final Context context, final boolean isSystemReady,
611bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa            final ArrayList<InputMethodInfo> imis, final Locale locale) {
612bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa        final Locale initialLocale = context.getResources().getConfiguration().locale;
613bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa        try {
614bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa            context.getResources().getConfiguration().setLocale(locale);
615bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa            return InputMethodUtils.getDefaultEnabledImes(context, isSystemReady, imis);
616bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa        } finally {
617bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa            context.getResources().getConfiguration().setLocale(initialLocale);
618bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa        }
619bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa    }
620bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa
621b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa    private String[] getPackageNames(final ArrayList<InputMethodInfo> imis) {
622b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        final String[] packageNames = new String[imis.size()];
623b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        for (int i = 0; i < imis.size(); ++i) {
624b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            packageNames[i] = imis.get(i).getPackageName();
625bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa        }
626bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa        return packageNames;
627bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa    }
628bca817b2e2623c49bbb618f78fe207bedf57f266Yohei Yukawa
629c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa    private static void verifyEquality(InputMethodInfo expected, InputMethodInfo actual) {
630c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        assertEquals(expected, actual);
631c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        assertEquals(expected.getSubtypeCount(), actual.getSubtypeCount());
632c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) {
633c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa            final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex);
634c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa            final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex);
635e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            verifyEquality(expectedSubtype, actualSubtype);
636c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa        }
637c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa    }
638c18cd393f65146fac03a9bdfa45380a69460ee98Yohei Yukawa
639e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    private static void verifyEquality(InputMethodSubtype expected, InputMethodSubtype actual) {
640e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        assertEquals(expected, actual);
641e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        assertEquals(expected.hashCode(), actual.hashCode());
642e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa    }
643e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
644f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
645f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            CharSequence label, boolean isAuxIme, boolean isDefault,
646f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            List<InputMethodSubtype> subtypes) {
647f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        final ResolveInfo ri = new ResolveInfo();
648f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        final ServiceInfo si = new ServiceInfo();
649f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        final ApplicationInfo ai = new ApplicationInfo();
650f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        ai.packageName = packageName;
651f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        ai.enabled = true;
652f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        ai.flags |= ApplicationInfo.FLAG_SYSTEM;
653f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        si.applicationInfo = ai;
654f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        si.enabled = true;
655f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        si.packageName = packageName;
656f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        si.name = name;
657f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        si.exported = true;
658f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        si.nonLocalizedLabel = label;
659f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        ri.serviceInfo = si;
660f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault);
661f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    }
662f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
663f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
664cfcbddaff269cbb35192c21e557d34aece2f3d6cYohei Yukawa            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
665e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) {
666e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
667e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        final StringBuilder subtypeExtraValue = new StringBuilder();
668e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        if (isEnabledWhenDefaultIsNotAsciiCapable) {
669e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
670e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypeExtraValue.append(EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
671e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
672e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
673e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // TODO: Remove following code. InputMethodSubtype#isAsciiCapable() has been publicly
674e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        // available since API level 19 (KitKat). We no longer need to rely on extra value.
675e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        if (isAsciiCapable) {
676e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
677e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypeExtraValue.append(EXTRA_VALUE_ASCII_CAPABLE);
678e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa        }
679e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa
680443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa        return new InputMethodSubtypeBuilder()
681443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .setSubtypeNameResId(0)
682443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .setSubtypeIconResId(0)
683443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .setSubtypeLocale(locale)
684443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .setSubtypeMode(mode)
685e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                .setSubtypeExtraValue(subtypeExtraValue.toString())
686443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .setIsAuxiliary(isAuxiliary)
687443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype)
688cfcbddaff269cbb35192c21e557d34aece2f3d6cYohei Yukawa                .setIsAsciiCapable(isAsciiCapable)
689443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                .build();
690f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    }
691f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
69259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    private static ArrayList<InputMethodInfo> getImesWithDefaultVoiceIme() {
69359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
69459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
69559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
696e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
697e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
698e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
69959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
700e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
701e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
70259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme",
70359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    "dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes));
70459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
70559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        preinstalledImes.addAll(getImesWithoutDefaultVoiceIme());
70659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        return preinstalledImes;
707f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    }
708f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
70959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa    private static ArrayList<InputMethodInfo> getImesWithoutDefaultVoiceIme() {
71059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
71159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
71259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
713e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
714e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
715e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
71659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
717e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
718e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
71959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0",
72059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    "dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes));
72159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
72259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
72359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
724e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa            subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
725e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
726e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
72759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
728e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
729e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
73059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1",
73159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    "dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes));
73259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
73359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
73459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
73559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
736e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
737e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
73859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2",
73959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    "dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes));
74059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
74159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
74259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
74359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
744e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
745e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
74659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme",
74759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    "dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes));
74859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
74959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        return preinstalledImes;
750f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka    }
751f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
752b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa    private static boolean contains(final String[] textList, final String textToBeChecked) {
753b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        if (textList == null) {
754b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            return false;
755b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        }
756b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        for (final String text : textList) {
757b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            if (Objects.equals(textToBeChecked, text)) {
758b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                return true;
759b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            }
760b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        }
761b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        return false;
762b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa    }
763b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa
764b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa    private static ArrayList<InputMethodInfo> getSamplePreinstalledImes(final String localeString) {
76559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
76659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
76759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // a dummy Voice IME
76859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
769b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final boolean isDefaultIme = false;
77059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
77159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX,
772e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
773e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
77459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice",
775b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    "com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme,
77659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    subtypes));
77759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
77859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // a dummy Hindi IME
77959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
780b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final boolean isDefaultIme = contains(new String[]{ "hi", "en-rIN" }, localeString);
78159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
78259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            // TODO: This subtype should be marked as IS_ASCII_CAPABLE
78359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
784e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
785e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
78659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
787e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
788e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
78959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi",
790b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    "com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme,
79159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    subtypes));
79259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
793f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
79459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // a dummy Pinyin IME
79559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
796b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString);
79759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
79859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
799e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
800e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
801b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin",
802b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    "com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme,
80359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    subtypes));
80459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
805f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
806b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa        // a dummy Korean IME
80759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
808b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString);
80959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
81059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
811e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
812e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
81359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean",
814b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    "com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme,
81559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    subtypes));
81659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
817589800485d770cab7b159ffcf4b18c10ae2aee6dYohei Yukawa
81859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // a dummy Latin IME
81959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
820b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final boolean isDefaultIme = contains(
821b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString);
82259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
82359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
824e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
825e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
82659cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
827e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
828e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
82959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
830e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
831e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
83259cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
833e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
834e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
83559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin",
836b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme,
83759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    subtypes));
83859cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
83959cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa
84059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        // a dummy Japanese IME
84159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        {
842b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa            final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString);
84359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
84459cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
845e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
846e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
84759cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
848e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
849e72d1c82743c4d573e529d4da3866c1fcea35c77Yohei Yukawa                    !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
85059cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa            preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese",
85159cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa                    "com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX,
852b21220efae92a56ff7b4b781fa614a6e3a8a3007Yohei Yukawa                    isDefaultIme, subtypes));
85359cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        }
854d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa
85559cccf93d28648a77860a30349e52b7eeb98436cYohei Yukawa        return preinstalledImes;
856d77adfe52d44396c54a4ce3a7f1e823e8618f27cYohei Yukawa    }
857174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
858174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    @SmallTest
859174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    public void testGetSuitableLocalesForSpellChecker() throws Exception {
860174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
861174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
862174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US);
863174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(3, locales.size());
864174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(0));
865174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(1));
866174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN, locales.get(2));
867174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
868174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
869174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
870174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
871174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB);
872174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(3, locales.size());
873174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(0));
874174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(1));
875174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN, locales.get(2));
876174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
877174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
878174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
879174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
880174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN);
881174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(3, locales.size());
882174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN, locales.get(0));
883174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(1));
884174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(2));
885174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
886174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
887174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
888174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
889174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN);
890174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(4, locales.size());
891174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_IN, locales.get(0));
892174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(1));
893174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(2));
894174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN, locales.get(3));
895174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
896174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
897174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
898174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
899174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP);
900174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(5, locales.size());
901174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_JA_JP, locales.get(0));
902174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_JA, locales.get(1));
903174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(2));
904174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(3));
905174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(Locale.ENGLISH, locales.get(4));
906174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
907174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
908174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        // Test 3-letter language code.
909174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
910174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
911174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH);
912174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(5, locales.size());
913174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_FIL_PH, locales.get(0));
914174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_FIL, locales.get(1));
915174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(2));
916174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(3));
917174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(Locale.ENGLISH, locales.get(4));
918174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
919174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
920174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        // Test variant.
921174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
922174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
923174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH);
924174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(6, locales.size());
925174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_TH_TH_TH, locales.get(0));
926174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_TH_TH, locales.get(1));
927174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_TH, locales.get(2));
928174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(3));
929174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(4));
930174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(Locale.ENGLISH, locales.get(5));
931174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
932174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
933174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        // Test Locale extension.
934174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        {
935174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final Locale localeWithoutVariant = LOCALE_JA_JP;
936174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final Locale localeWithVariant = new Locale.Builder()
937174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    .setLocale(LOCALE_JA_JP)
938174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    .setExtension('x', "android")
939174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    .build();
940174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertFalse(localeWithoutVariant.equals(localeWithVariant));
941174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa
942174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            final ArrayList<Locale> locales =
943174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa                    InputMethodUtils.getSuitableLocalesForSpellChecker(localeWithVariant);
944174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(5, locales.size());
945174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_JA_JP, locales.get(0));
946174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_JA, locales.get(1));
947174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_US, locales.get(2));
948174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(LOCALE_EN_GB, locales.get(3));
949174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa            assertEquals(Locale.ENGLISH, locales.get(4));
950174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa        }
951174843afb629c57af19e14ee3ec4a91358061dd9Yohei Yukawa    }
9522028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
953290e4e471b325d4afca9e36d55b54d83254b2e29Seigo Nonaka    @SmallTest
9542028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka    public void testParseInputMethodsAndSubtypesString() {
9552028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        // Trivial cases.
9562028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
9572028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString("").isEmpty());
9582028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString(null).isEmpty());
9592028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
9602028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
9612028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        // No subtype cases.
9622028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
9632028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
9642028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString("ime0");
9652028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, r.size());
9662028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
9672028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.get("ime0").isEmpty());
9682028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
9692028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
9702028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
9712028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString("ime0:ime1");
9722028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, r.size());
9732028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
9742028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.get("ime0").isEmpty());
9752028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime1"));
9762028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.get("ime1").isEmpty());
9772028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
9782028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
9792028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        // Input metho IDs and their subtypes.
9802028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
9812028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
9822028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0");
9832028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, r.size());
9842028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
9852028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes = r.get("ime0");
9862028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, subtypes.size());
9872028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes.contains("subtype0"));
9882028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
9892028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
9902028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
9912028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype0");
9922028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, r.size());
9932028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
9942028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes = r.get("ime0");
9952028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, subtypes.size());
9962028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes.contains("subtype0"));
9972028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
9982028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
9992028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
10002028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype1");
10012028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, r.size());
10022028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
10032028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes = r.get("ime0");
10042028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, subtypes.size());
10052028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes.contains("subtype0"));
10062028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes.contains("subtype1"));
10072028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
10082028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
10092028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
10102028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString(
10112028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                            "ime0;subtype0:ime1;subtype1");
10122028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, r.size());
10132028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
10142028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime1"));
10152028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes0 = r.get("ime0");
10162028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, subtypes0.size());
10172028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype0"));
10182028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
10192028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes1 = r.get("ime1");
10202028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, subtypes1.size());
10212028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes1.contains("subtype1"));
10222028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
10232028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
10242028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
10252028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString(
10262028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                            "ime0;subtype0;subtype1:ime1;subtype2");
10272028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, r.size());
10282028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
10292028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime1"));
10302028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes0 = r.get("ime0");
10312028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, subtypes0.size());
10322028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype0"));
10332028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype1"));
10342028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
10352028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes1 = r.get("ime1");
10362028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(1, subtypes1.size());
10372028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes1.contains("subtype2"));
10382028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
10392028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
10402028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
10412028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString(
10422028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                            "ime0;subtype0;subtype1:ime1;subtype1;subtype2");
10432028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, r.size());
10442028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
10452028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime1"));
10462028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes0 = r.get("ime0");
10472028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, subtypes0.size());
10482028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype0"));
10492028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype1"));
10502028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
10512028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes1 = r.get("ime1");
10522028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, subtypes1.size());
10532028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype1"));
10542028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes1.contains("subtype2"));
10552028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
10562028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        {
10572028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArrayMap<String, ArraySet<String>> r =
10582028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                    InputMethodUtils.parseInputMethodsAndSubtypesString(
10592028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka                            "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2");
10602028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(3, r.size());
10612028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime0"));
10622028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime1"));
10632028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(r.containsKey("ime2"));
10642028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes0 = r.get("ime0");
10652028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, subtypes0.size());
10662028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype0"));
10672028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype1"));
10682028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
10692028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes1 = r.get("ime1");
10702028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertEquals(2, subtypes1.size());
10712028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes0.contains("subtype1"));
10722028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes1.contains("subtype2"));
10732028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka
10742028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            ArraySet<String> subtypes2 = r.get("ime2");
10752028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka            assertTrue(subtypes2.isEmpty());
10762028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka        }
10772028ddaa5024dfc9844376f2032115aee360155aSeigo Nonaka    }
10782a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
10792a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka    @SmallTest
10802a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka    public void testbuildInputMethodsAndSubtypesString() {
10812a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
10822a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
10832a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertEquals("", InputMethodUtils.buildInputMethodsAndSubtypesString(map));
10842a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
10852a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
10862a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
10872a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", new ArraySet<String>());
10882a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertEquals("ime0", InputMethodUtils.buildInputMethodsAndSubtypesString(map));
10892a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
10902a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
10912a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
10922a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes1 = new ArraySet<>();
10932a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype0");
10942a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", subtypes1);
10952a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertEquals("ime0;subtype0", InputMethodUtils.buildInputMethodsAndSubtypesString(map));
10962a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
10972a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
10982a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
10992a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes1 = new ArraySet<>();
11002a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype0");
11012a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype1");
11022a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", subtypes1);
11032a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11042a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            // We do not expect what order will be used to concatenate items in
11052a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            // InputMethodUtils.buildInputMethodsAndSubtypesString() hence enumerate all possible
11062a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            // permutations here.
11072a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> validSequences = new ArraySet<>();
11082a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype0;subtype1");
11092a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype1;subtype0");
11102a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertTrue(validSequences.contains(
11112a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka                    InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
11122a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
11132a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
11142a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
11152a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", new ArraySet<String>());
11162a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime1", new ArraySet<String>());
11172a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11182a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> validSequences = new ArraySet<>();
11192a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0:ime1");
11202a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime1:ime0");
11212a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertTrue(validSequences.contains(
11222a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka                    InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
11232a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
11242a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
11252a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
11262a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes1 = new ArraySet<>();
11272a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype0");
11282a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", subtypes1);
11292a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime1", new ArraySet<String>());
11302a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11312a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> validSequences = new ArraySet<>();
11322a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype0:ime1");
11332a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime1;ime0;subtype0");
11342a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertTrue(validSequences.contains(
11352a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka                    InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
11362a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
11372a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
11382a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
11392a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes1 = new ArraySet<>();
11402a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype0");
11412a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype1");
11422a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", subtypes1);
11432a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime1", new ArraySet<String>());
11442a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11452a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> validSequences = new ArraySet<>();
11462a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype0;subtype1:ime1");
11472a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype1;subtype0:ime1");
11482a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime1:ime0;subtype0;subtype1");
11492a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime1:ime0;subtype1;subtype0");
11502a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertTrue(validSequences.contains(
11512a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka                    InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
11522a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
11532a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
11542a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
11552a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes1 = new ArraySet<>();
11562a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype0");
11572a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", subtypes1);
11582a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11592a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes2 = new ArraySet<>();
11602a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes2.add("subtype1");
11612a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime1", subtypes2);
11622a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11632a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> validSequences = new ArraySet<>();
11642a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype0:ime1;subtype1");
11652a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime1;subtype1:ime0;subtype0");
11662a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertTrue(validSequences.contains(
11672a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka                    InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
11682a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
11692a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        {
11702a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArrayMap<String, ArraySet<String>> map = new ArrayMap<>();
11712a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes1 = new ArraySet<>();
11722a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype0");
11732a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes1.add("subtype1");
11742a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime0", subtypes1);
11752a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11762a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> subtypes2 = new ArraySet<>();
11772a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes2.add("subtype2");
11782a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            subtypes2.add("subtype3");
11792a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            map.put("ime1", subtypes2);
11802a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka
11812a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            ArraySet<String> validSequences = new ArraySet<>();
11822a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype0;subtype1:ime1;subtype2;subtype3");
11832a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype1;subtype0:ime1;subtype2;subtype3");
11842a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype0;subtype1:ime1;subtype3;subtype2");
11852a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime0;subtype1;subtype0:ime1;subtype3;subtype2");
11862a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime1;subtype2;subtype3:ime0;subtype0;subtype1");
11872a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime2;subtype3;subtype2:ime0;subtype0;subtype1");
11882a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime3;subtype2;subtype3:ime0;subtype1;subtype0");
11892a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            validSequences.add("ime4;subtype3;subtype2:ime0;subtype1;subtype0");
11902a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka            assertTrue(validSequences.contains(
11912a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka                    InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
11922a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka        }
11932a099bcd6fe974bad47363c214a7bb327484aff8Seigo Nonaka    }
1194f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka}
1195