InputMethodTest.java revision f487e0e395a4e49f28c6448339d57357667756c6
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.os; 18 19import android.content.Context; 20import android.content.pm.ApplicationInfo; 21import android.content.pm.ResolveInfo; 22import android.content.pm.ServiceInfo; 23import android.test.InstrumentationTestCase; 24import android.test.suitebuilder.annotation.SmallTest; 25import android.view.inputmethod.InputMethodInfo; 26import android.view.inputmethod.InputMethodSubtype; 27import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; 28 29import com.android.internal.inputmethod.InputMethodUtils; 30 31import java.util.ArrayList; 32import java.util.List; 33import java.util.Locale; 34import java.util.Objects; 35 36public class InputMethodTest extends InstrumentationTestCase { 37 private static final boolean IS_AUX = true; 38 private static final boolean IS_DEFAULT = true; 39 private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true; 40 private static final boolean IS_ASCII_CAPABLE = true; 41 private static final boolean IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = true; 42 private static final boolean IS_SYSTEM_READY = true; 43 private static final Locale LOCALE_EN = new Locale("en"); 44 private static final Locale LOCALE_EN_US = new Locale("en", "US"); 45 private static final Locale LOCALE_EN_GB = new Locale("en", "GB"); 46 private static final Locale LOCALE_EN_IN = new Locale("en", "IN"); 47 private static final Locale LOCALE_FI = new Locale("fi"); 48 private static final Locale LOCALE_FI_FI = new Locale("fi", "FI"); 49 private static final Locale LOCALE_FIL = new Locale("fil"); 50 private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH"); 51 private static final Locale LOCALE_FR = new Locale("fr"); 52 private static final Locale LOCALE_FR_CA = new Locale("fr", "CA"); 53 private static final Locale LOCALE_HI = new Locale("hi"); 54 private static final Locale LOCALE_JA_JP = new Locale("ja", "JP"); 55 private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN"); 56 private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW"); 57 private static final Locale LOCALE_IN = new Locale("in"); 58 private static final Locale LOCALE_ID = new Locale("id"); 59 private static final String SUBTYPE_MODE_KEYBOARD = "keyboard"; 60 private static final String SUBTYPE_MODE_VOICE = "voice"; 61 private static final String SUBTYPE_MODE_ANY = null; 62 private static final String EXTRA_VALUE_PAIR_SEPARATOR = ","; 63 private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; 64 private static final String EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = 65 "EnabledWhenDefaultIsNotAsciiCapable"; 66 67 @SmallTest 68 public void testVoiceImes() throws Exception { 69 // locale: en_US 70 assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, 71 !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); 72 assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US, 73 !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme"); 74 assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, 75 IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); 76 assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US, 77 IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", 78 "DummyNonDefaultAutoVoiceIme1"); 79 80 // locale: en_GB 81 assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB, 82 !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); 83 assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB, 84 !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme"); 85 assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB, 86 IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); 87 assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB, 88 IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", 89 "DummyNonDefaultAutoVoiceIme1"); 90 91 // locale: ja_JP 92 assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP, 93 !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); 94 assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP, 95 !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme"); 96 assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP, 97 IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); 98 assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP, 99 IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", 100 "DummyNonDefaultAutoVoiceIme1"); 101 } 102 103 @SmallTest 104 public void testKeyboardImes() throws Exception { 105 // locale: en_US 106 assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US, 107 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 108 assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US, 109 IS_SYSTEM_READY, "com.android.apps.inputmethod.latin", 110 "com.android.apps.inputmethod.voice"); 111 112 // locale: en_GB 113 assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB, 114 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 115 assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB, 116 IS_SYSTEM_READY, "com.android.apps.inputmethod.latin", 117 "com.android.apps.inputmethod.voice"); 118 119 // locale: en_IN 120 assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN, 121 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 122 assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN, 123 IS_SYSTEM_READY, "com.android.apps.inputmethod.hindi", 124 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice"); 125 126 // locale: hi 127 assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI, 128 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 129 assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI, 130 IS_SYSTEM_READY, "com.android.apps.inputmethod.hindi", 131 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice"); 132 133 // locale: ja_JP 134 assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP, 135 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 136 assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP, 137 IS_SYSTEM_READY, "com.android.apps.inputmethod.japanese", 138 "com.android.apps.inputmethod.voice"); 139 140 // locale: zh_CN 141 assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN, 142 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 143 assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN, 144 IS_SYSTEM_READY, "com.android.apps.inputmethod.pinyin", 145 "com.android.apps.inputmethod.voice"); 146 147 // locale: zh_TW 148 // Note: In this case, no IME is suitable for the system locale. Hence we will pick up a 149 // fallback IME regardless of the "default" attribute. 150 assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW, 151 !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin"); 152 assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW, 153 IS_SYSTEM_READY, "com.android.apps.inputmethod.latin", 154 "com.android.apps.inputmethod.voice"); 155 } 156 157 @SmallTest 158 public void testParcelable() throws Exception { 159 final ArrayList<InputMethodInfo> originalList = getSamplePreinstalledImes("en-rUS"); 160 final List<InputMethodInfo> clonedList = cloneViaParcel(originalList); 161 assertNotNull(clonedList); 162 final List<InputMethodInfo> clonedClonedList = cloneViaParcel(clonedList); 163 assertNotNull(clonedClonedList); 164 assertEquals(originalList, clonedList); 165 assertEquals(clonedList, clonedClonedList); 166 assertEquals(originalList.size(), clonedList.size()); 167 assertEquals(clonedList.size(), clonedClonedList.size()); 168 for (int imeIndex = 0; imeIndex < originalList.size(); ++imeIndex) { 169 verifyEquality(originalList.get(imeIndex), clonedList.get(imeIndex)); 170 verifyEquality(clonedList.get(imeIndex), clonedClonedList.get(imeIndex)); 171 } 172 } 173 174 @SmallTest 175 public void testGetImplicitlyApplicableSubtypesLocked() throws Exception { 176 final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", 177 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 178 IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 179 final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", 180 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 181 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 182 final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA", 183 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 184 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 185 final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA", 186 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 187 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 188 final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", 189 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 190 IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 191 final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", 192 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 193 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 194 final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", 195 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 196 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 197 final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto", 198 SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 199 IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 200 final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja", 201 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 202 !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 203 final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype = 204 createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 205 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 206 IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 207 final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 = 208 createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 209 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 210 IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 211 212 // Make sure that an automatic subtype (overridesImplicitlyEnabledSubtype:true) is 213 // selected no matter what locale is specified. 214 { 215 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 216 subtypes.add(nonAutoEnUS); 217 subtypes.add(nonAutoEnGB); 218 subtypes.add(nonAutoJa); 219 subtypes.add(nonAutoFil); 220 subtypes.add(autoSubtype); // overridesImplicitlyEnabledSubtype == true 221 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); 222 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); 223 final InputMethodInfo imi = createDummyInputMethodInfo( 224 "com.android.apps.inputmethod.latin", 225 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 226 subtypes); 227 final ArrayList<InputMethodSubtype> result = 228 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi); 229 assertEquals(1, result.size()); 230 verifyEquality(autoSubtype, result.get(0)); 231 } 232 233 // Make sure that a subtype whose locale is exactly equal to the specified locale is 234 // selected as long as there is no no automatic subtype 235 // (overridesImplicitlyEnabledSubtype:true) in the given list. 236 { 237 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 238 subtypes.add(nonAutoEnUS); // locale == "en_US" 239 subtypes.add(nonAutoEnGB); 240 subtypes.add(nonAutoJa); 241 subtypes.add(nonAutoFil); 242 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); 243 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); 244 final InputMethodInfo imi = createDummyInputMethodInfo( 245 "com.android.apps.inputmethod.latin", 246 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 247 subtypes); 248 final ArrayList<InputMethodSubtype> result = 249 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi); 250 assertEquals(1, result.size()); 251 verifyEquality(nonAutoEnUS, result.get(0)); 252 } 253 254 // Make sure that a subtype whose locale is exactly equal to the specified locale is 255 // selected as long as there is no automatic subtype 256 // (overridesImplicitlyEnabledSubtype:true) in the given list. 257 { 258 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 259 subtypes.add(nonAutoEnUS); 260 subtypes.add(nonAutoEnGB); // locale == "en_GB" 261 subtypes.add(nonAutoJa); 262 subtypes.add(nonAutoFil); 263 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); 264 final InputMethodInfo imi = createDummyInputMethodInfo( 265 "com.android.apps.inputmethod.latin", 266 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 267 subtypes); 268 final ArrayList<InputMethodSubtype> result = 269 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_GB, imi); 270 assertEquals(1, result.size()); 271 verifyEquality(nonAutoEnGB, result.get(0)); 272 } 273 274 // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and 275 // any subtype whose locale is exactly equal to the specified locale in the given list, 276 // try to find a subtype whose language is equal to the language part of the given locale. 277 // Here make sure that a subtype (locale: "fr_CA") can be found with locale: "fr". 278 { 279 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 280 subtypes.add(nonAutoFrCA); // locale == "fr_CA" 281 subtypes.add(nonAutoJa); 282 subtypes.add(nonAutoFil); 283 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); 284 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); 285 final InputMethodInfo imi = createDummyInputMethodInfo( 286 "com.android.apps.inputmethod.latin", 287 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 288 subtypes); 289 final ArrayList<InputMethodSubtype> result = 290 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR, imi); 291 assertEquals(1, result.size()); 292 verifyEquality(nonAutoFrCA, result.get(0)); 293 } 294 // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA". 295 { 296 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 297 subtypes.add(nonAutoFr); // locale == "fr" 298 subtypes.add(nonAutoJa); 299 subtypes.add(nonAutoFil); 300 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); 301 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); 302 final InputMethodInfo imi = createDummyInputMethodInfo( 303 "com.android.apps.inputmethod.latin", 304 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 305 subtypes); 306 final ArrayList<InputMethodSubtype> result = 307 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR_CA, imi); 308 assertEquals(1, result.size()); 309 verifyEquality(nonAutoFrCA, result.get(0)); 310 } 311 312 // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its 313 // extra value is selected if and only if all other selected IMEs are not AsciiCapable. 314 { 315 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 316 subtypes.add(nonAutoEnUS); 317 subtypes.add(nonAutoJa); // not ASCII capable 318 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); 319 subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); 320 final InputMethodInfo imi = createDummyInputMethodInfo( 321 "com.android.apps.inputmethod.latin", 322 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 323 subtypes); 324 final ArrayList<InputMethodSubtype> result = 325 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_JA_JP, imi); 326 assertEquals(3, result.size()); 327 verifyEquality(nonAutoJa, result.get(0)); 328 verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1)); 329 verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2)); 330 } 331 332 // Make sure that 3-letter language code can be handled. 333 { 334 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 335 subtypes.add(nonAutoEnUS); 336 subtypes.add(nonAutoFil); 337 final InputMethodInfo imi = createDummyInputMethodInfo( 338 "com.android.apps.inputmethod.latin", 339 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 340 subtypes); 341 final ArrayList<InputMethodSubtype> result = 342 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FIL_PH, imi); 343 assertEquals(1, result.size()); 344 verifyEquality(nonAutoFil, result.get(0)); 345 } 346 347 // Make sure that we never end up matching "fi" (finnish) with "fil" (filipino). 348 // Also make sure that the first subtype will be used as the last-resort candidate. 349 { 350 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 351 subtypes.add(nonAutoJa); 352 subtypes.add(nonAutoEnUS); 353 subtypes.add(nonAutoFil); 354 final InputMethodInfo imi = createDummyInputMethodInfo( 355 "com.android.apps.inputmethod.latin", 356 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 357 subtypes); 358 final ArrayList<InputMethodSubtype> result = 359 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FI, imi); 360 assertEquals(1, result.size()); 361 verifyEquality(nonAutoJa, result.get(0)); 362 } 363 364 // Make sure that "in" and "id" conversion is taken into account. 365 { 366 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 367 subtypes.add(nonAutoIn); 368 subtypes.add(nonAutoEnUS); 369 final InputMethodInfo imi = createDummyInputMethodInfo( 370 "com.android.apps.inputmethod.latin", 371 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 372 subtypes); 373 final ArrayList<InputMethodSubtype> result = 374 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi); 375 assertEquals(1, result.size()); 376 verifyEquality(nonAutoIn, result.get(0)); 377 } 378 { 379 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 380 subtypes.add(nonAutoIn); 381 subtypes.add(nonAutoEnUS); 382 final InputMethodInfo imi = createDummyInputMethodInfo( 383 "com.android.apps.inputmethod.latin", 384 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 385 subtypes); 386 final ArrayList<InputMethodSubtype> result = 387 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi); 388 assertEquals(1, result.size()); 389 verifyEquality(nonAutoIn, result.get(0)); 390 } 391 { 392 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 393 subtypes.add(nonAutoId); 394 subtypes.add(nonAutoEnUS); 395 final InputMethodInfo imi = createDummyInputMethodInfo( 396 "com.android.apps.inputmethod.latin", 397 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 398 subtypes); 399 final ArrayList<InputMethodSubtype> result = 400 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi); 401 assertEquals(1, result.size()); 402 verifyEquality(nonAutoId, result.get(0)); 403 } 404 { 405 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 406 subtypes.add(nonAutoId); 407 subtypes.add(nonAutoEnUS); 408 final InputMethodInfo imi = createDummyInputMethodInfo( 409 "com.android.apps.inputmethod.latin", 410 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 411 subtypes); 412 final ArrayList<InputMethodSubtype> result = 413 callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi); 414 assertEquals(1, result.size()); 415 verifyEquality(nonAutoId, result.get(0)); 416 } 417 } 418 419 @SmallTest 420 public void testContainsSubtypeOf() throws Exception { 421 final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", 422 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 423 IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 424 final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", 425 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 426 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 427 final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", 428 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 429 IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 430 final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH", 431 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 432 IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 433 final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", 434 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 435 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 436 final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", 437 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, 438 IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 439 440 final boolean CHECK_COUNTRY = true; 441 442 { 443 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 444 subtypes.add(nonAutoEnUS); 445 final InputMethodInfo imi = createDummyInputMethodInfo( 446 "com.android.apps.inputmethod.latin", 447 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 448 subtypes); 449 450 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY, 451 SUBTYPE_MODE_KEYBOARD)); 452 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, CHECK_COUNTRY, 453 SUBTYPE_MODE_KEYBOARD)); 454 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY, 455 SUBTYPE_MODE_KEYBOARD)); 456 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY, 457 SUBTYPE_MODE_KEYBOARD)); 458 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY, 459 SUBTYPE_MODE_VOICE)); 460 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY, 461 SUBTYPE_MODE_VOICE)); 462 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY, 463 SUBTYPE_MODE_ANY)); 464 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY, 465 SUBTYPE_MODE_ANY)); 466 467 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, !CHECK_COUNTRY, 468 SUBTYPE_MODE_KEYBOARD)); 469 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, CHECK_COUNTRY, 470 SUBTYPE_MODE_KEYBOARD)); 471 } 472 473 // Make sure that 3-letter language code ("fil") can be handled. 474 { 475 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 476 subtypes.add(nonAutoFil); 477 final InputMethodInfo imi = createDummyInputMethodInfo( 478 "com.android.apps.inputmethod.latin", 479 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 480 subtypes); 481 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, 482 SUBTYPE_MODE_KEYBOARD)); 483 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY, 484 SUBTYPE_MODE_KEYBOARD)); 485 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY, 486 SUBTYPE_MODE_KEYBOARD)); 487 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY, 488 SUBTYPE_MODE_KEYBOARD)); 489 490 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY, 491 SUBTYPE_MODE_KEYBOARD)); 492 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY, 493 SUBTYPE_MODE_KEYBOARD)); 494 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY, 495 SUBTYPE_MODE_KEYBOARD)); 496 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY, 497 SUBTYPE_MODE_KEYBOARD)); 498 } 499 500 // Make sure that 3-letter language code ("fil_PH") can be handled. 501 { 502 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 503 subtypes.add(nonAutoFilPH); 504 final InputMethodInfo imi = createDummyInputMethodInfo( 505 "com.android.apps.inputmethod.latin", 506 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 507 subtypes); 508 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, 509 SUBTYPE_MODE_KEYBOARD)); 510 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY, 511 SUBTYPE_MODE_KEYBOARD)); 512 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY, 513 SUBTYPE_MODE_KEYBOARD)); 514 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY, 515 SUBTYPE_MODE_KEYBOARD)); 516 517 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY, 518 SUBTYPE_MODE_KEYBOARD)); 519 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY, 520 SUBTYPE_MODE_KEYBOARD)); 521 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY, 522 SUBTYPE_MODE_KEYBOARD)); 523 assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY, 524 SUBTYPE_MODE_KEYBOARD)); 525 } 526 527 // Make sure that a subtype whose locale is "in" can be queried with "id". 528 { 529 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 530 subtypes.add(nonAutoIn); 531 subtypes.add(nonAutoEnUS); 532 final InputMethodInfo imi = createDummyInputMethodInfo( 533 "com.android.apps.inputmethod.latin", 534 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 535 subtypes); 536 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, 537 SUBTYPE_MODE_KEYBOARD)); 538 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY, 539 SUBTYPE_MODE_KEYBOARD)); 540 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY, 541 SUBTYPE_MODE_KEYBOARD)); 542 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY, 543 SUBTYPE_MODE_KEYBOARD)); 544 } 545 546 // Make sure that a subtype whose locale is "id" can be queried with "in". 547 { 548 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 549 subtypes.add(nonAutoId); 550 subtypes.add(nonAutoEnUS); 551 final InputMethodInfo imi = createDummyInputMethodInfo( 552 "com.android.apps.inputmethod.latin", 553 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, 554 subtypes); 555 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, 556 SUBTYPE_MODE_KEYBOARD)); 557 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY, 558 SUBTYPE_MODE_KEYBOARD)); 559 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY, 560 SUBTYPE_MODE_KEYBOARD)); 561 assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY, 562 SUBTYPE_MODE_KEYBOARD)); 563 } 564 } 565 566 private ArrayList<InputMethodSubtype> callGetImplicitlyApplicableSubtypesLockedWithLocale( 567 final Locale locale, final InputMethodInfo imi) { 568 final Context context = getInstrumentation().getTargetContext(); 569 final Locale initialLocale = context.getResources().getConfiguration().locale; 570 try { 571 context.getResources().getConfiguration().setLocale(locale); 572 return InputMethodUtils.getImplicitlyApplicableSubtypesLocked(context.getResources(), 573 imi); 574 } finally { 575 context.getResources().getConfiguration().setLocale(initialLocale); 576 } 577 } 578 579 private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes, 580 final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) { 581 final Context context = getInstrumentation().getTargetContext(); 582 final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesWithLocale( 583 context, isSystemReady, preinstalledImes, systemLocale)); 584 assertEquals(expectedImeNames.length, actualImeNames.length); 585 for (int i = 0; i < expectedImeNames.length; ++i) { 586 assertEquals(expectedImeNames[i], actualImeNames[i]); 587 } 588 } 589 590 private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) { 591 Parcel p = null; 592 try { 593 p = Parcel.obtain(); 594 p.writeTypedList(list); 595 p.setDataPosition(0); 596 return p.createTypedArrayList(InputMethodInfo.CREATOR); 597 } finally { 598 if (p != null) { 599 p.recycle(); 600 } 601 } 602 } 603 604 private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesWithLocale( 605 final Context context, final boolean isSystemReady, 606 final ArrayList<InputMethodInfo> imis, final Locale locale) { 607 final Locale initialLocale = context.getResources().getConfiguration().locale; 608 try { 609 context.getResources().getConfiguration().setLocale(locale); 610 return InputMethodUtils.getDefaultEnabledImes(context, isSystemReady, imis); 611 } finally { 612 context.getResources().getConfiguration().setLocale(initialLocale); 613 } 614 } 615 616 private String[] getPackageNames(final ArrayList<InputMethodInfo> imis) { 617 final String[] packageNames = new String[imis.size()]; 618 for (int i = 0; i < imis.size(); ++i) { 619 packageNames[i] = imis.get(i).getPackageName(); 620 } 621 return packageNames; 622 } 623 624 private static void verifyEquality(InputMethodInfo expected, InputMethodInfo actual) { 625 assertEquals(expected, actual); 626 assertEquals(expected.getSubtypeCount(), actual.getSubtypeCount()); 627 for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) { 628 final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex); 629 final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex); 630 verifyEquality(expectedSubtype, actualSubtype); 631 } 632 } 633 634 private static void verifyEquality(InputMethodSubtype expected, InputMethodSubtype actual) { 635 assertEquals(expected, actual); 636 assertEquals(expected.hashCode(), actual.hashCode()); 637 } 638 639 private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, 640 CharSequence label, boolean isAuxIme, boolean isDefault, 641 List<InputMethodSubtype> subtypes) { 642 final ResolveInfo ri = new ResolveInfo(); 643 final ServiceInfo si = new ServiceInfo(); 644 final ApplicationInfo ai = new ApplicationInfo(); 645 ai.packageName = packageName; 646 ai.enabled = true; 647 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 648 si.applicationInfo = ai; 649 si.enabled = true; 650 si.packageName = packageName; 651 si.name = name; 652 si.exported = true; 653 si.nonLocalizedLabel = label; 654 ri.serviceInfo = si; 655 return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault); 656 } 657 658 private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, 659 boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, 660 boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) { 661 662 final StringBuilder subtypeExtraValue = new StringBuilder(); 663 if (isEnabledWhenDefaultIsNotAsciiCapable) { 664 subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR); 665 subtypeExtraValue.append(EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); 666 } 667 668 // TODO: Remove following code. InputMethodSubtype#isAsciiCapable() has been publicly 669 // available since API level 19 (KitKat). We no longer need to rely on extra value. 670 if (isAsciiCapable) { 671 subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR); 672 subtypeExtraValue.append(EXTRA_VALUE_ASCII_CAPABLE); 673 } 674 675 return new InputMethodSubtypeBuilder() 676 .setSubtypeNameResId(0) 677 .setSubtypeIconResId(0) 678 .setSubtypeLocale(locale) 679 .setSubtypeMode(mode) 680 .setSubtypeExtraValue(subtypeExtraValue.toString()) 681 .setIsAuxiliary(isAuxiliary) 682 .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype) 683 .setIsAsciiCapable(isAsciiCapable) 684 .build(); 685 } 686 687 private static ArrayList<InputMethodInfo> getImesWithDefaultVoiceIme() { 688 ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); 689 { 690 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 691 subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, 692 IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 693 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 694 subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, 695 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 696 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 697 preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", 698 "dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes)); 699 } 700 preinstalledImes.addAll(getImesWithoutDefaultVoiceIme()); 701 return preinstalledImes; 702 } 703 704 private static ArrayList<InputMethodInfo> getImesWithoutDefaultVoiceIme() { 705 ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); 706 { 707 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 708 subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, 709 IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 710 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 711 subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, 712 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 713 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 714 preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", 715 "dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes)); 716 } 717 { 718 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 719 subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, 720 IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 721 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 722 subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, 723 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 724 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 725 preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", 726 "dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes)); 727 } 728 { 729 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 730 subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, 731 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 732 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 733 preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", 734 "dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes)); 735 } 736 { 737 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 738 subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 739 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, 740 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 741 preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", 742 "dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes)); 743 } 744 return preinstalledImes; 745 } 746 747 private static boolean contains(final String[] textList, final String textToBeChecked) { 748 if (textList == null) { 749 return false; 750 } 751 for (final String text : textList) { 752 if (Objects.equals(textToBeChecked, text)) { 753 return true; 754 } 755 } 756 return false; 757 } 758 759 private static ArrayList<InputMethodInfo> getSamplePreinstalledImes(final String localeString) { 760 ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); 761 762 // a dummy Voice IME 763 { 764 final boolean isDefaultIme = false; 765 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 766 subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX, 767 IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 768 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 769 preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice", 770 "com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme, 771 subtypes)); 772 } 773 // a dummy Hindi IME 774 { 775 final boolean isDefaultIme = contains(new String[]{ "hi", "en-rIN" }, localeString); 776 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 777 // TODO: This subtype should be marked as IS_ASCII_CAPABLE 778 subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 779 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 780 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 781 subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 782 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 783 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 784 preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi", 785 "com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme, 786 subtypes)); 787 } 788 789 // a dummy Pinyin IME 790 { 791 final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString); 792 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 793 subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 794 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 795 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 796 preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin", 797 "com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme, 798 subtypes)); 799 } 800 801 // a dummy Korean IME 802 { 803 final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString); 804 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 805 subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 806 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 807 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 808 preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean", 809 "com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme, 810 subtypes)); 811 } 812 813 // a dummy Latin IME 814 { 815 final boolean isDefaultIme = contains( 816 new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString); 817 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 818 subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 819 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, 820 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 821 subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 822 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, 823 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 824 subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 825 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, 826 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 827 subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 828 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, 829 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 830 preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin", 831 "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme, 832 subtypes)); 833 } 834 835 // a dummy Japanese IME 836 { 837 final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString); 838 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 839 subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 840 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 841 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 842 subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX, 843 !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, 844 !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); 845 preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese", 846 "com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX, 847 isDefaultIme, subtypes)); 848 } 849 850 return preinstalledImes; 851 } 852} 853