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