Home | History | Annotate | Download | only in cts
      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 static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertNotNull;
     21 import static org.junit.Assert.assertTrue;
     22 import static org.mockito.Matchers.anyString;
     23 import static org.mockito.Mockito.atLeastOnce;
     24 import static org.mockito.Mockito.mock;
     25 import static org.mockito.Mockito.verify;
     26 
     27 import android.content.ComponentName;
     28 import android.content.Context;
     29 import android.content.Intent;
     30 import android.content.pm.ApplicationInfo;
     31 import android.content.pm.PackageManager;
     32 import android.content.pm.ResolveInfo;
     33 import android.content.pm.ServiceInfo;
     34 import android.os.Parcel;
     35 import android.os.ParcelFileDescriptor;
     36 import android.text.TextUtils;
     37 import android.util.Printer;
     38 import android.view.inputmethod.InputMethod;
     39 import android.view.inputmethod.InputMethodInfo;
     40 import android.view.inputmethod.InputMethodManager;
     41 import android.view.inputmethod.InputMethodSubtype;
     42 
     43 import androidx.test.InstrumentationRegistry;
     44 import androidx.test.filters.SmallTest;
     45 import androidx.test.runner.AndroidJUnit4;
     46 
     47 import org.junit.Before;
     48 import org.junit.Test;
     49 import org.junit.runner.RunWith;
     50 import org.xmlpull.v1.XmlPullParserException;
     51 
     52 import java.io.BufferedReader;
     53 import java.io.IOException;
     54 import java.io.InputStreamReader;
     55 import java.nio.charset.StandardCharsets;
     56 import java.util.List;
     57 
     58 @SmallTest
     59 @RunWith(AndroidJUnit4.class)
     60 public class InputMethodInfoTest {
     61     private Context mContext;
     62 
     63     private InputMethodInfo mInputMethodInfo;
     64     private String mPackageName;
     65     private String mClassName;
     66     private CharSequence mLabel;
     67     private String mSettingsActivity;
     68 
     69     private int mSubtypeNameResId;
     70     private int mSubtypeIconResId;
     71     private String mSubtypeLocale;
     72     private String mSubtypeMode;
     73     private String mSubtypeExtraValueKey;
     74     private String mSubtypeExtraValueValue;
     75     private String mSubtypeExtraValue;
     76     private boolean mSubtypeIsAuxiliary;
     77     private boolean mSubtypeOverridesImplicitlyEnabledSubtype;
     78     private int mSubtypeId;
     79     private InputMethodSubtype mInputMethodSubtype;
     80 
     81     @Before
     82     public void setup() {
     83         mContext = InstrumentationRegistry.getTargetContext();
     84         mPackageName = mContext.getPackageName();
     85         mClassName = InputMethodSettingsActivityStub.class.getName();
     86         mLabel = "test";
     87         mSettingsActivity = "android.view.inputmethod.cts.InputMethodSettingsActivityStub";
     88         mInputMethodInfo = new InputMethodInfo(mPackageName, mClassName, mLabel, mSettingsActivity);
     89 
     90         mSubtypeNameResId = 0;
     91         mSubtypeIconResId = 0;
     92         mSubtypeLocale = "en_US";
     93         mSubtypeMode = "keyboard";
     94         mSubtypeExtraValueKey = "key1";
     95         mSubtypeExtraValueValue = "value1";
     96         mSubtypeExtraValue = "tag," + mSubtypeExtraValueKey + "=" + mSubtypeExtraValueValue;
     97         mSubtypeIsAuxiliary = false;
     98         mSubtypeOverridesImplicitlyEnabledSubtype = false;
     99         mSubtypeId = 99;
    100         mInputMethodSubtype = new InputMethodSubtype(mSubtypeNameResId, mSubtypeIconResId,
    101                 mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue, mSubtypeIsAuxiliary,
    102                 mSubtypeOverridesImplicitlyEnabledSubtype, mSubtypeId);
    103     }
    104 
    105     @Test
    106     public void testInputMethodInfoProperties() throws XmlPullParserException, IOException {
    107         assertEquals(0, mInputMethodInfo.describeContents());
    108         assertNotNull(mInputMethodInfo.toString());
    109 
    110         assertInfo(mInputMethodInfo);
    111         assertEquals(0, mInputMethodInfo.getIsDefaultResourceId());
    112 
    113         Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
    114         intent.setClass(mContext, InputMethodSettingsActivityStub.class);
    115         PackageManager pm = mContext.getPackageManager();
    116         List<ResolveInfo> ris = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
    117         for (int i = 0; i < ris.size(); i++) {
    118             ResolveInfo resolveInfo = ris.get(i);
    119             mInputMethodInfo = new InputMethodInfo(mContext, resolveInfo);
    120             assertService(resolveInfo.serviceInfo, mInputMethodInfo.getServiceInfo());
    121             assertInfo(mInputMethodInfo);
    122         }
    123     }
    124 
    125     @Test
    126     public void testInputMethodSubtypeProperties() {
    127         // TODO: Test InputMethodSubtype.getDisplayName()
    128         assertEquals(mSubtypeNameResId, mInputMethodSubtype.getNameResId());
    129         assertEquals(mSubtypeIconResId, mInputMethodSubtype.getIconResId());
    130         assertEquals(mSubtypeLocale, mInputMethodSubtype.getLocale());
    131         assertEquals(mSubtypeMode, mInputMethodSubtype.getMode());
    132         assertEquals(mSubtypeExtraValue, mInputMethodSubtype.getExtraValue());
    133         assertTrue(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValueKey));
    134         assertEquals(mSubtypeExtraValueValue,
    135                 mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValueKey));
    136         assertEquals(mSubtypeIsAuxiliary, mInputMethodSubtype.isAuxiliary());
    137         assertEquals(mSubtypeOverridesImplicitlyEnabledSubtype,
    138                 mInputMethodSubtype.overridesImplicitlyEnabledSubtype());
    139         assertEquals(mSubtypeId, mInputMethodSubtype.hashCode());
    140     }
    141 
    142     private void assertService(ServiceInfo expected, ServiceInfo actual) {
    143         assertEquals(expected.getIconResource(), actual.getIconResource());
    144         assertEquals(expected.labelRes, actual.labelRes);
    145         assertEquals(expected.nonLocalizedLabel, actual.nonLocalizedLabel);
    146         assertEquals(expected.icon, actual.icon);
    147         assertEquals(expected.permission, actual.permission);
    148     }
    149 
    150     private void assertInfo(InputMethodInfo info) {
    151         assertEquals(mPackageName, info.getPackageName());
    152         assertEquals(mSettingsActivity, info.getSettingsActivity());
    153         ComponentName component = info.getComponent();
    154         assertEquals(mClassName, component.getClassName());
    155         String expectedId = component.flattenToShortString();
    156         assertEquals(expectedId, info.getId());
    157         assertEquals(mClassName, info.getServiceName());
    158     }
    159 
    160     @Test
    161     public void testDump() {
    162         Printer printer = mock(Printer.class);
    163         String prefix = "test";
    164         mInputMethodInfo.dump(printer, prefix);
    165         verify(printer, atLeastOnce()).println(anyString());
    166     }
    167 
    168     @Test
    169     public void testLoadIcon() {
    170         PackageManager pm = mContext.getPackageManager();
    171         assertNotNull(mInputMethodInfo.loadIcon(pm));
    172     }
    173 
    174     @Test
    175     public void testEquals() {
    176         InputMethodInfo inputMethodInfo = new InputMethodInfo(mPackageName, mClassName, mLabel,
    177                 mSettingsActivity);
    178         assertTrue(inputMethodInfo.equals(mInputMethodInfo));
    179     }
    180 
    181     @Test
    182     public void testLoadLabel() {
    183         CharSequence expected = "test";
    184         PackageManager pm = mContext.getPackageManager();
    185         assertEquals(expected.toString(), mInputMethodInfo.loadLabel(pm).toString());
    186     }
    187 
    188     @Test
    189     public void testInputMethodInfoWriteToParcel() {
    190         final Parcel p = Parcel.obtain();
    191         mInputMethodInfo.writeToParcel(p, 0);
    192         p.setDataPosition(0);
    193         final InputMethodInfo imi = InputMethodInfo.CREATOR.createFromParcel(p);
    194         p.recycle();
    195 
    196         assertEquals(mInputMethodInfo.getPackageName(), imi.getPackageName());
    197         assertEquals(mInputMethodInfo.getServiceName(), imi.getServiceName());
    198         assertEquals(mInputMethodInfo.getSettingsActivity(), imi.getSettingsActivity());
    199         assertEquals(mInputMethodInfo.getId(), imi.getId());
    200         assertEquals(mInputMethodInfo.getIsDefaultResourceId(), imi.getIsDefaultResourceId());
    201         assertService(mInputMethodInfo.getServiceInfo(), imi.getServiceInfo());
    202     }
    203 
    204     @Test
    205     public void testInputMethodSubtypeWriteToParcel() {
    206         final Parcel p = Parcel.obtain();
    207         mInputMethodSubtype.writeToParcel(p, 0);
    208         p.setDataPosition(0);
    209         final InputMethodSubtype subtype = InputMethodSubtype.CREATOR.createFromParcel(p);
    210         p.recycle();
    211 
    212         assertEquals(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValueKey),
    213                 subtype.containsExtraValueKey(mSubtypeExtraValueKey));
    214         assertEquals(mInputMethodSubtype.getExtraValue(), subtype.getExtraValue());
    215         assertEquals(mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValueKey),
    216                 subtype.getExtraValueOf(mSubtypeExtraValueKey));
    217         assertEquals(mInputMethodSubtype.getIconResId(), subtype.getIconResId());
    218         assertEquals(mInputMethodSubtype.getLocale(), subtype.getLocale());
    219         assertEquals(mInputMethodSubtype.getMode(), subtype.getMode());
    220         assertEquals(mInputMethodSubtype.getNameResId(), subtype.getNameResId());
    221         assertEquals(mInputMethodSubtype.hashCode(), subtype.hashCode());
    222         assertEquals(mInputMethodSubtype.isAuxiliary(), subtype.isAuxiliary());
    223         assertEquals(mInputMethodSubtype.overridesImplicitlyEnabledSubtype(),
    224                 subtype.overridesImplicitlyEnabledSubtype());
    225     }
    226 
    227     @Test
    228     public void testAtLeastOneEncryptionAwareInputMethodIsAvailable() {
    229         if (!mContext.getPackageManager().hasSystemFeature(
    230                 PackageManager.FEATURE_INPUT_METHODS)) {
    231             return;
    232         }
    233 
    234         if (!TextUtils.equals("native", getFbeMode())) {
    235             // Skip the test unless the device is in native FBE mode.
    236             return;
    237         }
    238 
    239         final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
    240         final List<InputMethodInfo> imis = imm.getInputMethodList();
    241         boolean hasEncryptionAwareInputMethod = false;
    242         for (final InputMethodInfo imi : imis) {
    243             final ServiceInfo serviceInfo = imi.getServiceInfo();
    244             if (serviceInfo == null) {
    245                 continue;
    246             }
    247             if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
    248                     != ApplicationInfo.FLAG_SYSTEM) {
    249                 continue;
    250             }
    251             if (serviceInfo.directBootAware) {
    252                 hasEncryptionAwareInputMethod = true;
    253                 break;
    254             }
    255         }
    256         assertTrue(hasEncryptionAwareInputMethod);
    257     }
    258 
    259     private String getFbeMode() {
    260         try (ParcelFileDescriptor.AutoCloseInputStream in =
    261                      new ParcelFileDescriptor.AutoCloseInputStream(InstrumentationRegistry
    262                              .getInstrumentation()
    263                              .getUiAutomation()
    264                              .executeShellCommand("sm get-fbe-mode"))) {
    265             try (BufferedReader br =
    266                          new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
    267                 // Assume that the output of "sm get-fbe-mode" is always one-line.
    268                 final String line = br.readLine();
    269                 return line != null ? line.trim() : "";
    270             }
    271         } catch (IOException e) {
    272             return "";
    273         }
    274     }
    275 }
    276