InputMethodTest.java revision 589800485d770cab7b159ffcf4b18c10ae2aee6d
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 assertEquals(originalList.size(), clonedList.size()); 105 assertEquals(originalList, clonedList); 106 107 for (int imeIndex = 0; imeIndex < originalList.size(); ++imeIndex) { 108 final InputMethodInfo original = originalList.get(imeIndex); 109 final InputMethodInfo cloned = clonedList.get(imeIndex); 110 assertEquals(original, cloned); 111 assertEquals(original.getSubtypeCount(), cloned.getSubtypeCount()); 112 for (int subtypeIndex = 0; subtypeIndex < original.getSubtypeCount(); ++subtypeIndex) { 113 final InputMethodSubtype originalSubtype = original.getSubtypeAt(subtypeIndex); 114 final InputMethodSubtype clonedSubtype = cloned.getSubtypeAt(subtypeIndex); 115 assertEquals(originalSubtype, clonedSubtype); 116 assertEquals(originalSubtype.hashCode(), clonedSubtype.hashCode()); 117 } 118 } 119 } 120 121 private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) { 122 Parcel p = null; 123 try { 124 p = Parcel.obtain(); 125 p.writeTypedList(list); 126 p.setDataPosition(0); 127 return p.createTypedArrayList(InputMethodInfo.CREATOR); 128 } finally { 129 if (p != null) { 130 p.recycle(); 131 } 132 } 133 } 134 135 private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, 136 CharSequence label, boolean isAuxIme, boolean isDefault, 137 List<InputMethodSubtype> subtypes) { 138 final ResolveInfo ri = new ResolveInfo(); 139 final ServiceInfo si = new ServiceInfo(); 140 final ApplicationInfo ai = new ApplicationInfo(); 141 ai.packageName = packageName; 142 ai.enabled = true; 143 ai.flags |= ApplicationInfo.FLAG_SYSTEM; 144 si.applicationInfo = ai; 145 si.enabled = true; 146 si.packageName = packageName; 147 si.name = name; 148 si.exported = true; 149 si.nonLocalizedLabel = label; 150 ri.serviceInfo = si; 151 return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault); 152 } 153 154 private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, 155 boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) { 156 return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary, 157 overridesImplicitlyEnabledSubtype); 158 } 159 160 private static InputMethodInfo createDefaultAutoDummyVoiceIme() { 161 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 162 subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); 163 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 164 return createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0", 165 "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes); 166 } 167 168 private static InputMethodInfo createNonDefaultAutoDummyVoiceIme0() { 169 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 170 subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); 171 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 172 return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1", 173 "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes); 174 } 175 176 private static InputMethodInfo createNonDefaultAutoDummyVoiceIme1() { 177 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 178 subtypes.add(createDummyInputMethodSubtype("auto", "voice", IS_AUX, IS_AUTO)); 179 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 180 return createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2", 181 "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes); 182 } 183 184 private static InputMethodInfo createNonDefaultDummyVoiceIme2() { 185 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 186 subtypes.add(createDummyInputMethodSubtype("en_US", "voice", IS_AUX, !IS_AUTO)); 187 return createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3", 188 "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes); 189 } 190 191 private static InputMethodInfo createDefaultDummyEnUSKeyboardIme() { 192 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 193 subtypes.add(createDummyInputMethodSubtype("en_US", "keyboard", !IS_AUX, !IS_AUTO)); 194 return createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0", 195 "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes); 196 } 197 198 private static InputMethodInfo createNonDefaultDummyJaJPKeyboardIme() { 199 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 200 subtypes.add(createDummyInputMethodSubtype("ja_JP", "keyboard", !IS_AUX, !IS_AUTO)); 201 return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1", 202 "DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes); 203 } 204 205 // Although IMEs that have no subtype are considered to be deprecated, the Android framework 206 // must still be able to handle such IMEs as well as IMEs that have at least one subtype. 207 private static InputMethodInfo createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes() { 208 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); 209 return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardImeWithoutSubtypes", 210 "dummy.keyboard2", "DummyKeyboard2", !IS_AUX, !IS_DEFAULT, NO_SUBTYPE); 211 } 212} 213