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