• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 org.junit.Assume.assumeTrue;
19 
20 import android.annotation.NonNull;
21 import android.app.ActivityManager;
22 import android.app.ActivityTaskManager;
23 import android.app.AppGlobals;
24 import android.app.IActivityManager;
25 import android.app.IStopUserCallback;
26 import android.app.UserSwitchObserver;
27 import android.app.WaitResult;
28 import android.content.BroadcastReceiver;
29 import android.content.Context;
30 import android.content.IIntentReceiver;
31 import android.content.IIntentSender;
32 import android.content.Intent;
33 import android.content.IntentFilter;
34 import android.content.IntentSender;
35 import android.content.pm.IPackageInstaller;
36 import android.content.pm.PackageManager;
37 import android.content.pm.UserInfo;
38 import android.os.Bundle;
39 import android.os.IBinder;
40 import android.os.IProgressListener;
41 import android.os.RemoteException;
42 import android.os.SystemClock;
43 import android.os.SystemProperties;
44 import android.os.UserHandle;
45 import android.os.UserManager;
46 import android.perftests.utils.ShellHelper;
47 import android.util.Log;
48 import android.view.WindowManagerGlobal;
49 
50 import androidx.test.InstrumentationRegistry;
51 import androidx.test.filters.LargeTest;
52 import androidx.test.runner.AndroidJUnit4;
53 
54 import org.junit.After;
55 import org.junit.Before;
56 import org.junit.Rule;
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 
60 import java.util.ArrayList;
61 import java.util.concurrent.CountDownLatch;
62 import java.util.concurrent.TimeUnit;
63 
64 /**
65  * Perf tests for user life cycle events.
66  *
67  * To run the tests: atest UserLifecycleTests
68  *
69  *
70  * Old methods for running the tests:
71  *
72  * make MultiUserPerfTests &&
73  * adb install -r \
74  *     ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk &&
75  * adb shell am instrument -e class android.multiuser.UserLifecycleTests \
76  *     -w com.android.perftests.multiuser/androidx.test.runner.AndroidJUnitRunner
77  *
78  * or
79  *
80  * bit MultiUserPerfTests:android.multiuser.UserLifecycleTests
81  *
82  * Note: If you use bit for running the tests, benchmark results won't be printed on the host side.
83  * But in either case, results can be checked on the device side 'adb logcat -s UserLifecycleTests'
84  */
85 @LargeTest
86 @RunWith(AndroidJUnit4.class)
87 public class UserLifecycleTests {
88     private static final String TAG = UserLifecycleTests.class.getSimpleName();
89 
90     /** Max runtime for each test (including all runs within that test). */
91     // Must be less than the AndroidTest.xml test-timeout to avoid being considered non-responsive.
92     private static final long TIMEOUT_MAX_TEST_TIME_MS = 24 * 60_000;
93 
94     private static final int TIMEOUT_IN_SECOND = 30;
95     private static final int CHECK_USER_REMOVED_INTERVAL_MS = 200;
96 
97     /** Name of users/profiles in the test. Users with this name may be freely removed. */
98     private static final String TEST_USER_NAME = "UserLifecycleTests_test_user";
99 
100     /** Name of dummy package used when timing how long app launches take. */
101     private static final String DUMMY_PACKAGE_NAME = "perftests.multiuser.apps.dummyapp";
102 
103     // Copy of UserSystemPackageInstaller whitelist mode constants.
104     private static final String PACKAGE_WHITELIST_MODE_PROP =
105             "persist.debug.user.package_whitelist_mode";
106     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0;
107     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0b001;
108     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0b100;
109     private static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1;
110 
111     private UserManager mUm;
112     private ActivityManager mAm;
113     private IActivityManager mIam;
114     private PackageManager mPm;
115     private ArrayList<Integer> mUsersToRemove;
116     private boolean mHasManagedUserFeature;
117     private BroadcastWaiter mBroadcastWaiter;
118 
119     private final BenchmarkRunner mRunner = new BenchmarkRunner();
120     @Rule
121     public BenchmarkResultsReporter mReporter = new BenchmarkResultsReporter(mRunner);
122 
123     @Before
setUp()124     public void setUp() {
125         final Context context = InstrumentationRegistry.getContext();
126         mUm = UserManager.get(context);
127         mAm = context.getSystemService(ActivityManager.class);
128         mIam = ActivityManager.getService();
129         mUsersToRemove = new ArrayList<>();
130         mPm = context.getPackageManager();
131         mHasManagedUserFeature = mPm.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
132         mBroadcastWaiter = new BroadcastWaiter(context, TAG, TIMEOUT_IN_SECOND,
133                 Intent.ACTION_USER_STARTED,
134                 Intent.ACTION_MEDIA_MOUNTED,
135                 Intent.ACTION_USER_UNLOCKED);
136         removeAnyPreviousTestUsers();
137         if (mAm.getCurrentUser() != UserHandle.USER_SYSTEM) {
138             Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser()
139                     + " rather than the system user");
140         }
141     }
142 
143     @After
tearDown()144     public void tearDown() {
145         mBroadcastWaiter.close();
146         for (int userId : mUsersToRemove) {
147             try {
148                 mUm.removeUser(userId);
149             } catch (Exception e) {
150                 // Ignore
151             }
152         }
153     }
154 
155     /** Tests creating a new user. */
156     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
createUser()157     public void createUser() {
158         while (mRunner.keepRunning()) {
159             Log.i(TAG, "Starting timer");
160             final int userId = createUserNoFlags();
161 
162             mRunner.pauseTiming();
163             Log.i(TAG, "Stopping timer");
164             removeUser(userId);
165             mRunner.resumeTimingForNextIteration();
166         }
167     }
168 
169     /** Tests creating and starting a new user. */
170     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
createAndStartUser()171     public void createAndStartUser() throws RemoteException {
172         while (mRunner.keepRunning()) {
173             Log.i(TAG, "Starting timer");
174             final int userId = createUserNoFlags();
175 
176             // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until
177             // ACTION_USER_STARTED.
178             mIam.startUserInBackground(userId);
179             waitForBroadcast(Intent.ACTION_USER_STARTED, userId);
180 
181             mRunner.pauseTiming();
182             Log.i(TAG, "Stopping timer");
183             removeUser(userId);
184             mRunner.resumeTimingForNextIteration();
185         }
186     }
187 
188     /**
189      * Tests starting an uninitialized user.
190      * Measures the time until ACTION_USER_STARTED is received.
191      */
192     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startUser()193     public void startUser() throws RemoteException {
194         while (mRunner.keepRunning()) {
195             mRunner.pauseTiming();
196             final int userId = createUserNoFlags();
197             mRunner.resumeTiming();
198             Log.i(TAG, "Starting timer");
199 
200             mIam.startUserInBackground(userId);
201             waitForBroadcast(Intent.ACTION_USER_STARTED, userId);
202 
203             mRunner.pauseTiming();
204             Log.i(TAG, "Stopping timer");
205             removeUser(userId);
206             mRunner.resumeTimingForNextIteration();
207         }
208     }
209 
210     /**
211      * Tests starting & unlocking an uninitialized user.
212      * Measures the time until unlock listener is triggered and user is unlocked.
213      */
214     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
startAndUnlockUser()215     public void startAndUnlockUser() {
216         while (mRunner.keepRunning()) {
217             mRunner.pauseTiming();
218             final int userId = createUserNoFlags();
219             mRunner.resumeTiming();
220             Log.i(TAG, "Starting timer");
221 
222             // Waits for UserState.mUnlockProgress.finish().
223             startUserInBackgroundAndWaitForUnlock(userId);
224 
225             mRunner.pauseTiming();
226             Log.i(TAG, "Stopping timer");
227             removeUser(userId);
228             mRunner.resumeTimingForNextIteration();
229         }
230     }
231 
232     /** Tests switching to an uninitialized user. */
233     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser()234     public void switchUser() throws RemoteException {
235         while (mRunner.keepRunning()) {
236             mRunner.pauseTiming();
237             final int startUser = mAm.getCurrentUser();
238             final int userId = createUserNoFlags();
239             mRunner.resumeTiming();
240             Log.i(TAG, "Starting timer");
241 
242             switchUser(userId);
243 
244             mRunner.pauseTiming();
245             Log.i(TAG, "Stopping timer");
246             switchUserNoCheck(startUser);
247             removeUser(userId);
248             mRunner.resumeTimingForNextIteration();
249         }
250     }
251 
252     /** Tests switching to a previously-started, but no-longer-running, user. */
253     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_stopped()254     public void switchUser_stopped() throws RemoteException {
255         while (mRunner.keepRunning()) {
256             mRunner.pauseTiming();
257             final int startUser = mAm.getCurrentUser();
258             final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
259             mRunner.resumeTiming();
260             Log.i(TAG, "Starting timer");
261 
262             mAm.switchUser(testUser);
263             waitForBroadcast(Intent.ACTION_USER_UNLOCKED, testUser);
264 
265             mRunner.pauseTiming();
266             Log.i(TAG, "Stopping timer");
267             switchUserNoCheck(startUser);
268             removeUser(testUser);
269             mRunner.resumeTimingForNextIteration();
270         }
271     }
272 
273     /** Tests switching to an already-created already-running non-owner background user. */
274     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
switchUser_running()275     public void switchUser_running() throws RemoteException {
276         while (mRunner.keepRunning()) {
277             mRunner.pauseTiming();
278             final int startUser = mAm.getCurrentUser();
279             final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false);
280             mRunner.resumeTiming();
281             Log.i(TAG, "Starting timer");
282 
283             switchUser(testUser);
284 
285             mRunner.pauseTiming();
286             Log.i(TAG, "Stopping timer");
287             switchUserNoCheck(startUser);
288             removeUser(testUser);
289             mRunner.resumeTimingForNextIteration();
290         }
291     }
292 
293     /** Tests stopping a background user. */
294     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
stopUser()295     public void stopUser() throws RemoteException {
296         while (mRunner.keepRunning()) {
297             mRunner.pauseTiming();
298             final int userId = createUserNoFlags();
299             mIam.startUserInBackground(userId);
300 
301             waitForBroadcast(Intent.ACTION_USER_STARTED, userId);
302             waitForBroadcast(Intent.ACTION_MEDIA_MOUNTED, userId);
303 
304             mRunner.resumeTiming();
305             Log.i(TAG, "Starting timer");
306 
307             stopUser(userId, false);
308 
309             mRunner.pauseTiming();
310             Log.i(TAG, "Stopping timer");
311             removeUser(userId);
312             mRunner.resumeTimingForNextIteration();
313         }
314     }
315 
316     /** Tests reaching LOOKED_BOOT_COMPLETE when switching to uninitialized user. */
317     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
lockedBootCompleted()318     public void lockedBootCompleted() throws RemoteException {
319         while (mRunner.keepRunning()) {
320             mRunner.pauseTiming();
321             final int startUser = mAm.getCurrentUser();
322             final int userId = createUserNoFlags();
323             final CountDownLatch latch = new CountDownLatch(1);
324             registerUserSwitchObserver(null, latch, userId);
325             mRunner.resumeTiming();
326             Log.i(TAG, "Starting timer");
327 
328             mAm.switchUser(userId);
329             waitForLatch("Failed to achieve onLockedBootComplete for user " + userId, latch);
330 
331             mRunner.pauseTiming();
332             Log.i(TAG, "Stopping timer");
333             switchUserNoCheck(startUser);
334             removeUser(userId);
335             mRunner.resumeTimingForNextIteration();
336         }
337     }
338 
339     /** Tests stopping an ephemeral foreground user. */
340     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
ephemeralUserStopped()341     public void ephemeralUserStopped() throws RemoteException {
342         while (mRunner.keepRunning()) {
343             mRunner.pauseTiming();
344             final int startUser = mAm.getCurrentUser();
345             final int userId = createUserWithFlags(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
346             switchUser(userId);
347             waitForBroadcast(Intent.ACTION_MEDIA_MOUNTED, userId);
348 
349             final CountDownLatch latch = new CountDownLatch(1);
350             InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() {
351                 @Override
352                 public void onReceive(Context context, Intent intent) {
353                     if (Intent.ACTION_USER_STOPPED.equals(intent.getAction()) && intent.getIntExtra(
354                             Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) {
355                         latch.countDown();
356                     }
357                 }
358             }, new IntentFilter(Intent.ACTION_USER_STOPPED));
359             final CountDownLatch switchLatch = new CountDownLatch(1);
360             registerUserSwitchObserver(switchLatch, null, startUser);
361             mRunner.resumeTiming();
362             Log.i(TAG, "Starting timer");
363 
364             mAm.switchUser(startUser);
365             waitForLatch("Failed to achieve ACTION_USER_STOPPED for user " + userId, latch);
366 
367             mRunner.pauseTiming();
368             Log.i(TAG, "Stopping timer");
369             try {
370                 switchLatch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
371             } catch (InterruptedException e) {
372                 Log.e(TAG, "Thread interrupted unexpectedly while waiting for switch.", e);
373             }
374             removeUser(userId);
375             mRunner.resumeTimingForNextIteration();
376         }
377     }
378 
379     /** Tests creating a new profile. */
380     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileCreate()381     public void managedProfileCreate() {
382         assumeTrue(mHasManagedUserFeature);
383 
384         while (mRunner.keepRunning()) {
385             Log.i(TAG, "Starting timer");
386             final int userId = createManagedProfile();
387 
388             mRunner.pauseTiming();
389             Log.i(TAG, "Stopping timer");
390             attestTrue("Failed creating profile " + userId, mUm.isManagedProfile(userId));
391             removeUser(userId);
392             mRunner.resumeTimingForNextIteration();
393         }
394     }
395 
396     /** Tests starting (unlocking) an uninitialized profile. */
397     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock()398     public void managedProfileUnlock() {
399         assumeTrue(mHasManagedUserFeature);
400 
401         while (mRunner.keepRunning()) {
402             mRunner.pauseTiming();
403             final int userId = createManagedProfile();
404             mRunner.resumeTiming();
405             Log.i(TAG, "Starting timer");
406 
407             startUserInBackgroundAndWaitForUnlock(userId);
408 
409             mRunner.pauseTiming();
410             Log.i(TAG, "Stopping timer");
411             removeUser(userId);
412             mRunner.resumeTimingForNextIteration();
413         }
414     }
415 
416     /** Tests starting (unlocking) a previously-started, but no-longer-running, profile. */
417     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_stopped()418     public void managedProfileUnlock_stopped() throws RemoteException {
419         assumeTrue(mHasManagedUserFeature);
420 
421         while (mRunner.keepRunning()) {
422             mRunner.pauseTiming();
423             final int userId = createManagedProfile();
424             // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
425             startUserInBackgroundAndWaitForUnlock(userId);
426             stopUser(userId, true);
427             mRunner.resumeTiming();
428             Log.i(TAG, "Starting timer");
429 
430             startUserInBackgroundAndWaitForUnlock(userId);
431 
432             mRunner.pauseTiming();
433             Log.i(TAG, "Stopping timer");
434             removeUser(userId);
435             mRunner.resumeTimingForNextIteration();
436         }
437     }
438 
439     /**
440      * Tests starting (unlocking) & launching an already-installed app in an uninitialized profile.
441      */
442     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlockAndLaunchApp()443     public void managedProfileUnlockAndLaunchApp() throws RemoteException {
444         assumeTrue(mHasManagedUserFeature);
445 
446         while (mRunner.keepRunning()) {
447             mRunner.pauseTiming();
448             final int userId = createManagedProfile();
449             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
450             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
451             mRunner.resumeTiming();
452             Log.i(TAG, "Starting timer");
453 
454             startUserInBackgroundAndWaitForUnlock(userId);
455             startApp(userId, DUMMY_PACKAGE_NAME);
456 
457             mRunner.pauseTiming();
458             Log.i(TAG, "Stopping timer");
459             removeUser(userId);
460             mRunner.resumeTimingForNextIteration();
461         }
462     }
463 
464     /**
465      * Tests starting (unlocking) and launching a previously-launched app
466      * in a previously-started, but no-longer-running, profile.
467      * A sort of combination of {@link #managedProfileUnlockAndLaunchApp} and
468      * {@link #managedProfileUnlock_stopped}}.
469      */
470     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlockAndLaunchApp_stopped()471     public void managedProfileUnlockAndLaunchApp_stopped() throws RemoteException {
472         assumeTrue(mHasManagedUserFeature);
473 
474         while (mRunner.keepRunning()) {
475             mRunner.pauseTiming();
476             final int userId = createManagedProfile();
477             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
478             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
479             startUserInBackgroundAndWaitForUnlock(userId);
480             startApp(userId, DUMMY_PACKAGE_NAME);
481             stopUser(userId, true);
482             SystemClock.sleep(1_000); // 1 second cool-down before re-starting profile.
483             mRunner.resumeTiming();
484             Log.i(TAG, "Starting timer");
485 
486             startUserInBackgroundAndWaitForUnlock(userId);
487             startApp(userId, DUMMY_PACKAGE_NAME);
488 
489             mRunner.pauseTiming();
490             Log.i(TAG, "Stopping timer");
491             removeUser(userId);
492             mRunner.resumeTimingForNextIteration();
493         }
494     }
495 
496     /** Tests installing a pre-existing app in an uninitialized profile. */
497     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileInstall()498     public void managedProfileInstall() throws RemoteException {
499         assumeTrue(mHasManagedUserFeature);
500 
501         while (mRunner.keepRunning()) {
502             mRunner.pauseTiming();
503             final int userId = createManagedProfile();
504             mRunner.resumeTiming();
505             Log.i(TAG, "Starting timer");
506 
507             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
508 
509             mRunner.pauseTiming();
510             Log.i(TAG, "Stopping timer");
511             removeUser(userId);
512             mRunner.resumeTimingForNextIteration();
513         }
514     }
515 
516     /**
517      * Tests creating a new profile, starting (unlocking) it, installing an app,
518      * and launching that app in it.
519      */
520     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileCreateUnlockInstallAndLaunchApp()521     public void managedProfileCreateUnlockInstallAndLaunchApp() throws RemoteException {
522         assumeTrue(mHasManagedUserFeature);
523 
524         while (mRunner.keepRunning()) {
525             mRunner.pauseTiming();
526             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
527             mRunner.resumeTiming();
528             Log.i(TAG, "Starting timer");
529 
530             final int userId = createManagedProfile();
531             startUserInBackgroundAndWaitForUnlock(userId);
532             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
533             startApp(userId, DUMMY_PACKAGE_NAME);
534 
535             mRunner.pauseTiming();
536             Log.i(TAG, "Stopping timer");
537             removeUser(userId);
538             mRunner.resumeTimingForNextIteration();
539         }
540     }
541 
542     /** Tests stopping a profile. */
543     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileStopped()544     public void managedProfileStopped() throws RemoteException {
545         assumeTrue(mHasManagedUserFeature);
546 
547         while (mRunner.keepRunning()) {
548             mRunner.pauseTiming();
549             final int userId = createManagedProfile();
550             startUserInBackgroundAndWaitForUnlock(userId);
551             waitForBroadcast(Intent.ACTION_MEDIA_MOUNTED, userId);
552 
553             mRunner.resumeTiming();
554             Log.i(TAG, "Starting timer");
555 
556             stopUser(userId, true);
557 
558             mRunner.pauseTiming();
559             Log.i(TAG, "Stopping timer");
560             removeUser(userId);
561             mRunner.resumeTimingForNextIteration();
562         }
563     }
564 
565     // TODO: This is just a POC. Do this properly and add more.
566     /** Tests starting (unlocking) a newly-created profile using the user-type-pkg-whitelist. */
567     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_usingWhitelist()568     public void managedProfileUnlock_usingWhitelist() {
569         assumeTrue(mHasManagedUserFeature);
570         final int origMode = getUserTypePackageWhitelistMode();
571         setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE
572                 | USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST);
573 
574         try {
575             while (mRunner.keepRunning()) {
576                 mRunner.pauseTiming();
577                 final int userId = createManagedProfile();
578                 mRunner.resumeTiming();
579                 Log.i(TAG, "Starting timer");
580 
581                 startUserInBackgroundAndWaitForUnlock(userId);
582 
583                 mRunner.pauseTiming();
584                 Log.i(TAG, "Stopping timer");
585                 removeUser(userId);
586                 mRunner.resumeTimingForNextIteration();
587             }
588         } finally {
589             setUserTypePackageWhitelistMode(origMode);
590         }
591     }
592     /** Tests starting (unlocking) a newly-created profile NOT using the user-type-pkg-whitelist. */
593     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
managedProfileUnlock_notUsingWhitelist()594     public void managedProfileUnlock_notUsingWhitelist() {
595         assumeTrue(mHasManagedUserFeature);
596         final int origMode = getUserTypePackageWhitelistMode();
597         setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE);
598 
599         try {
600             while (mRunner.keepRunning()) {
601                 mRunner.pauseTiming();
602                 final int userId = createManagedProfile();
603                 mRunner.resumeTiming();
604                 Log.i(TAG, "Starting timer");
605 
606                 startUserInBackgroundAndWaitForUnlock(userId);
607 
608                 mRunner.pauseTiming();
609                 Log.i(TAG, "Stopping timer");
610                 removeUser(userId);
611                 mRunner.resumeTimingForNextIteration();
612             }
613         } finally {
614             setUserTypePackageWhitelistMode(origMode);
615         }
616     }
617 
618     /** Creates a new user, returning its userId. */
createUserNoFlags()619     private int createUserNoFlags() {
620         return createUserWithFlags(/* flags= */ 0);
621     }
622 
623     /** Creates a new user with the given flags, returning its userId. */
createUserWithFlags(int flags)624     private int createUserWithFlags(int flags) {
625         int userId = mUm.createUser(TEST_USER_NAME, flags).id;
626         mUsersToRemove.add(userId);
627         return userId;
628     }
629 
630     /** Creates a managed (work) profile under the current user, returning its userId. */
createManagedProfile()631     private int createManagedProfile() {
632         final UserInfo userInfo = mUm.createProfileForUser(TEST_USER_NAME,
633                 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, mAm.getCurrentUser());
634         attestFalse("Creating managed profile failed. Most likely there is "
635                 + "already a pre-existing profile on the device.", userInfo == null);
636         mUsersToRemove.add(userInfo.id);
637         return userInfo.id;
638     }
639 
640     /**
641      * Start user in background and wait for it to unlock by waiting for
642      * UserState.mUnlockProgress.finish().
643      * <p> To start in foreground instead, see {@link #switchUser(int)}.
644      * <p> This should always be used for profiles since profiles cannot be started in foreground.
645      */
startUserInBackgroundAndWaitForUnlock(int userId)646     private void startUserInBackgroundAndWaitForUnlock(int userId) {
647         final ProgressWaiter waiter = new ProgressWaiter();
648         boolean success = false;
649         try {
650             mIam.startUserInBackgroundWithListener(userId, waiter);
651             success = waiter.waitForFinish(TIMEOUT_IN_SECOND);
652         } catch (RemoteException e) {
653             Log.e(TAG, "startUserInBackgroundAndWaitForUnlock failed", e);
654         }
655         attestTrue("Failed to start user " + userId + " in background.", success);
656     }
657 
658     /** Starts the given user in the foreground. */
switchUser(int userId)659     private void switchUser(int userId) throws RemoteException {
660         boolean success = switchUserNoCheck(userId);
661         attestTrue("Failed to properly switch to user " + userId, success);
662     }
663 
664     /**
665      * Starts the given user in the foreground.
666      * Returns true if successful. Does not fail the test if unsuccessful.
667      * If lack of success should fail the test, use {@link #switchUser(int)} instead.
668      */
switchUserNoCheck(int userId)669     private boolean switchUserNoCheck(int userId) throws RemoteException {
670         final CountDownLatch latch = new CountDownLatch(1);
671         registerUserSwitchObserver(latch, null, userId);
672         mAm.switchUser(userId);
673         try {
674             return latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
675         } catch (InterruptedException e) {
676             Log.e(TAG, "Thread interrupted unexpectedly.", e);
677             return false;
678         }
679     }
680 
stopUser(int userId, boolean force)681     private void stopUser(int userId, boolean force) throws RemoteException {
682         final CountDownLatch latch = new CountDownLatch(1);
683         mIam.stopUser(userId, force /* force */, new IStopUserCallback.Stub() {
684             @Override
685             public void userStopped(int userId) throws RemoteException {
686                 latch.countDown();
687             }
688 
689             @Override
690             public void userStopAborted(int userId) throws RemoteException {
691             }
692         });
693         waitForLatch("Failed to properly stop user " + userId, latch);
694     }
695 
696     /**
697      * Creates a user and waits for its ACTION_USER_UNLOCKED.
698      * Then switches to back to the original user and waits for its switchUser() to finish.
699      *
700      * @param stopNewUser whether to stop the new user after switching to otherUser.
701      * @return userId of the newly created user.
702      */
initializeNewUserAndSwitchBack(boolean stopNewUser)703     private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws RemoteException {
704         final int origUser = mAm.getCurrentUser();
705         // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED
706         final int testUser = createUserNoFlags();
707         mAm.switchUser(testUser);
708         waitForBroadcast(Intent.ACTION_USER_UNLOCKED, testUser);
709         waitForBroadcast(Intent.ACTION_MEDIA_MOUNTED, testUser);
710 
711         // Second, switch back to origUser, waiting merely for switchUser() to finish
712         switchUser(origUser);
713         attestTrue("Didn't switch back to user, " + origUser, origUser == mAm.getCurrentUser());
714 
715         if (stopNewUser) {
716             stopUser(testUser, true);
717             attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
718         }
719 
720         return testUser;
721     }
722 
723     /**
724      * Installs the given package in the given user.
725      */
installPreexistingApp(int userId, String packageName)726     private void installPreexistingApp(int userId, String packageName) throws RemoteException {
727         final CountDownLatch latch = new CountDownLatch(1);
728 
729         final IntentSender sender = new IntentSender((IIntentSender) new IIntentSender.Stub() {
730             @Override
731             public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
732                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
733                 latch.countDown();
734             }
735         });
736 
737         final IPackageInstaller installer = AppGlobals.getPackageManager().getPackageInstaller();
738         installer.installExistingPackage(packageName,
739                 PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
740                 PackageManager.INSTALL_REASON_UNKNOWN, sender, userId, null);
741 
742         waitForLatch("Failed to install app " + packageName + " on user " + userId, latch);
743     }
744 
745     /**
746      * Launches the given package in the given user.
747      * Make sure the keyguard has been dismissed prior to calling.
748      */
startApp(int userId, String packageName)749     private void startApp(int userId, String packageName) throws RemoteException {
750         final Context context = InstrumentationRegistry.getContext();
751         final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null,
752                 context.getPackageName(), context.getAttributionTag(),
753                 context.getPackageManager().getLaunchIntentForPackage(packageName), null, null,
754                 null, 0, 0, null, null, userId);
755         attestTrue("User " + userId + " failed to start " + packageName,
756                 result.result == ActivityManager.START_SUCCESS);
757     }
758 
registerUserSwitchObserver(final CountDownLatch switchLatch, final CountDownLatch bootCompleteLatch, final int userId)759     private void registerUserSwitchObserver(final CountDownLatch switchLatch,
760             final CountDownLatch bootCompleteLatch, final int userId) throws RemoteException {
761         ActivityManager.getService().registerUserSwitchObserver(
762                 new UserSwitchObserver() {
763                     @Override
764                     public void onUserSwitchComplete(int newUserId) throws RemoteException {
765                         if (switchLatch != null && userId == newUserId) {
766                             switchLatch.countDown();
767                         }
768                     }
769 
770                     @Override
771                     public void onLockedBootComplete(int newUserId) {
772                         if (bootCompleteLatch != null && userId == newUserId) {
773                             bootCompleteLatch.countDown();
774                         }
775                     }
776                 }, TAG);
777     }
778 
779     private class ProgressWaiter extends IProgressListener.Stub {
780         private final CountDownLatch mFinishedLatch = new CountDownLatch(1);
781 
782         @Override
onStarted(int id, Bundle extras)783         public void onStarted(int id, Bundle extras) {}
784 
785         @Override
onProgress(int id, int progress, Bundle extras)786         public void onProgress(int id, int progress, Bundle extras) {}
787 
788         @Override
onFinished(int id, Bundle extras)789         public void onFinished(int id, Bundle extras) {
790             mFinishedLatch.countDown();
791         }
792 
waitForFinish(long timeoutSecs)793         public boolean waitForFinish(long timeoutSecs) {
794             try {
795                 return mFinishedLatch.await(timeoutSecs, TimeUnit.SECONDS);
796             } catch (InterruptedException e) {
797                 Log.e(TAG, "Thread interrupted unexpectedly.", e);
798                 return false;
799             }
800         }
801     }
802 
803     /**
804      * Waits TIMEOUT_IN_SECOND for the broadcast to be received, otherwise declares the given error.
805      * It only works for the broadcasts provided in {@link #mBroadcastWaiter}'s instantiation above.
806      * @param action action of the broadcast, i.e. {@link Intent#ACTION_USER_STARTED}
807      * @param userId sendingUserId of the broadcast. See {@link BroadcastReceiver#getSendingUserId}
808      */
waitForBroadcast(String action, int userId)809     private void waitForBroadcast(String action, int userId) {
810         attestTrue("Failed to achieve " + action + " for user " + userId,
811                 mBroadcastWaiter.waitActionForUser(action, userId));
812     }
813 
814     /** Waits TIMEOUT_IN_SECOND for the latch to complete, otherwise declares the given error. */
waitForLatch(String errMsg, CountDownLatch latch)815     private void waitForLatch(String errMsg, CountDownLatch latch) {
816         boolean success = false;
817         try {
818             success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
819         } catch (InterruptedException e) {
820             Log.e(TAG, "Thread interrupted unexpectedly.", e);
821         }
822         attestTrue(errMsg, success);
823     }
824 
825     /** Gets the PACKAGE_WHITELIST_MODE_PROP System Property. */
getUserTypePackageWhitelistMode()826     private int getUserTypePackageWhitelistMode() {
827         return SystemProperties.getInt(PACKAGE_WHITELIST_MODE_PROP,
828                 USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT);
829     }
830 
831     /** Sets the PACKAGE_WHITELIST_MODE_PROP System Property to the given value. */
setUserTypePackageWhitelistMode(int mode)832     private void setUserTypePackageWhitelistMode(int mode) {
833         String result = ShellHelper.runShellCommand(
834                 String.format("setprop %s %d", PACKAGE_WHITELIST_MODE_PROP, mode));
835         attestFalse("Failed to set sysprop " + PACKAGE_WHITELIST_MODE_PROP + ": " + result,
836                 result != null && result.contains("Failed"));
837     }
838 
removeUser(int userId)839     private void removeUser(int userId) {
840         if (mBroadcastWaiter.hasActionBeenReceivedForUser(Intent.ACTION_USER_STARTED, userId)) {
841             mBroadcastWaiter.waitActionForUserIfNotReceivedYet(Intent.ACTION_MEDIA_MOUNTED, userId);
842         }
843         try {
844             mUm.removeUser(userId);
845             final long startTime = System.currentTimeMillis();
846             final long timeoutInMs = TIMEOUT_IN_SECOND * 1000;
847             while (mUm.getUserInfo(userId) != null &&
848                     System.currentTimeMillis() - startTime < timeoutInMs) {
849                 TimeUnit.MILLISECONDS.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
850             }
851         } catch (InterruptedException e) {
852             Thread.currentThread().interrupt();
853         } catch (Exception e) {
854             // Ignore
855         }
856         if (mUm.getUserInfo(userId) != null) {
857             mUsersToRemove.add(userId);
858         }
859     }
860 
removeAnyPreviousTestUsers()861     private void removeAnyPreviousTestUsers() {
862         for (UserInfo user : mUm.getUsers()) {
863             if (TEST_USER_NAME.equals(user.name)) {
864                 Log.i(TAG, "Found previous test user " + user.id + ". Removing it.");
865                 if (mAm.getCurrentUser() == user.id) {
866                     try {
867                         switchUserNoCheck(UserHandle.USER_SYSTEM);
868                     } catch (RemoteException e) {
869                         Log.e(TAG, "Failed to correctly switch to system user", e);
870                     }
871                 }
872                 mUm.removeUser(user.id);
873             }
874         }
875     }
876 
attestTrue(@onNull String message, boolean assertion)877     private void attestTrue(@NonNull String message, boolean assertion) {
878         if (!assertion) {
879             Log.e(TAG, "Test failed on iteration #" + mRunner.getIteration() + ": " + message);
880             mRunner.markAsFailed(new AssertionError(message));
881         }
882     }
883 
attestFalse(@onNull String message, boolean assertion)884     private void attestFalse(@NonNull String message, boolean assertion) {
885         attestTrue(message, !assertion);
886     }
887 }
888