1 /*
2  * Copyright (C) 2016 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.multiuser;
17 
18 import static android.app.WallpaperManager.FLAG_LOCK;
19 import static android.app.WallpaperManager.FLAG_SYSTEM;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assume.assumeTrue;
24 
25 import android.annotation.NonNull;
26 import android.app.ActivityManager;
27 import android.app.AppGlobals;
28 import android.app.IActivityManager;
29 import android.app.IStopUserCallback;
30 import android.app.WallpaperManager;
31 import android.content.BroadcastReceiver;
32 import android.content.Context;
33 import android.content.IIntentReceiver;
34 import android.content.IIntentSender;
35 import android.content.Intent;
36 import android.content.IntentSender;
37 import android.content.pm.IPackageInstaller;
38 import android.content.pm.PackageManager;
39 import android.content.pm.UserInfo;
40 import android.graphics.Bitmap;
41 import android.os.Bundle;
42 import android.os.IBinder;
43 import android.os.IProgressListener;
44 import android.os.RemoteException;
45 import android.os.SystemClock;
46 import android.os.SystemProperties;
47 import android.os.UserHandle;
48 import android.os.UserManager;
49 import android.perftests.utils.ShellHelper;
50 import android.text.TextUtils;
51 import android.util.Log;
52 import android.view.WindowManagerGlobal;
53 
54 import androidx.test.InstrumentationRegistry;
55 import androidx.test.filters.LargeTest;
56 import androidx.test.runner.AndroidJUnit4;
57 
58 import com.android.internal.util.FunctionalUtils;
59 
60 import org.junit.After;
61 import org.junit.Before;
62 import org.junit.Rule;
63 import org.junit.Test;
64 import org.junit.runner.RunWith;
65 
66 import java.io.IOException;
67 import java.util.ArrayList;
68 import java.util.concurrent.CountDownLatch;
69 import java.util.concurrent.TimeUnit;
70 import java.util.concurrent.TimeoutException;
71 
72 /**
73  * Perf tests for user life cycle events.
74  *
75  * To run the tests: atest UserLifecycleTests
76  *
77  *
78  * Old methods for running the tests:
79  *
80  * make MultiUserPerfTests &&
81  * adb install -r \
82  *     ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk &&
83  * adb shell am instrument -e class android.multiuser.UserLifecycleTests \
84  *     -w com.android.perftests.multiuser/androidx.test.runner.AndroidJUnitRunner
85  *
86  * or
87  *
88  * bit MultiUserPerfTests:android.multiuser.UserLifecycleTests
89  *
90  * Note: If you use bit for running the tests, benchmark results won't be printed on the host side.
91  * But in either case, results can be checked on the device side 'adb logcat -s UserLifecycleTests'
92  */
93 @LargeTest
94 @RunWith(AndroidJUnit4.class)
95 public class UserLifecycleTests {
96     private static final String TAG = UserLifecycleTests.class.getSimpleName();
97 
98     /** Max runtime for each test (including all runs within that test). */
99     // Must be less than the AndroidTest.xml test-timeout to avoid being considered non-responsive.
100     private static final long TIMEOUT_MAX_TEST_TIME_MS = 24 * 60_000;
101 
102     private static final int TIMEOUT_IN_SECOND = 30;
103 
104     /** Name of users/profiles in the test. Users with this name may be freely removed. */
105     private static final String TEST_USER_NAME = "UserLifecycleTests_test_user";
106 
107     /** Name of dummy package used when timing how long app launches take. */
108     private static final String DUMMY_PACKAGE_NAME = "perftests.multiuser.apps.dummyapp";
109 
110     // Copy of UserSystemPackageInstaller whitelist mode constants.
111     private static final String PACKAGE_WHITELIST_MODE_PROP =
112             "persist.debug.user.package_whitelist_mode";
113     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0;
114     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0b001;
115     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0b100;
116     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1;
117 
118     private UserManager mUm;
119     private ActivityManager mAm;
120     private IActivityManager mIam;
121     private PackageManager mPm;
122     private WallpaperManager mWm;
123     private ArrayList<Integer> mUsersToRemove;
124     private boolean mHasManagedUserFeature;
125     private BroadcastWaiter mBroadcastWaiter;
126     private UserSwitchWaiter mUserSwitchWaiter;
127     private String mUserSwitchTimeoutMs;
128     private String mDisableUserSwitchingDialogAnimations;
129 
130     private final BenchmarkRunner mRunner = new BenchmarkRunner();
131     @Rule
132     public BenchmarkResultsReporter mReporter = new BenchmarkResultsReporter(mRunner);
133 
134     @Before
setUp()135     public void setUp() throws Exception {
136         final Context context = InstrumentationRegistry.getContext();
137         mUm = UserManager.get(context);
138         mAm = context.getSystemService(ActivityManager.class);
139         mIam = ActivityManager.getService();
140         mUsersToRemove = new ArrayList<>();
141         mPm = context.getPackageManager();
142         mWm = WallpaperManager.getInstance(context);
143         mHasManagedUserFeature = mPm.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
144         mBroadcastWaiter = new BroadcastWaiter(context, TAG, TIMEOUT_IN_SECOND,
145                 Intent.ACTION_USER_STARTED,
146                 Intent.ACTION_MEDIA_MOUNTED,
147                 Intent.ACTION_USER_UNLOCKED,
148                 Intent.ACTION_USER_STOPPED);
149         mUserSwitchWaiter = new UserSwitchWaiter(TAG, TIMEOUT_IN_SECOND);
150         removeAnyPreviousTestUsers();
151         if (mAm.getCurrentUser() != UserHandle.USER_SYSTEM) {
152             Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser()
153                     + " rather than the system user");
154         }
155         mUserSwitchTimeoutMs = setSystemProperty(
156                 "debug.usercontroller.user_switch_timeout_ms", "100000");
157         mDisableUserSwitchingDialogAnimations = setSystemProperty(
158                 "debug.usercontroller.disable_user_switching_dialog_animations", "true");
159     }
160 
161     @After
tearDown()162     public void tearDown() throws Exception {
163         setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs);
164         setSystemProperty("debug.usercontroller.disable_user_switching_dialog_animations",
165                 mDisableUserSwitchingDialogAnimations);
166         mBroadcastWaiter.close();
167         mUserSwitchWaiter.close();
168         for (int userId : mUsersToRemove) {
169             try {
170                 mUm.removeUser(userId);
171             } catch (Exception e) {
172                 // Ignore
173             }
174         }
175     }
176 
177     /** Tests creating a new user. */
178     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
createUser()179     public void createUser() throws RemoteException {
180         while (mRunner.keepRunning()) {
181             Log.i(TAG, "Starting timer");
182             final int userId = createUserNoFlags();
183 
184             mRunner.pauseTiming();
185             Log.i(TAG, "Stopping timer");
186             removeUser(userId);
187             mRunner.resumeTimingForNextIteration();
188         }
189     }
190 
191     /** Tests creating a new user, with wait times between iterations. */
192     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
createUser_realistic()193     public void createUser_realistic() throws RemoteException {
194         while (mRunner.keepRunning()) {
195             Log.i(TAG, "Starting timer");
196             final int userId = createUserNoFlags();
197 
198             mRunner.pauseTiming();
199             Log.i(TAG, "Stopping timer");
200             removeUser(userId);
201             waitCoolDownPeriod();
202             mRunner.resumeTimingForNextIteration();
203         }
204     }
205 
206     /** Tests creating and starting a new user. */
207     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
createAndStartUser()208     public void createAndStartUser() throws RemoteException {
209         while (mRunner.keepRunning()) {
210             Log.i(TAG, "Starting timer");
211             final int userId = createUserNoFlags();
212 
213             // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until
214             // ACTION_USER_STARTED.
215             runThenWaitForBroadcasts(userId, () -> {
216                 mIam.startUserInBackground(userId);
217             }, Intent.ACTION_USER_STARTED);
218 
219             mRunner.pauseTiming();
220             Log.i(TAG, "Stopping timer");
221             removeUser(userId);
222             mRunner.resumeTimingForNextIteration();
223         }
224     }
225 
226     /** Tests creating and starting a new user. */
227     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
createAndStartUser_realistic()228     public void createAndStartUser_realistic() throws RemoteException {
229         while (mRunner.keepRunning()) {
230             Log.d(TAG, "Starting timer");
231             final int userId = createUserNoFlags();
232 
233             // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until
234             // ACTION_USER_STARTED.
235             runThenWaitForBroadcasts(userId, () -> {
236                 mIam.startUserInBackground(userId);
237             }, Intent.ACTION_USER_STARTED);
238 
239             mRunner.pauseTiming();
240             Log.d(TAG, "Stopping timer");
241             removeUser(userId);
242             waitCoolDownPeriod();
243             mRunner.resumeTimingForNextIteration();
244         }
245     }
246 
247     /**
248      * Tests starting an uninitialized user.
249      * Measures the time until ACTION_USER_STARTED is received.
250      */
251     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startUser()252     public void startUser() throws RemoteException {
253         while (mRunner.keepRunning()) {
254             mRunner.pauseTiming();
255             final int userId = createUserNoFlags();
256 
257             waitForBroadcastIdle();
258             runThenWaitForBroadcasts(userId, () -> {
259                 mRunner.resumeTiming();
260                 Log.i(TAG, "Starting timer");
261 
262                 mIam.startUserInBackground(userId);
263             }, Intent.ACTION_USER_STARTED);
264 
265             mRunner.pauseTiming();
266             Log.i(TAG, "Stopping timer");
267             removeUser(userId);
268             mRunner.resumeTimingForNextIteration();
269         }
270     }
271 
272     /**
273      * Tests starting an uninitialized user, with wait times in between iterations.
274      *
275      * The first iteration will take longer due to the process of setting policy permissions for
276      * a new user.
277      */
278     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startUser_uninitializedUser()279     public void startUser_uninitializedUser() throws RemoteException {
280         startUser_measuresAfterFirstIterations(/* numberOfIterationsToSkip */0);
281     }
282 
283     /**
284      * Tests the second iteration of start user that has a problem that it takes too long to run, a
285      * bug has been created (b/266574680) and after investigating or fix this problem,
286      * this test can be removed.
287      */
288     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startUser_startedOnceBefore()289     public void startUser_startedOnceBefore() throws RemoteException {
290         startUser_measuresAfterFirstIterations(/* numberOfIterationsToSkip */1);
291     }
292 
293     /**
294      * Tests a specific iteration of the start user process.
295      * Measures the time until ACTION_USER_STARTED is received.
296      * @param numberOfIterationsToSkip number of iterations that must be skipped in the preStartUser
297      *                                 method.
298      */
startUser_measuresAfterFirstIterations(int numberOfIterationsToSkip)299     private void startUser_measuresAfterFirstIterations(int numberOfIterationsToSkip)
300             throws RemoteException {
301         /**
302          * Run start user and stop for the next iteration, measures time while mRunner.keepRunning()
303          * return true.
304          */
305         while (mRunner.keepRunning()) {
306             mRunner.pauseTiming();
307 
308             final int userId = createUserNoFlags();
309 
310             preStartUser(userId, numberOfIterationsToSkip);
311 
312             waitForBroadcastIdle();
313             waitCoolDownPeriod();
314 
315             runThenWaitForBroadcasts(userId, () -> {
316                 mRunner.resumeTiming();
317                 Log.i(TAG, "Starting timer");
318 
319                 mIam.startUserInBackground(userId);
320             }, Intent.ACTION_USER_STARTED);
321 
322             mRunner.pauseTiming();
323             Log.i(TAG, "Stopping timer");
324 
325             removeUser(userId);
326             mRunner.resumeTimingForNextIteration();
327         }
328     }
329 
330     /**
331      * Tests starting an initialized user, with wait times in between iterations stopping between
332      * iterations,this test will skip the first two iterations and only measure the next ones.
333      *
334      * The first iteration will take longer due to the process of setting policy permissions for
335      * a new user.
336      *
337      * The second iteration takes longer than expected and has a bug (b/266574680) to investigate
338      * it.
339      *
340      * The next iterations take the expected time to start a user.
341      */
342     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startUser_startedTwiceBefore()343     public void startUser_startedTwiceBefore() throws RemoteException {
344         final int userId = createUserNoFlags();
345 
346         //TODO(b/266681181) Reduce iteration number by 1 after investigation and possible fix.
347         preStartUser(userId, /* numberOfIterations */2);
348 
349         /**
350          * Run start user and stop for the next iteration, measures time while mRunner.keepRunning()
351          * return true.
352          */
353         while (mRunner.keepRunning()) {
354             mRunner.pauseTiming();
355 
356             waitForBroadcastIdle();
357             waitCoolDownPeriod();
358 
359             runThenWaitForBroadcasts(userId, () -> {
360                 mRunner.resumeTiming();
361                 Log.i(TAG, "Starting timer");
362 
363                 mIam.startUserInBackground(userId);
364             }, Intent.ACTION_USER_STARTED);
365 
366             mRunner.pauseTiming();
367             Log.i(TAG, "Stopping timer");
368 
369             stopUser(userId, /* force */true);
370             mRunner.resumeTimingForNextIteration();
371         }
372 
373         removeUser(userId);
374     }
375 
376 
377     /**
378      * Tests starting & unlocking an uninitialized user.
379      * Measures the time until unlock listener is triggered and user is unlocked.
380      */
381     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startAndUnlockUser()382     public void startAndUnlockUser() throws RemoteException {
383         while (mRunner.keepRunning()) {
384             mRunner.pauseTiming();
385             final int userId = createUserNoFlags();
386             mRunner.resumeTiming();
387             Log.i(TAG, "Starting timer");
388 
389             // Waits for UserState.mUnlockProgress.finish().
390             startUserInBackgroundAndWaitForUnlock(userId);
391 
392             mRunner.pauseTiming();
393             Log.i(TAG, "Stopping timer");
394             removeUser(userId);
395             mRunner.resumeTimingForNextIteration();
396         }
397     }
398 
399     /**
400      * Tests starting & unlocking an initialized user, stopping the user at the end simulating real
401      * usage where the user is not removed after created and initialized.
402      * Measures the time until unlock listener is triggered and user is unlocked.
403      * This test will skip the first two iterations and only measure the next ones.
404      *
405      * The first iteration will take longer due to the process of setting policy permissions for a
406      * new user.
407      *
408      * The second iteration takes longer than expected and has a bug (b/266574680) to investigate
409      * it.
410      *
411      * The next iterations take the expected time to start a user.
412      */
413     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startAndUnlockUser_startedTwiceBefore()414     public void startAndUnlockUser_startedTwiceBefore() throws RemoteException {
415         final int userId = createUserNoFlags();
416 
417         //TODO(b/266681181) Reduce iteration number by 1 after investigation and possible fix.
418         preStartUser(userId, /* numberOfIterations */2);
419 
420         while (mRunner.keepRunning()) {
421             mRunner.pauseTiming();
422 
423             waitCoolDownPeriod();
424             mRunner.resumeTiming();
425             Log.i(TAG, "Starting timer");
426 
427             // Waits for UserState.mUnlockProgress.finish().
428             startUserInBackgroundAndWaitForUnlock(userId);
429 
430             mRunner.pauseTiming();
431             Log.i(TAG, "Stopping timer");
432             stopUser(userId, /* force */true);
433             mRunner.resumeTimingForNextIteration();
434         }
435 
436         removeUser(userId);
437     }
438 
439     /**
440      * Tests starting & unlocking an uninitialized user.
441      * Measures the time until unlock listener is triggered and user is unlocked.
442      */
443     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startAndUnlockUser_realistic()444     public void startAndUnlockUser_realistic() throws RemoteException {
445         while (mRunner.keepRunning()) {
446             mRunner.pauseTiming();
447             final int userId = createUserNoFlags();
448             mRunner.resumeTiming();
449             Log.d(TAG, "Starting timer");
450 
451             // Waits for UserState.mUnlockProgress.finish().
452             startUserInBackgroundAndWaitForUnlock(userId);
453 
454             mRunner.pauseTiming();
455             Log.d(TAG, "Stopping timer");
456             removeUser(userId);
457             waitCoolDownPeriod();
458             mRunner.resumeTimingForNextIteration();
459         }
460     }
461 
462     /** Tests switching to an uninitialized user. */
463     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser()464     public void switchUser() throws Exception {
465         while (mRunner.keepRunning()) {
466             mRunner.pauseTiming();
467             final int startUser = mAm.getCurrentUser();
468             final int userId = createUserNoFlags();
469             mRunner.resumeTiming();
470             Log.i(TAG, "Starting timer");
471 
472             switchUser(userId);
473 
474             mRunner.pauseTiming();
475             Log.i(TAG, "Stopping timer");
476             switchUserNoCheck(startUser);
477             removeUser(userId);
478             mRunner.resumeTimingForNextIteration();
479         }
480     }
481 
482     /** Tests switching to an uninitialized user with wait times between iterations. */
483     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_realistic()484     public void switchUser_realistic() throws Exception {
485         while (mRunner.keepRunning()) {
486             mRunner.pauseTiming();
487             final int startUser = ActivityManager.getCurrentUser();
488             final int userId = createUserNoFlags();
489             waitCoolDownPeriod();
490             Log.d(TAG, "Starting timer");
491             mRunner.resumeTiming();
492 
493             switchUser(userId);
494 
495             mRunner.pauseTiming();
496             Log.d(TAG, "Stopping timer");
497             switchUserNoCheck(startUser);
498             removeUser(userId);
499             mRunner.resumeTimingForNextIteration();
500         }
501     }
502 
503     /** Tests switching to a previously-started, but no-longer-running, user. */
504     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_stopped()505     public void switchUser_stopped() throws RemoteException {
506         while (mRunner.keepRunning()) {
507             mRunner.pauseTiming();
508             final int startUser = mAm.getCurrentUser();
509             final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
510             mRunner.resumeTiming();
511             Log.i(TAG, "Starting timer");
512 
513             switchUser(testUser);
514 
515             mRunner.pauseTiming();
516             Log.i(TAG, "Stopping timer");
517             switchUserNoCheck(startUser);
518             removeUser(testUser);
519             mRunner.resumeTimingForNextIteration();
520         }
521     }
522 
523     /**
524      * Tests switching to a previously-started, but no-longer-running, user with wait
525      * times between iterations
526      **/
527     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_stopped_realistic()528     public void switchUser_stopped_realistic() throws RemoteException {
529         final int currentUserId = ActivityManager.getCurrentUser();
530         final int userId = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
531 
532         /**
533          * Skip the second iteration of start user process that is taking a long time to finish.
534          */
535         preStartUser(userId, /* numberOfIterations */1);
536 
537         while (mRunner.keepRunning()) {
538             mRunner.pauseTiming();
539             waitCoolDownPeriod();
540             Log.d(TAG, "Starting timer");
541             mRunner.resumeTiming();
542 
543             switchUser(userId);
544 
545             mRunner.pauseTiming();
546             Log.d(TAG, "Stopping timer");
547             switchUserNoCheck(currentUserId);
548             stopUserAfterWaitingForBroadcastIdle(userId, /* force */true);
549             attestFalse("Failed to stop user " + userId, mAm.isUserRunning(userId));
550             mRunner.resumeTimingForNextIteration();
551         }
552         removeUser(userId);
553     }
554 
555     /** Tests switching to a previously-started, but no-longer-running, user with wait
556      * times between iterations and using a static wallpaper */
557     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_stopped_staticWallpaper()558     public void switchUser_stopped_staticWallpaper() throws RemoteException {
559         assumeTrue(mWm.isWallpaperSupported() && mWm.isSetWallpaperAllowed());
560         final int startUser = ActivityManager.getCurrentUser();
561         final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true,
562                 /* useStaticWallpaper */true);
563         while (mRunner.keepRunning()) {
564             mRunner.pauseTiming();
565             waitCoolDownPeriod();
566             Log.d(TAG, "Starting timer");
567             mRunner.resumeTiming();
568 
569             switchUser(testUser);
570 
571             mRunner.pauseTiming();
572             Log.d(TAG, "Stopping timer");
573             switchUserNoCheck(startUser);
574             stopUserAfterWaitingForBroadcastIdle(testUser, true);
575             attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
576             mRunner.resumeTimingForNextIteration();
577         }
578         removeUser(testUser);
579     }
580 
581     /** Tests switching to an already-created already-running non-owner background user. */
582     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_running()583     public void switchUser_running() throws RemoteException {
584         while (mRunner.keepRunning()) {
585             mRunner.pauseTiming();
586             final int startUser = mAm.getCurrentUser();
587             final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false);
588             mRunner.resumeTiming();
589             Log.i(TAG, "Starting timer");
590 
591             switchUser(testUser);
592 
593             mRunner.pauseTiming();
594             Log.i(TAG, "Stopping timer");
595             switchUserNoCheck(startUser);
596             removeUser(testUser);
597             mRunner.resumeTimingForNextIteration();
598         }
599     }
600 
601     /** Tests switching to an already-created already-running non-owner background user, with wait
602      * times between iterations */
603     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_running_initializedUser()604     public void switchUser_running_initializedUser() throws RemoteException {
605         final int startUser = ActivityManager.getCurrentUser();
606         final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false);
607         while (mRunner.keepRunning()) {
608             mRunner.pauseTiming();
609             waitCoolDownPeriod();
610             Log.d(TAG, "Starting timer");
611             mRunner.resumeTiming();
612 
613             switchUser(testUser);
614 
615             mRunner.pauseTiming();
616             Log.d(TAG, "Stopping timer");
617             waitForBroadcastIdle();
618             switchUserNoCheck(startUser);
619             mRunner.resumeTimingForNextIteration();
620         }
621         removeUser(testUser);
622     }
623 
624     /** Tests switching to an already-created already-running non-owner background user, with wait
625      * times between iterations and using a default static wallpaper */
626     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_running_staticWallpaper()627     public void switchUser_running_staticWallpaper() throws RemoteException {
628         assumeTrue(mWm.isWallpaperSupported() && mWm.isSetWallpaperAllowed());
629         final int startUser = ActivityManager.getCurrentUser();
630         final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false,
631                 /* useStaticWallpaper */ true);
632         while (mRunner.keepRunning()) {
633             mRunner.pauseTiming();
634             waitCoolDownPeriod();
635             Log.d(TAG, "Starting timer");
636             mRunner.resumeTiming();
637 
638             switchUser(testUser);
639 
640             mRunner.pauseTiming();
641             Log.d(TAG, "Stopping timer");
642             waitForBroadcastIdle();
643             switchUserNoCheck(startUser);
644             mRunner.resumeTimingForNextIteration();
645         }
646         removeUser(testUser);
647     }
648 
649     /** Tests stopping a background user. */
650     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
stopUser()651     public void stopUser() throws RemoteException {
652         while (mRunner.keepRunning()) {
653             mRunner.pauseTiming();
654             final int userId = createUserNoFlags();
655 
656             runThenWaitForBroadcasts(userId, ()-> {
657                 mIam.startUserInBackground(userId);
658             }, Intent.ACTION_USER_STARTED, Intent.ACTION_MEDIA_MOUNTED);
659 
660             mRunner.resumeTiming();
661             Log.i(TAG, "Starting timer");
662 
663             stopUser(userId, false);
664 
665             mRunner.pauseTiming();
666             Log.i(TAG, "Stopping timer");
667             removeUser(userId);
668             mRunner.resumeTimingForNextIteration();
669         }
670     }
671 
672     /** Tests stopping a background user, with wait times between iterations. The hypothesis is
673      * that the effects of the user creation could impact the measured times, so in this variant we
674      * create one user per run, instead of one per iteration */
675     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
stopUser_realistic()676     public void stopUser_realistic() throws RemoteException {
677         final int userId = createUserNoFlags();
678         waitCoolDownPeriod();
679         while (mRunner.keepRunning()) {
680             mRunner.pauseTiming();
681             runThenWaitForBroadcasts(userId, ()-> {
682                 mIam.startUserInBackground(userId);
683             }, Intent.ACTION_USER_STARTED, Intent.ACTION_MEDIA_MOUNTED);
684             waitCoolDownPeriod();
685             Log.d(TAG, "Starting timer");
686             mRunner.resumeTiming();
687 
688             stopUser(userId, false);
689 
690             mRunner.pauseTiming();
691             Log.d(TAG, "Stopping timer");
692 
693             mRunner.resumeTimingForNextIteration();
694         }
695         removeUser(userId);
696     }
697 
698     /** Tests reaching LOCKED_BOOT_COMPLETE when switching to uninitialized user. */
699     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
lockedBootCompleted()700     public void lockedBootCompleted() throws RemoteException {
701         while (mRunner.keepRunning()) {
702             mRunner.pauseTiming();
703             final int startUser = mAm.getCurrentUser();
704             final int userId = createUserNoFlags();
705 
706             waitForBroadcastIdle();
707             mUserSwitchWaiter.runThenWaitUntilBootCompleted(userId, () -> {
708                 mRunner.resumeTiming();
709                 Log.i(TAG, "Starting timer");
710                 mAm.switchUser(userId);
711             }, () -> fail("Failed to achieve onLockedBootComplete for user " + userId));
712 
713             mRunner.pauseTiming();
714             Log.i(TAG, "Stopping timer");
715             switchUserNoCheck(startUser);
716             removeUser(userId);
717             mRunner.resumeTimingForNextIteration();
718         }
719     }
720 
721     /** Tests reaching LOCKED_BOOT_COMPLETE when switching to uninitialized user. */
722     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
lockedBootCompleted_realistic()723     public void lockedBootCompleted_realistic() throws RemoteException {
724         while (mRunner.keepRunning()) {
725             mRunner.pauseTiming();
726             final int startUser = ActivityManager.getCurrentUser();
727             final int userId = createUserNoFlags();
728 
729             waitCoolDownPeriod();
730             mUserSwitchWaiter.runThenWaitUntilBootCompleted(userId, () -> {
731                 mRunner.resumeTiming();
732                 Log.d(TAG, "Starting timer");
733                 mAm.switchUser(userId);
734             }, () -> fail("Failed to achieve onLockedBootComplete for user " + userId));
735 
736             mRunner.pauseTiming();
737             Log.d(TAG, "Stopping timer");
738             switchUserNoCheck(startUser);
739             removeUser(userId);
740             mRunner.resumeTimingForNextIteration();
741         }
742     }
743 
744     /** Tests stopping an ephemeral foreground user. */
745     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
ephemeralUserStopped()746     public void ephemeralUserStopped() throws RemoteException {
747         while (mRunner.keepRunning()) {
748             mRunner.pauseTiming();
749             final int startUser = mAm.getCurrentUser();
750             final int userId = createUserWithFlags(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
751             runThenWaitForBroadcasts(userId, () -> {
752                 switchUser(userId);
753             }, Intent.ACTION_MEDIA_MOUNTED);
754 
755             waitForBroadcastIdle();
756             mUserSwitchWaiter.runThenWaitUntilSwitchCompleted(startUser, () -> {
757                 runThenWaitForBroadcasts(userId, () -> {
758                     mRunner.resumeTiming();
759                     Log.i(TAG, "Starting timer");
760 
761                     mAm.switchUser(startUser);
762                 }, Intent.ACTION_USER_STOPPED);
763 
764                 mRunner.pauseTiming();
765                 Log.i(TAG, "Stopping timer");
766             }, null);
767 
768             removeUser(userId);
769             mRunner.resumeTimingForNextIteration();
770         }
771     }
772 
773     /** Tests stopping an ephemeral foreground user. */
774     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
ephemeralUserStopped_realistic()775     public void ephemeralUserStopped_realistic() throws RemoteException {
776         while (mRunner.keepRunning()) {
777             mRunner.pauseTiming();
778             final int startUser = ActivityManager.getCurrentUser();
779             final int userId = createUserWithFlags(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
780             runThenWaitForBroadcasts(userId, () -> {
781                 switchUser(userId);
782             }, Intent.ACTION_MEDIA_MOUNTED);
783 
784             waitCoolDownPeriod();
785             mUserSwitchWaiter.runThenWaitUntilSwitchCompleted(startUser, () -> {
786                 runThenWaitForBroadcasts(userId, () -> {
787                     mRunner.resumeTiming();
788                     Log.d(TAG, "Starting timer");
789 
790                     mAm.switchUser(startUser);
791                 }, Intent.ACTION_USER_STOPPED);
792 
793                 mRunner.pauseTiming();
794                 Log.d(TAG, "Stopping timer");
795             }, null);
796             mRunner.resumeTimingForNextIteration();
797         }
798     }
799 
800     /** Tests creating a new profile. */
801     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileCreate()802     public void managedProfileCreate() throws RemoteException {
803         assumeTrue(mHasManagedUserFeature);
804 
805         while (mRunner.keepRunning()) {
806             Log.i(TAG, "Starting timer");
807             final int userId = createManagedProfile();
808 
809             mRunner.pauseTiming();
810             Log.i(TAG, "Stopping timer");
811             attestTrue("Failed creating profile " + userId, mUm.isManagedProfile(userId));
812             removeUser(userId);
813             mRunner.resumeTimingForNextIteration();
814         }
815     }
816 
817     /** Tests creating a new profile. */
818     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileCreate_realistic()819     public void managedProfileCreate_realistic() throws RemoteException {
820         assumeTrue(mHasManagedUserFeature);
821 
822         while (mRunner.keepRunning()) {
823             Log.d(TAG, "Starting timer");
824             final int userId = createManagedProfile();
825 
826             mRunner.pauseTiming();
827             Log.d(TAG, "Stopping timer");
828             attestTrue("Failed creating profile " + userId, mUm.isManagedProfile(userId));
829             removeUser(userId);
830             waitCoolDownPeriod();
831             mRunner.resumeTimingForNextIteration();
832         }
833     }
834 
835     /** Tests starting (unlocking) an uninitialized profile. */
836     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock()837     public void managedProfileUnlock() throws RemoteException {
838         assumeTrue(mHasManagedUserFeature);
839 
840         while (mRunner.keepRunning()) {
841             mRunner.pauseTiming();
842             final int userId = createManagedProfile();
843             mRunner.resumeTiming();
844             Log.i(TAG, "Starting timer");
845 
846             startUserInBackgroundAndWaitForUnlock(userId);
847 
848             mRunner.pauseTiming();
849             Log.i(TAG, "Stopping timer");
850             removeUser(userId);
851             mRunner.resumeTimingForNextIteration();
852         }
853     }
854 
855     /** Tests starting (unlocking) an uninitialized profile. */
856     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_realistic()857     public void managedProfileUnlock_realistic() throws RemoteException {
858         assumeTrue(mHasManagedUserFeature);
859 
860         while (mRunner.keepRunning()) {
861             mRunner.pauseTiming();
862             final int userId = createManagedProfile();
863             mRunner.resumeTiming();
864             Log.d(TAG, "Starting timer");
865 
866             startUserInBackgroundAndWaitForUnlock(userId);
867 
868             mRunner.pauseTiming();
869             Log.d(TAG, "Stopping timer");
870             removeUser(userId);
871             waitCoolDownPeriod();
872             mRunner.resumeTimingForNextIteration();
873         }
874     }
875 
876     /** Tests starting (unlocking) a previously-started, but no-longer-running, profile. */
877     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_stopped()878     public void managedProfileUnlock_stopped() throws RemoteException {
879         assumeTrue(mHasManagedUserFeature);
880 
881         while (mRunner.keepRunning()) {
882             mRunner.pauseTiming();
883             final int userId = createManagedProfile();
884             // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
885             startUserInBackgroundAndWaitForUnlock(userId);
886             stopUserAfterWaitingForBroadcastIdle(userId, true);
887             mRunner.resumeTiming();
888             Log.i(TAG, "Starting timer");
889 
890             startUserInBackgroundAndWaitForUnlock(userId);
891 
892             mRunner.pauseTiming();
893             Log.i(TAG, "Stopping timer");
894             removeUser(userId);
895             mRunner.resumeTimingForNextIteration();
896         }
897     }
898 
899     /** Tests starting (unlocking) a previously-started, but no-longer-running, profile. */
900     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_stopped_realistic()901     public void managedProfileUnlock_stopped_realistic() throws RemoteException {
902         assumeTrue(mHasManagedUserFeature);
903         final int userId = createManagedProfile();
904         // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
905         startUserInBackgroundAndWaitForUnlock(userId);
906         while (mRunner.keepRunning()) {
907             mRunner.pauseTiming();
908             stopUserAfterWaitingForBroadcastIdle(userId, true);
909             mRunner.resumeTiming();
910             Log.d(TAG, "Starting timer");
911 
912             startUserInBackgroundAndWaitForUnlock(userId);
913 
914             mRunner.pauseTiming();
915             Log.d(TAG, "Stopping timer");
916             waitCoolDownPeriod();
917             mRunner.resumeTimingForNextIteration();
918         }
919         removeUser(userId);
920     }
921 
922     /**
923      * Tests starting (unlocking) & launching an already-installed app in an uninitialized profile.
924      */
925     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlockAndLaunchApp()926     public void managedProfileUnlockAndLaunchApp() throws RemoteException {
927         assumeTrue(mHasManagedUserFeature);
928 
929         while (mRunner.keepRunning()) {
930             mRunner.pauseTiming();
931             final int userId = createManagedProfile();
932             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
933             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
934             mRunner.resumeTiming();
935             Log.i(TAG, "Starting timer");
936 
937             startUserInBackgroundAndWaitForUnlock(userId);
938             startApp(userId, DUMMY_PACKAGE_NAME);
939 
940             mRunner.pauseTiming();
941             Log.i(TAG, "Stopping timer");
942             removeUser(userId);
943             mRunner.resumeTimingForNextIteration();
944         }
945     }
946 
947     /**
948      * Tests starting (unlocking) & launching an already-installed app in an uninitialized profile.
949      */
950     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlockAndLaunchApp_realistic()951     public void managedProfileUnlockAndLaunchApp_realistic() throws RemoteException {
952         assumeTrue(mHasManagedUserFeature);
953 
954         while (mRunner.keepRunning()) {
955             mRunner.pauseTiming();
956             final int userId = createManagedProfile();
957             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
958             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
959             mRunner.resumeTiming();
960             Log.d(TAG, "Starting timer");
961 
962             startUserInBackgroundAndWaitForUnlock(userId);
963             startApp(userId, DUMMY_PACKAGE_NAME);
964 
965             mRunner.pauseTiming();
966             Log.d(TAG, "Stopping timer");
967             removeUser(userId);
968             waitCoolDownPeriod();
969             mRunner.resumeTimingForNextIteration();
970         }
971     }
972 
973     /**
974      * Tests starting (unlocking) and launching a previously-launched app
975      * in a previously-started, but no-longer-running, profile.
976      * A sort of combination of {@link #managedProfileUnlockAndLaunchApp} and
977      * {@link #managedProfileUnlock_stopped}}.
978      */
979     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlockAndLaunchApp_stopped()980     public void managedProfileUnlockAndLaunchApp_stopped() throws RemoteException {
981         assumeTrue(mHasManagedUserFeature);
982 
983         while (mRunner.keepRunning()) {
984             mRunner.pauseTiming();
985             final int userId = createManagedProfile();
986             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
987             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
988             startUserInBackgroundAndWaitForUnlock(userId);
989             startApp(userId, DUMMY_PACKAGE_NAME);
990             stopUserAfterWaitingForBroadcastIdle(userId, true);
991             SystemClock.sleep(1_000); // 1 second cool-down before re-starting profile.
992             mRunner.resumeTiming();
993             Log.i(TAG, "Starting timer");
994 
995             startUserInBackgroundAndWaitForUnlock(userId);
996             startApp(userId, DUMMY_PACKAGE_NAME);
997 
998             mRunner.pauseTiming();
999             Log.i(TAG, "Stopping timer");
1000             removeUser(userId);
1001             mRunner.resumeTimingForNextIteration();
1002         }
1003     }
1004 
1005     /**
1006      * Tests starting (unlocking) and launching a previously-launched app
1007      * in a previously-started, but no-longer-running, profile.
1008      * A sort of combination of {@link #managedProfileUnlockAndLaunchApp} and
1009      * {@link #managedProfileUnlock_stopped}}.
1010      */
1011     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlockAndLaunchApp_stopped_realistic()1012     public void managedProfileUnlockAndLaunchApp_stopped_realistic() throws RemoteException {
1013         assumeTrue(mHasManagedUserFeature);
1014 
1015         while (mRunner.keepRunning()) {
1016             mRunner.pauseTiming();
1017             final int userId = createManagedProfile();
1018             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
1019             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
1020             startUserInBackgroundAndWaitForUnlock(userId);
1021             startApp(userId, DUMMY_PACKAGE_NAME);
1022             stopUserAfterWaitingForBroadcastIdle(userId, true);
1023             SystemClock.sleep(1_000); // 1 second cool-down before re-starting profile.
1024             mRunner.resumeTiming();
1025             Log.d(TAG, "Starting timer");
1026 
1027             startUserInBackgroundAndWaitForUnlock(userId);
1028             startApp(userId, DUMMY_PACKAGE_NAME);
1029 
1030             mRunner.pauseTiming();
1031             Log.d(TAG, "Stopping timer");
1032             removeUser(userId);
1033             waitCoolDownPeriod();
1034             mRunner.resumeTimingForNextIteration();
1035         }
1036     }
1037 
1038     /** Tests installing a pre-existing app in an uninitialized profile. */
1039     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileInstall()1040     public void managedProfileInstall() throws RemoteException {
1041         assumeTrue(mHasManagedUserFeature);
1042 
1043         while (mRunner.keepRunning()) {
1044             mRunner.pauseTiming();
1045             final int userId = createManagedProfile();
1046             mRunner.resumeTiming();
1047             Log.i(TAG, "Starting timer");
1048 
1049             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
1050 
1051             mRunner.pauseTiming();
1052             Log.i(TAG, "Stopping timer");
1053             removeUser(userId);
1054             mRunner.resumeTimingForNextIteration();
1055         }
1056     }
1057 
1058     /** Tests installing a pre-existing app in an uninitialized profile. */
1059     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileInstall_realistic()1060     public void managedProfileInstall_realistic() throws RemoteException {
1061         assumeTrue(mHasManagedUserFeature);
1062 
1063         while (mRunner.keepRunning()) {
1064             mRunner.pauseTiming();
1065             final int userId = createManagedProfile();
1066             mRunner.resumeTiming();
1067             Log.d(TAG, "Starting timer");
1068 
1069             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
1070 
1071             mRunner.pauseTiming();
1072             Log.d(TAG, "Stopping timer");
1073             removeUser(userId);
1074             waitCoolDownPeriod();
1075             mRunner.resumeTimingForNextIteration();
1076         }
1077     }
1078 
1079     /**
1080      * Tests creating a new profile, starting (unlocking) it, installing an app,
1081      * and launching that app in it.
1082      */
1083     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileCreateUnlockInstallAndLaunchApp()1084     public void managedProfileCreateUnlockInstallAndLaunchApp() throws RemoteException {
1085         assumeTrue(mHasManagedUserFeature);
1086 
1087         while (mRunner.keepRunning()) {
1088             mRunner.pauseTiming();
1089             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
1090             mRunner.resumeTiming();
1091             Log.i(TAG, "Starting timer");
1092 
1093             final int userId = createManagedProfile();
1094             startUserInBackgroundAndWaitForUnlock(userId);
1095             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
1096             startApp(userId, DUMMY_PACKAGE_NAME);
1097 
1098             mRunner.pauseTiming();
1099             Log.i(TAG, "Stopping timer");
1100             removeUser(userId);
1101             mRunner.resumeTimingForNextIteration();
1102         }
1103     }
1104 
1105     /**
1106      * Tests creating a new profile, starting (unlocking) it, installing an app,
1107      * and launching that app in it.
1108      */
1109     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileCreateUnlockInstallAndLaunchApp_realistic()1110     public void managedProfileCreateUnlockInstallAndLaunchApp_realistic() throws RemoteException {
1111         assumeTrue(mHasManagedUserFeature);
1112 
1113         while (mRunner.keepRunning()) {
1114             mRunner.pauseTiming();
1115             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
1116             mRunner.resumeTiming();
1117             Log.d(TAG, "Starting timer");
1118 
1119             final int userId = createManagedProfile();
1120             startUserInBackgroundAndWaitForUnlock(userId);
1121             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
1122             startApp(userId, DUMMY_PACKAGE_NAME);
1123 
1124             mRunner.pauseTiming();
1125             Log.d(TAG, "Stopping timer");
1126             removeUser(userId);
1127             waitCoolDownPeriod();
1128             mRunner.resumeTimingForNextIteration();
1129         }
1130     }
1131 
1132     /** Tests stopping a profile. */
1133     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileStopped()1134     public void managedProfileStopped() throws RemoteException {
1135         assumeTrue(mHasManagedUserFeature);
1136 
1137         while (mRunner.keepRunning()) {
1138             mRunner.pauseTiming();
1139             final int userId = createManagedProfile();
1140             runThenWaitForBroadcasts(userId, () -> {
1141                 startUserInBackgroundAndWaitForUnlock(userId);
1142             }, Intent.ACTION_MEDIA_MOUNTED);
1143 
1144             mRunner.resumeTiming();
1145             Log.i(TAG, "Starting timer");
1146 
1147             stopUser(userId, true);
1148 
1149             mRunner.pauseTiming();
1150             Log.i(TAG, "Stopping timer");
1151             removeUser(userId);
1152             mRunner.resumeTimingForNextIteration();
1153         }
1154     }
1155 
1156     /** Tests stopping a profile. */
1157     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileStopped_realistic()1158     public void managedProfileStopped_realistic() throws RemoteException {
1159         assumeTrue(mHasManagedUserFeature);
1160         final int userId = createManagedProfile();
1161         while (mRunner.keepRunning()) {
1162             mRunner.pauseTiming();
1163 
1164             runThenWaitForBroadcasts(userId, () -> {
1165                 startUserInBackgroundAndWaitForUnlock(userId);
1166             }, Intent.ACTION_MEDIA_MOUNTED);
1167             waitCoolDownPeriod();
1168             mRunner.resumeTiming();
1169             Log.d(TAG, "Starting timer");
1170 
1171             stopUser(userId, true);
1172 
1173             mRunner.pauseTiming();
1174             Log.d(TAG, "Stopping timer");
1175             mRunner.resumeTimingForNextIteration();
1176         }
1177         removeUser(userId);
1178     }
1179 
1180     // TODO: This is just a POC. Do this properly and add more.
1181     /** Tests starting (unlocking) a newly-created profile using the user-type-pkg-whitelist. */
1182     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_usingWhitelist()1183     public void managedProfileUnlock_usingWhitelist() throws RemoteException {
1184         assumeTrue(mHasManagedUserFeature);
1185         final int origMode = getUserTypePackageWhitelistMode();
1186         setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE
1187                 | USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST);
1188 
1189         try {
1190             while (mRunner.keepRunning()) {
1191                 mRunner.pauseTiming();
1192                 final int userId = createManagedProfile();
1193                 mRunner.resumeTiming();
1194                 Log.i(TAG, "Starting timer");
1195 
1196                 startUserInBackgroundAndWaitForUnlock(userId);
1197 
1198                 mRunner.pauseTiming();
1199                 Log.i(TAG, "Stopping timer");
1200                 removeUser(userId);
1201                 mRunner.resumeTimingForNextIteration();
1202             }
1203         } finally {
1204             setUserTypePackageWhitelistMode(origMode);
1205         }
1206     }
1207     /** Tests starting (unlocking) a newly-created profile NOT using the user-type-pkg-whitelist. */
1208     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_notUsingWhitelist()1209     public void managedProfileUnlock_notUsingWhitelist() throws RemoteException {
1210         assumeTrue(mHasManagedUserFeature);
1211         final int origMode = getUserTypePackageWhitelistMode();
1212         setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE);
1213 
1214         try {
1215             while (mRunner.keepRunning()) {
1216                 mRunner.pauseTiming();
1217                 final int userId = createManagedProfile();
1218                 mRunner.resumeTiming();
1219                 Log.i(TAG, "Starting timer");
1220 
1221                 startUserInBackgroundAndWaitForUnlock(userId);
1222 
1223                 mRunner.pauseTiming();
1224                 Log.i(TAG, "Stopping timer");
1225                 removeUser(userId);
1226                 mRunner.resumeTimingForNextIteration();
1227             }
1228         } finally {
1229             setUserTypePackageWhitelistMode(origMode);
1230         }
1231     }
1232 
1233     /** Creates a new user, returning its userId. */
createUserNoFlags()1234     private int createUserNoFlags() {
1235         return createUserWithFlags(/* flags= */ 0);
1236     }
1237 
1238     /** Creates a new user with the given flags, returning its userId. */
createUserWithFlags(int flags)1239     private int createUserWithFlags(int flags) {
1240         int userId = mUm.createUser(TEST_USER_NAME, flags).id;
1241         mUsersToRemove.add(userId);
1242         return userId;
1243     }
1244 
1245     /** Creates a managed (work) profile under the current user, returning its userId. */
createManagedProfile()1246     private int createManagedProfile() {
1247         final UserInfo userInfo = mUm.createProfileForUser(TEST_USER_NAME,
1248                 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, mAm.getCurrentUser());
1249         attestFalse("Creating managed profile failed. Most likely there is "
1250                 + "already a pre-existing profile on the device.", userInfo == null);
1251         mUsersToRemove.add(userInfo.id);
1252         return userInfo.id;
1253     }
1254 
1255     /**
1256      * Start user in background and wait for it to unlock by waiting for
1257      * UserState.mUnlockProgress.finish().
1258      * <p> To start in foreground instead, see {@link #switchUser(int)}.
1259      * <p> This should always be used for profiles since profiles cannot be started in foreground.
1260      */
startUserInBackgroundAndWaitForUnlock(int userId)1261     private void startUserInBackgroundAndWaitForUnlock(int userId) {
1262         try {
1263             attestTrue("Failed to start user " + userId + " in background.",
1264                     ShellHelper.runShellCommandWithTimeout("am start-user -w " + userId,
1265                             TIMEOUT_IN_SECOND).startsWith("Success:"));
1266         } catch (TimeoutException e) {
1267             fail("Could not start user " + userId + " in " + TIMEOUT_IN_SECOND + " seconds");
1268         }
1269     }
1270 
1271     /** Starts the given user in the foreground. */
switchUser(int userId)1272     private void switchUser(int userId) throws RemoteException {
1273         boolean success = switchUserNoCheck(userId);
1274         attestTrue("Failed to properly switch to user " + userId, success);
1275     }
1276 
1277     /**
1278      * Starts the given user in the foreground.
1279      * Returns true if successful. Does not fail the test if unsuccessful.
1280      * If lack of success should fail the test, use {@link #switchUser(int)} instead.
1281      */
switchUserNoCheck(int userId)1282     private boolean switchUserNoCheck(int userId) throws RemoteException {
1283         final boolean[] success = {true};
1284         mUserSwitchWaiter.runThenWaitUntilSwitchCompleted(userId, () -> {
1285             mAm.switchUser(userId);
1286         }, () -> success[0] = false);
1287         return success[0];
1288     }
1289 
1290     /**
1291      * Waits for broadcast idle before stopping a user, to prevent timeouts on stop user.
1292      * Stopping a user heavily depends on broadcast queue, and that gets crowded after user creation
1293      * or user switches, which leads to a timeout on stopping user and cause the tests to be flaky.
1294      * Do not call this method while timing is on. i.e. between mRunner.resumeTiming() and
1295      * mRunner.pauseTiming(). Otherwise it would cause the test results to be spiky.
1296      */
stopUserAfterWaitingForBroadcastIdle(int userId, boolean force)1297     private void stopUserAfterWaitingForBroadcastIdle(int userId, boolean force)
1298             throws RemoteException {
1299         waitForBroadcastIdle();
1300         stopUser(userId, force);
1301     }
1302 
stopUser(int userId, boolean force)1303     private void stopUser(int userId, boolean force) throws RemoteException {
1304         final CountDownLatch latch = new CountDownLatch(1);
1305         mIam.stopUser(userId, force /* force */, new IStopUserCallback.Stub() {
1306             @Override
1307             public void userStopped(int userId) throws RemoteException {
1308                 latch.countDown();
1309             }
1310 
1311             @Override
1312             public void userStopAborted(int userId) throws RemoteException {
1313             }
1314         });
1315         waitForLatch("Failed to properly stop user " + userId, latch);
1316     }
1317 
initializeNewUserAndSwitchBack(boolean stopNewUser)1318     private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws RemoteException {
1319         return initializeNewUserAndSwitchBack(stopNewUser, /* useStaticWallpaper */ false);
1320     }
1321 
1322     /**
1323      * Creates a user and waits for its ACTION_USER_UNLOCKED.
1324      * Then switches to back to the original user and waits for its switchUser() to finish.
1325      *
1326      * @param stopNewUser whether to stop the new user after switching to otherUser.
1327      * @param useStaticWallpaper whether to switch the wallpaper of the default user to a static.
1328      * @return userId of the newly created user.
1329      */
initializeNewUserAndSwitchBack(boolean stopNewUser, boolean useStaticWallpaper)1330     private int initializeNewUserAndSwitchBack(boolean stopNewUser, boolean useStaticWallpaper)
1331             throws RemoteException {
1332         final int origUser = mAm.getCurrentUser();
1333         // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED
1334         final int testUser = createUserNoFlags();
1335         runThenWaitForBroadcasts(testUser, () -> {
1336             mAm.switchUser(testUser);
1337         }, Intent.ACTION_USER_UNLOCKED, Intent.ACTION_MEDIA_MOUNTED);
1338 
1339         if (useStaticWallpaper) {
1340             assertTrue(mWm.isWallpaperSupported() && mWm.isSetWallpaperAllowed());
1341             try {
1342                 Bitmap blank = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
1343                 mWm.setBitmap(blank, /* visibleCropHint */ null, /* allowBackup */ true,
1344                         /* which */ FLAG_SYSTEM | FLAG_LOCK, testUser);
1345             } catch (IOException exception) {
1346                 fail("Unable to set static wallpaper.");
1347             }
1348         }
1349 
1350         // Second, switch back to origUser, waiting merely for switchUser() to finish
1351         switchUser(origUser);
1352         attestTrue("Didn't switch back to user, " + origUser, origUser == mAm.getCurrentUser());
1353 
1354         if (stopNewUser) {
1355             stopUserAfterWaitingForBroadcastIdle(testUser, true);
1356             attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
1357         }
1358 
1359         return testUser;
1360     }
1361 
1362     /**
1363      * Installs the given package in the given user.
1364      */
installPreexistingApp(int userId, String packageName)1365     private void installPreexistingApp(int userId, String packageName) throws RemoteException {
1366         final CountDownLatch latch = new CountDownLatch(1);
1367 
1368         final IntentSender sender = new IntentSender((IIntentSender) new IIntentSender.Stub() {
1369             @Override
1370             public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
1371                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1372                 latch.countDown();
1373             }
1374         });
1375 
1376         final IPackageInstaller installer = AppGlobals.getPackageManager().getPackageInstaller();
1377         installer.installExistingPackage(packageName,
1378                 PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
1379                 PackageManager.INSTALL_REASON_UNKNOWN, sender, userId, null);
1380 
1381         waitForLatch("Failed to install app " + packageName + " on user " + userId, latch);
1382     }
1383 
1384     /**
1385      * Launches the given package in the given user.
1386      * Make sure the keyguard has been dismissed prior to calling.
1387      */
startApp(int userId, String packageName)1388     private void startApp(int userId, String packageName) {
1389         final String failMessage = "User " + userId + " failed to start " + packageName;
1390         final String component = InstrumentationRegistry.getContext().getPackageManager()
1391                 .getLaunchIntentForPackage(packageName).getComponent().flattenToShortString();
1392         try {
1393             final String result = ShellHelper.runShellCommandWithTimeout(
1394                     "am start -W -n " + component + " --user " + userId, TIMEOUT_IN_SECOND);
1395             assertTrue(failMessage + ", component=" + component + ", result=" + result,
1396                     result.contains("Status: ok")
1397                     && !result.contains("Warning:")
1398                     && !result.contains("Error:"));
1399         } catch (TimeoutException e) {
1400             fail(failMessage + " in " + TIMEOUT_IN_SECOND + " seconds");
1401         }
1402     }
1403 
1404     private class ProgressWaiter extends IProgressListener.Stub {
1405         private final CountDownLatch mFinishedLatch = new CountDownLatch(1);
1406 
1407         @Override
onStarted(int id, Bundle extras)1408         public void onStarted(int id, Bundle extras) {}
1409 
1410         @Override
onProgress(int id, int progress, Bundle extras)1411         public void onProgress(int id, int progress, Bundle extras) {}
1412 
1413         @Override
onFinished(int id, Bundle extras)1414         public void onFinished(int id, Bundle extras) {
1415             mFinishedLatch.countDown();
1416         }
1417 
waitForFinish(long timeoutSecs)1418         public boolean waitForFinish(long timeoutSecs) {
1419             try {
1420                 return mFinishedLatch.await(timeoutSecs, TimeUnit.SECONDS);
1421             } catch (InterruptedException e) {
1422                 Log.e(TAG, "Thread interrupted unexpectedly.", e);
1423                 return false;
1424             }
1425         }
1426     }
1427 
1428     /**
1429      * Waits TIMEOUT_IN_SECOND for the broadcast to be received, otherwise declares the given error.
1430      * It only works for the broadcasts provided in {@link #mBroadcastWaiter}'s instantiation above.
1431      * @param userId userId associated with the broadcast. It is {@link Intent#EXTRA_USER_HANDLE}
1432      *               or in case that is null, then it is {@link BroadcastReceiver#getSendingUserId}.
1433      * @param runnable function to be run after clearing any possible previously received broadcasts
1434      *                 and before waiting for the new broadcasts. This function should typically do
1435      *                 something to trigger broadcasts to be sent. Like starting or stopping a user.
1436      * @param actions actions of the broadcasts, i.e. {@link Intent#ACTION_USER_STARTED}.
1437      *                If multiple actions are provided, they will be waited in given order.
1438      */
runThenWaitForBroadcasts(int userId, FunctionalUtils.ThrowingRunnable runnable, String... actions)1439     private void runThenWaitForBroadcasts(int userId, FunctionalUtils.ThrowingRunnable runnable,
1440             String... actions) {
1441         final String unreceivedAction =
1442                 mBroadcastWaiter.runThenWaitForBroadcasts(userId, runnable, actions);
1443 
1444         attestTrue("Failed to achieve " + unreceivedAction + " for user " + userId,
1445                 unreceivedAction == null);
1446     }
1447 
1448     /** Waits TIMEOUT_IN_SECOND for the latch to complete, otherwise declares the given error. */
waitForLatch(String errMsg, CountDownLatch latch)1449     private void waitForLatch(String errMsg, CountDownLatch latch) {
1450         boolean success = false;
1451         try {
1452             success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
1453         } catch (InterruptedException e) {
1454             Log.e(TAG, "Thread interrupted unexpectedly.", e);
1455         }
1456         attestTrue(errMsg, success);
1457     }
1458 
1459     /** Gets the PACKAGE_WHITELIST_MODE_PROP System Property. */
getUserTypePackageWhitelistMode()1460     private int getUserTypePackageWhitelistMode() {
1461         return SystemProperties.getInt(PACKAGE_WHITELIST_MODE_PROP,
1462                 USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT);
1463     }
1464 
1465     /** Sets the PACKAGE_WHITELIST_MODE_PROP System Property to the given value. */
setUserTypePackageWhitelistMode(int mode)1466     private void setUserTypePackageWhitelistMode(int mode) {
1467         String result = ShellHelper.runShellCommand(
1468                 String.format("setprop %s %d", PACKAGE_WHITELIST_MODE_PROP, mode));
1469         attestFalse("Failed to set sysprop " + PACKAGE_WHITELIST_MODE_PROP + ": " + result,
1470                 result != null && result.contains("Failed"));
1471     }
1472 
removeUser(int userId)1473     private void removeUser(int userId) throws RemoteException {
1474         stopUserAfterWaitingForBroadcastIdle(userId, true);
1475         try {
1476             ShellHelper.runShellCommandWithTimeout("pm remove-user -w " + userId,
1477                     TIMEOUT_IN_SECOND);
1478         } catch (TimeoutException e) {
1479             Log.e(TAG, String.format("Could not remove user %d in %d seconds",
1480                     userId, TIMEOUT_IN_SECOND), e);
1481         }
1482         if (mUm.getUserInfo(userId) != null) {
1483             mUsersToRemove.add(userId);
1484         }
1485     }
1486 
removeAnyPreviousTestUsers()1487     private void removeAnyPreviousTestUsers() {
1488         for (UserInfo user : mUm.getUsers()) {
1489             if (TEST_USER_NAME.equals(user.name)) {
1490                 Log.i(TAG, "Found previous test user " + user.id + ". Removing it.");
1491                 if (mAm.getCurrentUser() == user.id) {
1492                     try {
1493                         switchUserNoCheck(UserHandle.USER_SYSTEM);
1494                     } catch (RemoteException e) {
1495                         Log.e(TAG, "Failed to correctly switch to system user", e);
1496                     }
1497                 }
1498                 mUm.removeUser(user.id);
1499             }
1500         }
1501     }
1502 
1503     /**
1504      * Start the user and stop after that, will repeat numberOfIterations times.
1505      * Make sure the user is started before proceeding with the test.
1506      * @param userId identifier of the user that will be started.
1507      * @param numberOfIterations number of iterations that must be skipped.
1508      */
preStartUser(int userId, int numberOfIterations)1509     private void preStartUser(int userId, int numberOfIterations) throws RemoteException {
1510         for (int i = 0; i < numberOfIterations; i++) {
1511             final ProgressWaiter preWaiter = new ProgressWaiter();
1512 
1513             final boolean preStartComplete = mIam.startUserInBackgroundWithListener(userId,
1514                     preWaiter) && preWaiter.waitForFinish(TIMEOUT_IN_SECOND * 1000);
1515             stopUserAfterWaitingForBroadcastIdle(userId, /* force */true);
1516 
1517             assertTrue("Pre start was not performed for user" + userId, preStartComplete);
1518         }
1519     }
1520 
fail(@onNull String message)1521     private void fail(@NonNull String message) {
1522         Log.e(TAG, "Test failed on iteration #" + mRunner.getIteration() + ": " + message);
1523         mRunner.markAsFailed(new AssertionError(message));
1524     }
1525 
attestTrue(@onNull String message, boolean assertion)1526     private void attestTrue(@NonNull String message, boolean assertion) {
1527         if (!assertion) {
1528             fail(message);
1529         }
1530     }
1531 
attestFalse(@onNull String message, boolean assertion)1532     private void attestFalse(@NonNull String message, boolean assertion) {
1533         attestTrue(message, !assertion);
1534     }
1535 
setSystemProperty(String name, String value)1536     private String setSystemProperty(String name, String value) throws Exception {
1537         final String oldValue = ShellHelper.runShellCommand("getprop " + name);
1538         assertEquals("", ShellHelper.runShellCommand("setprop " + name + " " + value));
1539         return TextUtils.firstNotEmpty(oldValue, "invalid");
1540     }
1541 
waitForBroadcastIdle()1542     private void waitForBroadcastIdle() {
1543         try {
1544             ShellHelper.runShellCommandWithTimeout(
1545                     "am wait-for-broadcast-idle --flush-broadcast-loopers", TIMEOUT_IN_SECOND);
1546         } catch (TimeoutException e) {
1547             Log.e(TAG, "Ending waitForBroadcastIdle because it is taking too long", e);
1548         }
1549     }
1550 
sleep(long ms)1551     private void sleep(long ms) {
1552         try {
1553             Thread.sleep(ms);
1554         } catch (InterruptedException e) {
1555             // Ignore
1556         }
1557     }
1558 
waitCoolDownPeriod()1559     private void waitCoolDownPeriod() {
1560         final int tenSeconds = 1000 * 10;
1561         waitForBroadcastIdle();
1562         sleep(tenSeconds);
1563     }
1564 }
1565