• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 package android.view.contentcapture;
17 
18 import static android.view.contentcapture.CustomTestActivity.INTENT_EXTRA_CUSTOM_VIEWS;
19 import static android.view.contentcapture.CustomTestActivity.INTENT_EXTRA_LAYOUT_ID;
20 
21 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
22 
23 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
24 
25 import android.app.Activity;
26 import android.app.Application;
27 import android.app.Instrumentation;
28 import android.content.ContentCaptureOptions;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.os.BatteryManager;
32 import android.os.UserHandle;
33 import android.perftests.utils.PerfStatusReporter;
34 import android.perftests.utils.PerfTestActivity;
35 import android.provider.Settings;
36 import android.util.Log;
37 
38 import androidx.annotation.NonNull;
39 
40 import com.android.compatibility.common.util.ActivitiesWatcher;
41 import com.android.compatibility.common.util.ActivitiesWatcher.ActivityWatcher;
42 import com.android.perftests.contentcapture.R;
43 
44 import org.junit.After;
45 import org.junit.AfterClass;
46 import org.junit.Before;
47 import org.junit.BeforeClass;
48 import org.junit.Rule;
49 import org.junit.rules.TestRule;
50 import org.junit.runners.model.Statement;
51 
52 /**
53  * Base class for all content capture tests.
54  */
55 public abstract class AbstractContentCapturePerfTestCase {
56 
57     private static final String TAG = AbstractContentCapturePerfTestCase.class.getSimpleName();
58     protected static final long GENERIC_TIMEOUT_MS = 5_000;
59 
60     private static int sOriginalStayOnWhilePluggedIn;
61     protected static final Instrumentation sInstrumentation = getInstrumentation();
62     protected static final Context sContext = sInstrumentation.getTargetContext();
63 
64     protected ActivitiesWatcher mActivitiesWatcher;
65 
66     /** A simple activity as the task root to reduce the noise of pause and animation time. */
67     protected Activity mEntryActivity;
68 
69     private MyContentCaptureService.ServiceWatcher mServiceWatcher;
70 
71     @Rule
72     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
73 
74     @Rule
75     public TestRule mServiceDisablerRule = (base, description) -> {
76         return new Statement() {
77             @Override
78             public void evaluate() throws Throwable {
79                 try {
80                     base.evaluate();
81                 } finally {
82                     Log.v(TAG, "@mServiceDisablerRule: safelyDisableService()");
83                     safelyDisableService();
84                 }
85             }
86         };
87     };
88 
safelyDisableService()89     private void safelyDisableService() {
90         try {
91             resetService();
92             MyContentCaptureService.resetStaticState();
93 
94             if (mServiceWatcher != null) {
95                 mServiceWatcher.waitOnDestroy();
96             }
97         } catch (Throwable t) {
98             Log.e(TAG, "error disabling service", t);
99         }
100     }
101 
102     /**
103      * Sets the content capture service.
104      */
setService(@onNull String service)105     private static void setService(@NonNull String service) {
106         final int userId = getCurrentUserId();
107         Log.d(TAG, "Setting service for user " + userId + " to " + service);
108         // TODO(b/123540602): use @TestingAPI to get max duration constant
109         runShellCommand("cmd content_capture set temporary-service %d %s 119000", userId, service);
110     }
111 
112     /**
113      * Resets the content capture service.
114      */
resetService()115     private static void resetService() {
116         final int userId = getCurrentUserId();
117         Log.d(TAG, "Resetting back user " + userId + " to default service");
118         runShellCommand("cmd content_capture set temporary-service %d", userId);
119     }
120 
getCurrentUserId()121     private static int getCurrentUserId() {
122         return UserHandle.myUserId();
123     }
124 
125     @BeforeClass
setStayAwake()126     public static void setStayAwake() {
127         Log.v(TAG, "@BeforeClass: setStayAwake()");
128         // Some test cases will restart the activity, and stay awake is necessary to ensure that
129         // the test will not screen off during the test.
130         // Keeping the activity screen on is not enough, screen off may occur between the activity
131         // finished and the next start
132         final int stayOnWhilePluggedIn = Settings.Global.getInt(sContext.getContentResolver(),
133                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
134         sOriginalStayOnWhilePluggedIn = -1;
135         if (stayOnWhilePluggedIn != BatteryManager.BATTERY_PLUGGED_ANY) {
136             sOriginalStayOnWhilePluggedIn = stayOnWhilePluggedIn;
137             // Keep the device awake during testing.
138             setStayOnWhilePluggedIn(BatteryManager.BATTERY_PLUGGED_ANY);
139         }
140     }
141 
142     @AfterClass
resetStayAwake()143     public static void resetStayAwake() {
144         Log.v(TAG, "@AfterClass: resetStayAwake()");
145         if (sOriginalStayOnWhilePluggedIn != -1) {
146             setStayOnWhilePluggedIn(sOriginalStayOnWhilePluggedIn);
147         }
148     }
149 
setStayOnWhilePluggedIn(int value)150     private static void setStayOnWhilePluggedIn(int value) {
151         runShellCommand(String.format("settings put global %s %d",
152                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value));
153     }
154 
155     @BeforeClass
setAllowSelf()156     public static void setAllowSelf() {
157         final ContentCaptureOptions options = new ContentCaptureOptions(null);
158         Log.v(TAG, "@BeforeClass: setAllowSelf(): options=" + options);
159         sContext.getApplicationContext().setContentCaptureOptions(options);
160     }
161 
162     @AfterClass
unsetAllowSelf()163     public static void unsetAllowSelf() {
164         Log.v(TAG, "@AfterClass: unsetAllowSelf()");
165         clearOptions();
166     }
167 
clearOptions()168     protected static void clearOptions() {
169         sContext.getApplicationContext().setContentCaptureOptions(null);
170     }
171 
172     @BeforeClass
disableDefaultService()173     public static void disableDefaultService() {
174         Log.v(TAG, "@BeforeClass: disableDefaultService()");
175         setDefaultServiceEnabled(false);
176     }
177 
178     @AfterClass
enableDefaultService()179     public static void enableDefaultService() {
180         Log.v(TAG, "@AfterClass: enableDefaultService()");
181         setDefaultServiceEnabled(true);
182     }
183 
184     /**
185      * Enables / disables the default service.
186      */
setDefaultServiceEnabled(boolean enabled)187     private static void setDefaultServiceEnabled(boolean enabled) {
188         final int userId = getCurrentUserId();
189         Log.d(TAG, "setDefaultServiceEnabled(user=" + userId + ", enabled= " + enabled + ")");
190         runShellCommand("cmd content_capture set default-service-enabled %d %s", userId,
191                 Boolean.toString(enabled));
192     }
193 
194     @Before
prepareDevice()195     public void prepareDevice() throws Exception {
196         Log.v(TAG, "@Before: prepareDevice()");
197 
198         // Unlock screen.
199         runShellCommand("input keyevent KEYCODE_WAKEUP");
200 
201         // Dismiss keyguard, in case it's set as "Swipe to unlock".
202         runShellCommand("wm dismiss-keyguard");
203 
204         // Collapse notifications.
205         runShellCommand("cmd statusbar collapse");
206     }
207 
208     @Before
registerLifecycleCallback()209     public void registerLifecycleCallback() {
210         Log.v(TAG, "@Before: Registering lifecycle callback");
211         final Application app = (Application) sContext.getApplicationContext();
212         mActivitiesWatcher = new ActivitiesWatcher(GENERIC_TIMEOUT_MS);
213         app.registerActivityLifecycleCallbacks(mActivitiesWatcher);
214     }
215 
216     @After
unregisterLifecycleCallback()217     public void unregisterLifecycleCallback() {
218         Log.d(TAG, "@After: Unregistering lifecycle callback: " + mActivitiesWatcher);
219         if (mActivitiesWatcher != null) {
220             final Application app = (Application) sContext.getApplicationContext();
221             app.unregisterActivityLifecycleCallbacks(mActivitiesWatcher);
222         }
223     }
224 
225     @Before
setUp()226     public void setUp() {
227         mEntryActivity = sInstrumentation.startActivitySync(
228                 PerfTestActivity.createLaunchIntent(sInstrumentation.getContext()));
229     }
230 
231     @After
tearDown()232     public void tearDown() {
233         mEntryActivity.finishAndRemoveTask();
234     }
235 
236     /**
237      * Sets {@link MyContentCaptureService} as the service for the current user and waits until
238      * its created, then add the perf test package into allow list.
239      */
enableService()240     public MyContentCaptureService enableService() throws InterruptedException {
241         if (mServiceWatcher != null) {
242             throw new IllegalStateException("There Can Be Only One!");
243         }
244 
245         mServiceWatcher = MyContentCaptureService.setServiceWatcher();
246         setService(MyContentCaptureService.SERVICE_NAME);
247         mServiceWatcher.setAllowSelf();
248         return mServiceWatcher.waitOnCreate();
249     }
250 
251     /** Wait for session paused. */
waitForSessionPaused()252     public void waitForSessionPaused() throws InterruptedException {
253         mServiceWatcher.waitSessionPaused();
254     }
255 
256     @NonNull
startWatcher()257     protected ActivityWatcher startWatcher() {
258         return mActivitiesWatcher.watch(CustomTestActivity.class);
259     }
260 
261     /**
262      * Launch test activity with default login layout
263      */
launchActivity()264     protected CustomTestActivity launchActivity() {
265         return launchActivity(R.layout.test_login_activity, 0);
266     }
267 
268     /**
269      * Returns the intent which will launch CustomTestActivity.
270      */
getLaunchIntent(int layoutId, int numViews)271     protected Intent getLaunchIntent(int layoutId, int numViews) {
272         final Intent intent = new Intent(sContext, CustomTestActivity.class)
273                 // Use NEW_TASK because the context is not activity. It is still in the same task
274                 // of PerfTestActivity because of the same task affinity. Use NO_ANIMATION because
275                 // this test focuses on launch time instead of animation duration.
276                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
277         intent.putExtra(INTENT_EXTRA_LAYOUT_ID, layoutId);
278         intent.putExtra(INTENT_EXTRA_CUSTOM_VIEWS, numViews);
279         return intent;
280     }
281 
282     /**
283      * Launch test activity with give layout and parameter
284      */
launchActivity(int layoutId, int numViews)285     protected CustomTestActivity launchActivity(int layoutId, int numViews) {
286         final Intent intent = getLaunchIntent(layoutId, numViews);
287         return (CustomTestActivity) sInstrumentation.startActivitySync(intent);
288     }
289 }
290