InputMethodTest.java revision 443c2bafd824779a75cd4b922b6839a8df9795e9
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 com.android.internal.inputmethod.InputMethodUtils; 20 21import android.content.Context; 22import android.content.pm.ApplicationInfo; 23import android.content.pm.ResolveInfo; 24import android.content.pm.ServiceInfo; 25import android.test.InstrumentationTestCase; 26import android.test.suitebuilder.annotation.SmallTest; 27import android.view.inputmethod.InputMethodInfo; 28import android.view.inputmethod.InputMethodSubtype; 29import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; 30 31import java.util.ArrayList; 32import java.util.List; 33 34public class InputMethodTest extends InstrumentationTestCase { 35 private static final boolean IS_AUX = true; 36 private static final boolean IS_DEFAULT = true; 37 private static final boolean IS_AUTO = true; 38 private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null; 39 40 @SmallTest 41 public void testDefaultEnabledImesWithDefaultVoiceIme() throws Exception { 42 final Context context = getInstrumentation().getTargetContext(); 43 final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>(); 44 imis.add(createDefaultAutoDummyVoiceIme()); 45 imis.add(createNonDefaultAutoDummyVoiceIme0()); 46 imis.add(createNonDefaultAutoDummyVoiceIme1()); 47 imis.add(createNonDefaultDummyVoiceIme2()); 48 imis.add(createDefaultDummyEnUSKeyboardIme()); 49 imis.add(createNonDefaultDummyJaJPKeyboardIme()); 50 imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes()); 51 final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes( 52 context, true, imis); 53 assertEquals(2, enabledImis.size()); 54 for (int i = 0; i < enabledImis.size(); ++i) { 55 final InputMethodInfo imi = enabledImis.get(0); 56 // "DummyDefaultAutoVoiceIme" and "DummyDefaultEnKeyboardIme" 57 if (imi.getPackageName().equals("DummyDefaultAutoVoiceIme") 58 || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) { 59 continue; 60 } else { 61 fail("Invalid enabled subtype."); 62 } 63 } 64 } 65 66 @SmallTest 67 public void testDefaultEnabledImesWithOutDefaultVoiceIme() throws Exception { 68 final Context context = getInstrumentation().getTargetContext(); 69 final ArrayList<InputMethodInfo> imis = new ArrayList<InputMethodInfo>(); 70 imis.add(createNonDefaultAutoDummyVoiceIme0()); 71 imis.add(createNonDefaultAutoDummyVoiceIme1()); 72 imis.add(createNonDefaultDummyVoiceIme2()); 73 imis.add(createDefaultDummyEnUSKeyboardIme()); 74 imis.add(createNonDefaultDummyJaJPKeyboardIme()); 75 imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes()); 76 final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes( 77 context, true, imis); 78 assertEquals(3, enabledImis.size()); 79 for (int i = 0; i < enabledImis.size(); ++i) { 80 final InputMethodInfo imi = enabledImis.get(0); 81 // "DummyNonDefaultAutoVoiceIme0", "DummyNonDefaultAutoVoiceIme1" and 82 // "DummyDefaultEnKeyboardIme" 83 if (imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme0") 84 || imi.getPackageName().equals("DummyNonDefaultAutoVoiceIme1") 85 || imi.getPackageName().equals("DummyDefaultEnKeyboardIme")) { 86 continue; 87 } else { 88 fail("Invalid enabled subtype."); 89 } 90 } 91 } 92 93 @SmallTest 94 public void testParcelable() throws Exception { 95 final ArrayList<InputMethodInfo> originalList = new ArrayList<InputMethodInfo>(); 96 originalList.add(createNonDefaultAutoDummyVoiceIme0()); 97 originalList.add(createNonDefaultAutoDummyVoiceIme1()); 98 originalList.add(createNonDefaultDummyVoiceIme2()); 99 originalList.add(createDefaultDummyEnUSKeyboardIme()); 100 originalList.add(createNonDefaultDummyJaJPKeyboardIme()); 101 originalList.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes()); 102 103 final List<InputMethodInfo> clonedList = cloneViaParcel(originalList); 104 assertNotNull(clonedList); 105 final List<InputMethodInfo> clonedClonedList = cloneViaParcel(clonedList); 106 assertNotNull(clonedClonedList); 107 assertEquals(originalList, clonedList); 108 assertEquals(clonedList, clonedClonedList); 109 assertEquals(originalList.size(), clonedList.size()); 110 assertEquals(clonedList.size(), clonedClonedList.size()); 111 for (int imeIndex = 0; imeIndex < originalList.size(); ++imeIndex) { 112 verifyEquality(originalList.get(imeIndex), clonedList.get(imeIndex)); 113 verifyEquality(clonedList.get(imeIndex), clonedClonedList.get(imeIndex)); 114 } 115 } 116 117 private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) { 118 Parcel p = null; 119 try { 120 p = Parcel.obtain(); 121 p.writeTypedList(list); 122 p.setDataPosition(0); 123 return p.createTypedArrayList(InputMethodInfo.CREATOR); 124 } finally { 125 if (p != null) { 126 p.recycle(); 127 } 128 } 129 } 130 131 private static void verifyEquality(InputMethodInfo expected, InputMethodInfo actual) { 132 assertEquals(expected, actual); 133 assertEquals(expected.getSubtypeCount(), actual.getSubtypeCount()); 134 for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) { 135 final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex); 136 final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex); 137 assertEquals(expectedSubtype, actualSubtype); 138 assertEquals(expectedSubtype.hashCode(), actualSubtype.hashCode()); 139 } 140 } 141 142 private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, 143 CharSequence label, boolean isAuxIme, boolean isDefault, 144 List<InputMethodSubtype> subtypes) { 145 final ResolveInfo ri = new ResolveInfo(); 146 final ServiceInfo si = new ServiceInfo(); 147 final ApplicationInfo ai = new ApplicationInfo(); 148 ai.packageName = packageName; 149 ai.enabled = true; 150 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 151 si.applicationInfo = ai; 152 si.enabled = true; 153 si.packageName = packageName; 154 si.name = name; 155 si.exported = true; 156 si.nonLocalizedLabel = label; 157 ri.serviceInfo = si; 158 return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault); 159 } 160 161 private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, 162 boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) { 163 return new InputMethodSubtypeBuilder() 164 .setSubtypeNameResId(0) 165 .setSubtypeIconResId(0) 166 .setSubtypeLocale(locale) 167 .setSubtypeMode(mode) 168 .setSubtypeExtraValue("") 169 .setIsAuxiliary(isAuxiliary) 170 .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype) 171 .build(); 172 } 173 174 private static InputMethodInfo createDefaultAutoDummyVoiceIme() { 175 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 176 subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); 177 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 178 return createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0", 179 "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes); 180 } 181 182 private static InputMethodInfo createNonDefaultAutoDummyVoiceIme0() { 183 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 184 subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); 185 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 186 return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1", 187 "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes); 188 } 189 190 private static InputMethodInfo createNonDefaultAutoDummyVoiceIme1() { 191 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 192 subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); 193 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 194 return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2", 195 "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes); 196 } 197 198 private static InputMethodInfo createNonDefaultDummyVoiceIme2() { 199 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 200 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 201 return createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3", 202 "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes); 203 } 204 205 private static InputMethodInfo createDefaultDummyEnUSKeyboardIme() { 206 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 207 subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO)); 208 return createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0", 209 "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes); 210 } 211 212 private static InputMethodInfo createNonDefaultDummyJaJPKeyboardIme() { 213 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 214 subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO)); 215 return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1", 216 "DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes); 217 } 218 219 // Although IMEs that have no subtype are considered to be deprecated, the Android framework 220 // must still be able to handle such IMEs as well as IMEs that have at least one subtype. 221 private static InputMethodInfo createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes() { 222 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 223 return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardImeWithoutSubtypes", 224 "dummy.keyboard2", "DummyKeyboard2", !IS_AUX, !IS_DEFAULT, NO_SUBTYPE); 225 } 226} 227