Home | History | Annotate | Download | only in hostside
      1 /*
      2  * Copyright (C) 2017 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.inputmethodservice.cts.hostside;
     18 
     19 import static android.inputmethodservice.cts.common.DeviceEventConstants.ACTION_DEVICE_EVENT;
     20 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.TEST_START;
     21 import static android.inputmethodservice.cts.common.DeviceEventConstants.EXTRA_EVENT_SENDER;
     22 import static android.inputmethodservice.cts.common.DeviceEventConstants.EXTRA_EVENT_TYPE;
     23 import static android.inputmethodservice.cts.common.DeviceEventConstants.RECEIVER_COMPONENT;
     24 
     25 import static org.junit.Assert.assertTrue;
     26 import static org.junit.Assume.assumeTrue;
     27 
     28 import android.inputmethodservice.cts.common.EditTextAppConstants;
     29 import android.inputmethodservice.cts.common.EventProviderConstants.EventTableConstants;
     30 import android.inputmethodservice.cts.common.Ime1Constants;
     31 import android.inputmethodservice.cts.common.Ime2Constants;
     32 import android.inputmethodservice.cts.common.test.DeviceTestConstants;
     33 import android.inputmethodservice.cts.common.test.ShellCommandUtils;
     34 import android.inputmethodservice.cts.common.test.TestInfo;
     35 import android.platform.test.annotations.AppModeFull;
     36 import android.platform.test.annotations.AppModeInstant;
     37 
     38 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
     39 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
     40 
     41 import org.junit.After;
     42 import org.junit.Before;
     43 import org.junit.Test;
     44 import org.junit.runner.RunWith;
     45 
     46 import java.util.concurrent.TimeUnit;
     47 import java.util.concurrent.TimeoutException;
     48 
     49 @RunWith(DeviceJUnit4ClassRunner.class)
     50 public class InputMethodServiceLifecycleTest extends BaseHostJUnit4Test {
     51 
     52     private static final long TIMEOUT = TimeUnit.MICROSECONDS.toMillis(20000);
     53     private static final long POLLING_INTERVAL = TimeUnit.MICROSECONDS.toMillis(200);
     54 
     55     @Before
     56     public void setUp() throws Exception {
     57         // Skip whole tests when DUT has no android.software.input_methods feature.
     58         assumeTrue(hasDeviceFeature(ShellCommandUtils.FEATURE_INPUT_METHODS));
     59         cleanUpTestImes();
     60         shell(ShellCommandUtils.deleteContent(EventTableConstants.CONTENT_URI));
     61     }
     62 
     63     @After
     64     public void tearDown() throws Exception {
     65         shell(ShellCommandUtils.resetImes());
     66     }
     67 
     68     private void installPossibleInstantPackage(String apkFileName, boolean instant)
     69             throws Exception {
     70         if (instant) {
     71             installPackage(apkFileName, "-r", "--instant");
     72         } else {
     73             installPackage(apkFileName, "-r");
     74         }
     75     }
     76 
     77     private void testSwitchIme(boolean instant) throws Exception {
     78         final TestInfo testSwitchIme1ToIme2 = new TestInfo(DeviceTestConstants.PACKAGE,
     79                 DeviceTestConstants.TEST_CLASS, DeviceTestConstants.TEST_SWITCH_IME1_TO_IME2);
     80         sendTestStartEvent(testSwitchIme1ToIme2);
     81         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
     82         installPackage(Ime1Constants.APK, "-r");
     83         installPackage(Ime2Constants.APK, "-r");
     84         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
     85         shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
     86         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
     87 
     88         assertTrue(runDeviceTestMethod(testSwitchIme1ToIme2));
     89     }
     90 
     91     @AppModeFull
     92     @Test
     93     public void testSwitchImeull() throws Exception {
     94         testSwitchIme(false);
     95     }
     96 
     97     @AppModeInstant
     98     @Test
     99     public void testSwitchImeInstant() throws Exception {
    100         testSwitchIme(true);
    101     }
    102 
    103     private void testUninstallCurrentIme(boolean instant) throws Exception {
    104         final TestInfo testCreateIme1 = new TestInfo(DeviceTestConstants.PACKAGE,
    105                 DeviceTestConstants.TEST_CLASS, DeviceTestConstants.TEST_CREATE_IME1);
    106         sendTestStartEvent(testCreateIme1);
    107         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    108         installPackage(Ime1Constants.APK, "-r");
    109         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    110         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    111         assertTrue(runDeviceTestMethod(testCreateIme1));
    112 
    113         uninstallPackageIfExists(Ime1Constants.PACKAGE);
    114         assertImeNotSelectedInSecureSettings(Ime1Constants.IME_ID, TIMEOUT);
    115     }
    116 
    117     @AppModeFull
    118     @Test
    119     public void testUninstallCurrentImeFull() throws Exception {
    120         testUninstallCurrentIme(false);
    121     }
    122 
    123     @AppModeInstant
    124     @Test
    125     public void testUninstallCurrentImeInstant() throws Exception {
    126         testUninstallCurrentIme(true);
    127     }
    128 
    129     private void testDisableCurrentIme(boolean instant) throws Exception {
    130         final TestInfo testCreateIme1 = new TestInfo(DeviceTestConstants.PACKAGE,
    131                 DeviceTestConstants.TEST_CLASS, DeviceTestConstants.TEST_CREATE_IME1);
    132         sendTestStartEvent(testCreateIme1);
    133         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    134         installPackage(Ime1Constants.APK, "-r");
    135         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    136         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    137         assertTrue(runDeviceTestMethod(testCreateIme1));
    138 
    139         shell(ShellCommandUtils.disableIme(Ime1Constants.IME_ID));
    140         assertImeNotSelectedInSecureSettings(Ime1Constants.IME_ID, TIMEOUT);
    141     }
    142 
    143     @AppModeFull
    144     @Test
    145     public void testDisableCurrentImeFull() throws Exception {
    146         testDisableCurrentIme(false);
    147     }
    148 
    149     @AppModeInstant
    150     @Test
    151     public void testDisableCurrentImeInstant() throws Exception {
    152         testDisableCurrentIme(true);
    153     }
    154 
    155     private void testSwitchInputMethod(boolean instant) throws Exception {
    156         final TestInfo testSetInputMethod = new TestInfo(
    157                 DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
    158                 DeviceTestConstants.TEST_SWITCH_INPUTMETHOD);
    159         sendTestStartEvent(testSetInputMethod);
    160         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    161         installPackage(Ime1Constants.APK, "-r");
    162         installPackage(Ime2Constants.APK, "-r");
    163         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    164         shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
    165         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    166 
    167         assertTrue(runDeviceTestMethod(testSetInputMethod));
    168     }
    169 
    170     @AppModeFull
    171     @Test
    172     public void testSwitchInputMethodFull() throws Exception {
    173         testSwitchInputMethod(false);
    174     }
    175 
    176     @AppModeInstant
    177     @Test
    178     public void testSwitchInputMethodInstant() throws Exception {
    179         testSwitchInputMethod(true);
    180     }
    181 
    182     private void testSwitchToNextInput(boolean instant) throws Exception {
    183         final TestInfo testSwitchInputs = new TestInfo(
    184                 DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
    185                 DeviceTestConstants.TEST_SWITCH_NEXT_INPUT);
    186         sendTestStartEvent(testSwitchInputs);
    187         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    188         installPackage(Ime1Constants.APK, "-r");
    189         installPackage(Ime2Constants.APK, "-r");
    190         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    191         // Make sure that there is at least one more IME that specifies
    192         // supportsSwitchingToNextInputMethod="true"
    193         shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
    194         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    195 
    196         assertTrue(runDeviceTestMethod(testSwitchInputs));
    197     }
    198 
    199     @AppModeFull
    200     @Test
    201     public void testSwitchToNextInputFull() throws Exception {
    202         testSwitchToNextInput(false);
    203     }
    204 
    205     @AppModeInstant
    206     @Test
    207     public void testSwitchToNextInputInstant() throws Exception {
    208         testSwitchToNextInput(true);
    209     }
    210 
    211     private void testSwitchToPreviousInput(boolean instant) throws Exception {
    212         final TestInfo testSwitchInputs = new TestInfo(
    213                 DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
    214                 DeviceTestConstants.TEST_SWITCH_PREVIOUS_INPUT);
    215         sendTestStartEvent(testSwitchInputs);
    216         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    217         installPackage(Ime1Constants.APK, "-r");
    218         installPackage(Ime2Constants.APK, "-r");
    219         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    220         shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
    221         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    222 
    223         assertTrue(runDeviceTestMethod(testSwitchInputs));
    224     }
    225 
    226     @AppModeFull
    227     @Test
    228     public void testSwitchToPreviousInputFull() throws Exception {
    229         testSwitchToPreviousInput(false);
    230     }
    231 
    232     @AppModeInstant
    233     @Test
    234     public void testSwitchToPreviousInputInstant() throws Exception {
    235         testSwitchToPreviousInput(true);
    236     }
    237 
    238     private void testInputUnbindsOnImeStopped(boolean instant) throws Exception {
    239         final TestInfo testUnbind = new TestInfo(
    240                 DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
    241                 DeviceTestConstants.TEST_INPUT_UNBINDS_ON_IME_STOPPED);
    242         sendTestStartEvent(testUnbind);
    243         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    244         installPackage(Ime1Constants.APK, "-r");
    245         installPackage(Ime2Constants.APK, "-r");
    246         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    247         shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
    248         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    249 
    250         assertTrue(runDeviceTestMethod(testUnbind));
    251     }
    252 
    253     @AppModeFull
    254     @Test
    255     public void testInputUnbindsOnImeStoppedFull() throws Exception {
    256         testInputUnbindsOnImeStopped(false);
    257     }
    258 
    259     @AppModeInstant
    260     @Test
    261     public void testInputUnbindsOnImeStoppedInstant() throws Exception {
    262         testInputUnbindsOnImeStopped(true);
    263     }
    264 
    265     private void testInputUnbindsOnAppStop(boolean instant) throws Exception {
    266         final TestInfo testUnbind = new TestInfo(
    267                 DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
    268                 DeviceTestConstants.TEST_INPUT_UNBINDS_ON_APP_STOPPED);
    269         sendTestStartEvent(testUnbind);
    270         installPossibleInstantPackage(EditTextAppConstants.APK, instant);
    271         installPackage(Ime1Constants.APK, "-r");
    272         shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
    273         shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
    274 
    275         assertTrue(runDeviceTestMethod(testUnbind));
    276     }
    277 
    278     @AppModeFull
    279     @Test
    280     public void testInputUnbindsOnAppStopFull() throws Exception {
    281         testInputUnbindsOnAppStop(false);
    282     }
    283 
    284     @AppModeInstant
    285     @Test
    286     public void testInputUnbindsOnAppStopInstant() throws Exception {
    287         testInputUnbindsOnAppStop(true);
    288     }
    289 
    290     private void sendTestStartEvent(final TestInfo deviceTest) throws Exception {
    291         final String sender = deviceTest.getTestName();
    292         // {@link EventType#EXTRA_EVENT_TIME} will be recorded at device side.
    293         shell(ShellCommandUtils.broadcastIntent(
    294                 ACTION_DEVICE_EVENT, RECEIVER_COMPONENT,
    295                 "--es", EXTRA_EVENT_SENDER, sender,
    296                 "--es", EXTRA_EVENT_TYPE, TEST_START.name()));
    297     }
    298 
    299     private boolean runDeviceTestMethod(final TestInfo deviceTest) throws Exception {
    300         return runDeviceTests(deviceTest.testPackage, deviceTest.testClass, deviceTest.testMethod);
    301     }
    302 
    303     private String shell(final String command) throws Exception {
    304         return getDevice().executeShellCommand(command).trim();
    305     }
    306 
    307     private void cleanUpTestImes() throws Exception {
    308         uninstallPackageIfExists(Ime1Constants.PACKAGE);
    309         uninstallPackageIfExists(Ime2Constants.PACKAGE);
    310     }
    311 
    312     private void uninstallPackageIfExists(final String packageName) throws Exception {
    313         if (isPackageInstalled(getDevice(), packageName)) {
    314             uninstallPackage(getDevice(), packageName);
    315         }
    316     }
    317 
    318     /**
    319      * Makes sure that the given IME is not in the stored in the secure settings as the current IME.
    320      *
    321      * @param imeId IME ID to be monitored
    322      * @param timeout timeout in millisecond
    323      */
    324     private void assertImeNotSelectedInSecureSettings(String imeId, long timeout) throws Exception {
    325         while (true) {
    326             if (timeout < 0) {
    327                 throw new TimeoutException(imeId + " is still the current IME even after "
    328                         + timeout + " msec.");
    329             }
    330             if (!imeId.equals(shell(ShellCommandUtils.getCurrentIme()))) {
    331                 break;
    332             }
    333             Thread.sleep(POLLING_INTERVAL);
    334             timeout -= POLLING_INTERVAL;
    335         }
    336     }
    337 }
    338