1 /*
2  * Copyright (C) 2023 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 com.android.inputmethod.stresstest;
18 
19 import android.app.Instrumentation;
20 import android.os.RemoteException;
21 import android.support.test.uiautomator.UiDevice;
22 
23 import androidx.annotation.NonNull;
24 import androidx.test.platform.app.InstrumentationRegistry;
25 
26 import org.junit.rules.TestWatcher;
27 import org.junit.runner.Description;
28 
29 import java.io.IOException;
30 
31 /**
32  * Do setup and cleanup for Ime stress tests, including disabling lock and auto-rotate screen,
33  * pressing home and enabling a simple test Ime during the tests.
34  */
35 public class ImeStressTestRule extends TestWatcher {
36     private static final String LOCK_SCREEN_OFF_COMMAND = "locksettings set-disabled true";
37     private static final String LOCK_SCREEN_ON_COMMAND = "locksettings set-disabled false";
38     private static final String SIMPLE_IME_ID =
39             "com.android.apps.inputmethod.simpleime/.SimpleInputMethodService";
40     private static final String ENABLE_IME_COMMAND = "ime enable " + SIMPLE_IME_ID;
41     private static final String SET_IME_COMMAND = "ime set " + SIMPLE_IME_ID;
42     private static final String DISABLE_IME_COMMAND = "ime disable " + SIMPLE_IME_ID;
43     private static final String RESET_IME_COMMAND = "ime reset";
44 
45     @NonNull
46     private final Instrumentation mInstrumentation;
47     @NonNull
48     private final UiDevice mUiDevice;
49     // Whether the screen orientation is set to portrait.
50     private boolean mIsPortrait;
51     // Whether to use a simple test Ime or system default Ime for test.
52     private final boolean mUseSimpleTestIme;
53 
ImeStressTestRule(boolean useSimpleTestIme)54     public ImeStressTestRule(boolean useSimpleTestIme) {
55         mInstrumentation = InstrumentationRegistry.getInstrumentation();
56         mUiDevice = UiDevice.getInstance(mInstrumentation);
57         // Default is portrait mode
58         mIsPortrait = true;
59         mUseSimpleTestIme = useSimpleTestIme;
60     }
61 
setIsPortrait(boolean isPortrait)62     public void setIsPortrait(boolean isPortrait) {
63         mIsPortrait = isPortrait;
64     }
65 
66     @Override
starting(Description description)67     protected void starting(Description description) {
68         disableLockScreen();
69         setOrientation();
70         mUiDevice.pressHome();
71         if (mUseSimpleTestIme) {
72             enableSimpleIme();
73         } else {
74             resetImeToDefault();
75         }
76 
77         mInstrumentation.waitForIdleSync();
78     }
79 
80     @Override
finished(Description description)81     protected void finished(Description description) {
82         if (mUseSimpleTestIme) {
83             disableSimpleIme();
84         }
85         unfreezeRotation();
86         restoreLockScreen();
87     }
88 
disableLockScreen()89     private void disableLockScreen() {
90         try {
91             executeShellCommand(LOCK_SCREEN_OFF_COMMAND);
92         } catch (IOException e) {
93             throw new RuntimeException("Could not disable lock screen.", e);
94         }
95     }
96 
restoreLockScreen()97     private void restoreLockScreen() {
98         try {
99             executeShellCommand(LOCK_SCREEN_ON_COMMAND);
100         } catch (IOException e) {
101             throw new RuntimeException("Could not enable lock screen.", e);
102         }
103     }
104 
setOrientation()105     private void setOrientation() {
106         try {
107             mUiDevice.freezeRotation();
108             if (mIsPortrait) {
109                 mUiDevice.setOrientationNatural();
110             } else {
111                 mUiDevice.setOrientationLeft();
112             }
113         } catch (RemoteException e) {
114             throw new RuntimeException("Could not freeze rotation or set screen orientation.", e);
115         }
116     }
117 
unfreezeRotation()118     private void unfreezeRotation() {
119         try {
120             mUiDevice.unfreezeRotation();
121         } catch (RemoteException e) {
122             throw new RuntimeException("Could not unfreeze screen rotation.", e);
123         }
124     }
125 
enableSimpleIme()126     private void enableSimpleIme() {
127         try {
128             executeShellCommand(ENABLE_IME_COMMAND);
129             executeShellCommand(SET_IME_COMMAND);
130         } catch (IOException e) {
131             throw new RuntimeException("Could not enable SimpleTestIme.", e);
132         }
133     }
134 
disableSimpleIme()135     private void disableSimpleIme() {
136         try {
137             executeShellCommand(DISABLE_IME_COMMAND);
138         } catch (IOException e) {
139             throw new RuntimeException("Could not disable SimpleTestIme.", e);
140         }
141     }
142 
resetImeToDefault()143     private void resetImeToDefault() {
144         try {
145             executeShellCommand(RESET_IME_COMMAND);
146         } catch (IOException e) {
147             throw new RuntimeException("Could not reset Ime to default.", e);
148         }
149     }
150 
151     @NonNull
executeShellCommand(@onNull String cmd)152     private String executeShellCommand(@NonNull String cmd) throws IOException {
153         return mUiDevice.executeShellCommand(cmd);
154     }
155 }
156