1 /* 2 * Copyright (C) 2008 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 17 package android.view.inputmethod.cts; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageManager; 24 import android.content.pm.ResolveInfo; 25 import android.content.pm.ServiceInfo; 26 import android.content.res.Resources; 27 import android.os.Parcel; 28 import android.test.AndroidTestCase; 29 import android.util.Printer; 30 import android.view.inputmethod.InputMethod; 31 import android.view.inputmethod.InputMethodInfo; 32 import android.view.inputmethod.InputMethodManager; 33 import android.view.inputmethod.InputMethodSubtype; 34 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import java.io.IOException; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.List; 41 42 public class InputMethodInfoTest extends AndroidTestCase { 43 private InputMethodInfo mInputMethodInfo; 44 private String mPackageName; 45 private String mClassName; 46 private CharSequence mLabel; 47 private String mSettingsActivity; 48 49 private int mSubtypeNameResId; 50 private int mSubtypeIconResId; 51 private String mSubtypeLocale; 52 private String mSubtypeMode; 53 private String mSubtypeExtraValue_key; 54 private String mSubtypeExtraValue_value; 55 private String mSubtypeExtraValue; 56 private boolean mSubtypeIsAuxiliary; 57 private boolean mSubtypeOverridesImplicitlyEnabledSubtype; 58 private int mSubtypeId; 59 private InputMethodSubtype mInputMethodSubtype; 60 61 @Override setUp()62 protected void setUp() throws Exception { 63 super.setUp(); 64 mPackageName = mContext.getPackageName(); 65 mClassName = InputMethodSettingsActivityStub.class.getName(); 66 mLabel = "test"; 67 mSettingsActivity = "android.view.inputmethod.cts.InputMethodSettingsActivityStub"; 68 mInputMethodInfo = new InputMethodInfo(mPackageName, mClassName, mLabel, mSettingsActivity); 69 70 mSubtypeNameResId = 0; 71 mSubtypeIconResId = 0; 72 mSubtypeLocale = "en_US"; 73 mSubtypeMode = "keyboard"; 74 mSubtypeExtraValue_key = "key1"; 75 mSubtypeExtraValue_value = "value1"; 76 mSubtypeExtraValue = "tag," + mSubtypeExtraValue_key + "=" + mSubtypeExtraValue_value; 77 mSubtypeIsAuxiliary = false; 78 mSubtypeOverridesImplicitlyEnabledSubtype = false; 79 mSubtypeId = 99; 80 mInputMethodSubtype = new InputMethodSubtype(mSubtypeNameResId, mSubtypeIconResId, 81 mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue, mSubtypeIsAuxiliary, 82 mSubtypeOverridesImplicitlyEnabledSubtype, mSubtypeId); 83 } 84 testInputMethodInfoProperties()85 public void testInputMethodInfoProperties() throws XmlPullParserException, IOException { 86 assertEquals(0, mInputMethodInfo.describeContents()); 87 assertNotNull(mInputMethodInfo.toString()); 88 89 assertInfo(mInputMethodInfo); 90 assertEquals(0, mInputMethodInfo.getIsDefaultResourceId()); 91 92 Intent intent = new Intent(InputMethod.SERVICE_INTERFACE); 93 intent.setClass(mContext, InputMethodSettingsActivityStub.class); 94 PackageManager pm = mContext.getPackageManager(); 95 List<ResolveInfo> ris = pm.queryIntentServices(intent, PackageManager.GET_META_DATA); 96 for (int i = 0; i < ris.size(); i++) { 97 ResolveInfo resolveInfo = ris.get(i); 98 mInputMethodInfo = new InputMethodInfo(mContext, resolveInfo); 99 assertService(resolveInfo.serviceInfo, mInputMethodInfo.getServiceInfo()); 100 assertInfo(mInputMethodInfo); 101 } 102 } 103 testInputMethodSubtypeProperties()104 public void testInputMethodSubtypeProperties() { 105 // TODO: Test InputMethodSubtype.getDisplayName() 106 assertEquals(mSubtypeNameResId, mInputMethodSubtype.getNameResId()); 107 assertEquals(mSubtypeIconResId, mInputMethodSubtype.getIconResId()); 108 assertEquals(mSubtypeLocale, mInputMethodSubtype.getLocale()); 109 assertEquals(mSubtypeMode, mInputMethodSubtype.getMode()); 110 assertEquals(mSubtypeExtraValue, mInputMethodSubtype.getExtraValue()); 111 assertTrue(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key)); 112 assertEquals(mSubtypeExtraValue_value, 113 mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValue_key)); 114 assertEquals(mSubtypeIsAuxiliary, mInputMethodSubtype.isAuxiliary()); 115 assertEquals(mSubtypeOverridesImplicitlyEnabledSubtype, 116 mInputMethodSubtype.overridesImplicitlyEnabledSubtype()); 117 assertEquals(mSubtypeId, mInputMethodSubtype.hashCode()); 118 } 119 assertService(ServiceInfo expected, ServiceInfo actual)120 private void assertService(ServiceInfo expected, ServiceInfo actual) { 121 assertEquals(expected.getIconResource(), actual.getIconResource()); 122 assertEquals(expected.labelRes, actual.labelRes); 123 assertEquals(expected.nonLocalizedLabel, actual.nonLocalizedLabel); 124 assertEquals(expected.icon, actual.icon); 125 assertEquals(expected.permission, actual.permission); 126 } 127 assertInfo(InputMethodInfo info)128 private void assertInfo(InputMethodInfo info) { 129 assertEquals(mPackageName, info.getPackageName()); 130 assertEquals(mSettingsActivity, info.getSettingsActivity()); 131 ComponentName component = info.getComponent(); 132 assertEquals(mClassName, component.getClassName()); 133 String expectedId = component.flattenToShortString(); 134 assertEquals(expectedId, info.getId()); 135 assertEquals(mClassName, info.getServiceName()); 136 } 137 testDump()138 public void testDump() { 139 MockPrinter printer = new MockPrinter(); 140 String prefix = "test"; 141 mInputMethodInfo.dump(printer, prefix); 142 } 143 testLoadIcon()144 public void testLoadIcon() { 145 PackageManager pm = mContext.getPackageManager(); 146 assertNotNull(mInputMethodInfo.loadIcon(pm)); 147 } 148 testEquals()149 public void testEquals() { 150 InputMethodInfo inputMethodInfo = new InputMethodInfo(mPackageName, mClassName, mLabel, 151 mSettingsActivity); 152 assertTrue(inputMethodInfo.equals(mInputMethodInfo)); 153 } 154 testLoadLabel()155 public void testLoadLabel() { 156 CharSequence expected = "test"; 157 PackageManager pm = mContext.getPackageManager(); 158 assertEquals(expected.toString(), mInputMethodInfo.loadLabel(pm).toString()); 159 } 160 testInputMethodInfoWriteToParcel()161 public void testInputMethodInfoWriteToParcel() { 162 final Parcel p = Parcel.obtain(); 163 mInputMethodInfo.writeToParcel(p, 0); 164 p.setDataPosition(0); 165 final InputMethodInfo imi = InputMethodInfo.CREATOR.createFromParcel(p); 166 p.recycle(); 167 168 assertEquals(mInputMethodInfo.getPackageName(), imi.getPackageName()); 169 assertEquals(mInputMethodInfo.getServiceName(), imi.getServiceName()); 170 assertEquals(mInputMethodInfo.getSettingsActivity(), imi.getSettingsActivity()); 171 assertEquals(mInputMethodInfo.getId(), imi.getId()); 172 assertEquals(mInputMethodInfo.getIsDefaultResourceId(), imi.getIsDefaultResourceId()); 173 assertService(mInputMethodInfo.getServiceInfo(), imi.getServiceInfo()); 174 } 175 testInputMethodSubtypeWriteToParcel()176 public void testInputMethodSubtypeWriteToParcel() { 177 final Parcel p = Parcel.obtain(); 178 mInputMethodSubtype.writeToParcel(p, 0); 179 p.setDataPosition(0); 180 final InputMethodSubtype subtype = InputMethodSubtype.CREATOR.createFromParcel(p); 181 p.recycle(); 182 183 assertEquals(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key), 184 subtype.containsExtraValueKey(mSubtypeExtraValue_key)); 185 assertEquals(mInputMethodSubtype.getExtraValue(), subtype.getExtraValue()); 186 assertEquals(mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValue_key), 187 subtype.getExtraValueOf(mSubtypeExtraValue_key)); 188 assertEquals(mInputMethodSubtype.getIconResId(), subtype.getIconResId()); 189 assertEquals(mInputMethodSubtype.getLocale(), subtype.getLocale()); 190 assertEquals(mInputMethodSubtype.getMode(), subtype.getMode()); 191 assertEquals(mInputMethodSubtype.getNameResId(), subtype.getNameResId()); 192 assertEquals(mInputMethodSubtype.hashCode(), subtype.hashCode()); 193 assertEquals(mInputMethodSubtype.isAuxiliary(), subtype.isAuxiliary()); 194 assertEquals(mInputMethodSubtype.overridesImplicitlyEnabledSubtype(), 195 subtype.overridesImplicitlyEnabledSubtype()); 196 } 197 testInputMethodSubtypesOfSystemImes()198 public void testInputMethodSubtypesOfSystemImes() { 199 if (!getContext().getPackageManager().hasSystemFeature( 200 PackageManager.FEATURE_INPUT_METHODS)) { 201 return; 202 } 203 204 final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class); 205 final List<InputMethodInfo> imis = imm.getInputMethodList(); 206 final ArrayList<String> localeList = new ArrayList<>(Arrays.asList( 207 Resources.getSystem().getAssets().getLocales())); 208 boolean foundEnabledSystemImeSubtypeWithValidLanguage = false; 209 for (InputMethodInfo imi : imis) { 210 if ((imi.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 211 continue; 212 } 213 final int subtypeCount = imi.getSubtypeCount(); 214 // System IME must have one subtype at least. 215 assertTrue(subtypeCount > 0); 216 if (foundEnabledSystemImeSubtypeWithValidLanguage) { 217 continue; 218 } 219 final List<InputMethodSubtype> enabledSubtypes = 220 imm.getEnabledInputMethodSubtypeList(imi, true); 221 SUBTYPE_LOOP: 222 for (InputMethodSubtype subtype : enabledSubtypes) { 223 final String subtypeLocale = subtype.getLocale(); 224 if (subtypeLocale.length() < 2) { 225 continue; 226 } 227 // TODO: Detect language more strictly. 228 final String subtypeLanguage = subtypeLocale.substring(0, 2); 229 for (final String locale : localeList) { 230 if (locale.startsWith(subtypeLanguage)) { 231 foundEnabledSystemImeSubtypeWithValidLanguage = true; 232 break SUBTYPE_LOOP; 233 } 234 } 235 } 236 } 237 assertTrue(foundEnabledSystemImeSubtypeWithValidLanguage); 238 } 239 testAtLeastOneEncryptionAwareInputMethodIsAvailable()240 public void testAtLeastOneEncryptionAwareInputMethodIsAvailable() { 241 if (!getContext().getPackageManager().hasSystemFeature( 242 PackageManager.FEATURE_INPUT_METHODS)) { 243 return; 244 } 245 246 final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class); 247 final List<InputMethodInfo> imis = imm.getInputMethodList(); 248 boolean hasEncryptionAwareInputMethod = false; 249 for (final InputMethodInfo imi : imis) { 250 final ServiceInfo serviceInfo = imi.getServiceInfo(); 251 if (serviceInfo == null) { 252 continue; 253 } 254 if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 255 ApplicationInfo.FLAG_SYSTEM) { 256 continue; 257 } 258 if (serviceInfo.encryptionAware) { 259 hasEncryptionAwareInputMethod = true; 260 break; 261 } 262 } 263 assertTrue(hasEncryptionAwareInputMethod); 264 } 265 266 class MockPrinter implements Printer { 267 @Override println(String x)268 public void println(String x) { 269 } 270 } 271 } 272