diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java index 163ef4cd3ec48..b1c42a92af9c2 100644 --- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java @@ -39,6 +39,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.IProgressListener; import android.os.RemoteException; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -153,7 +154,7 @@ public class UserLifecycleTests { } @Test - public void createAndStartUser() throws Exception { + public void createAndStartUser() throws RemoteException { while (mRunner.keepRunning()) { final int userId = createUserNoFlags(); @@ -162,7 +163,7 @@ public class UserLifecycleTests { // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until // ACTION_USER_STARTED. mIam.startUserInBackground(userId); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to achieve ACTION_USER_STARTED for user " + userId, latch); mRunner.pauseTiming(); removeUser(userId); @@ -174,7 +175,7 @@ public class UserLifecycleTests { * Measures the time until ACTION_USER_STARTED is received. */ @Test - public void startUser() throws Exception { + public void startUser() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createUserNoFlags(); @@ -183,7 +184,7 @@ public class UserLifecycleTests { mRunner.resumeTiming(); mIam.startUserInBackground(userId); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to achieve ACTION_USER_STARTED for user " + userId, latch); mRunner.pauseTiming(); removeUser(userId); @@ -195,7 +196,7 @@ public class UserLifecycleTests { * Measures the time until unlock listener is triggered and user is unlocked. */ @Test - public void startAndUnlockUser() throws Exception { + public void startAndUnlockUser() { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createUserNoFlags(); @@ -210,10 +211,8 @@ public class UserLifecycleTests { } } - - @Test - public void switchUser() throws Exception { + public void switchUser() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); @@ -223,7 +222,7 @@ public class UserLifecycleTests { switchUser(userId); mRunner.pauseTiming(); - switchUser(startUser); + switchUserNoCheck(startUser); removeUser(userId); mRunner.resumeTiming(); } @@ -231,7 +230,7 @@ public class UserLifecycleTests { /** Tests switching to an already-created, but no-longer-running, user. */ @Test - public void switchUser_stopped() throws Exception { + public void switchUser_stopped() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); @@ -241,11 +240,11 @@ public class UserLifecycleTests { mRunner.resumeTiming(); mAm.switchUser(testUser); - boolean success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to achieve 2nd ACTION_USER_UNLOCKED for user " + testUser, latch); + mRunner.pauseTiming(); - attestTrue("Failed to achieve 2nd ACTION_USER_UNLOCKED for user " + testUser, success); - switchUser(startUser); + switchUserNoCheck(startUser); removeUser(testUser); mRunner.resumeTiming(); } @@ -253,7 +252,7 @@ public class UserLifecycleTests { /** Tests switching to an already-created already-running non-owner user. */ @Test - public void switchUser_running() throws Exception { + public void switchUser_running() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); @@ -263,22 +262,21 @@ public class UserLifecycleTests { switchUser(testUser); mRunner.pauseTiming(); - attestTrue("Failed to switch to user " + testUser, mAm.isUserRunning(testUser)); - switchUser(startUser); + switchUserNoCheck(startUser); removeUser(testUser); mRunner.resumeTiming(); } } @Test - public void stopUser() throws Exception { + public void stopUser() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createUserNoFlags(); final CountDownLatch latch = new CountDownLatch(1); registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId); mIam.startUserInBackground(userId); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to achieve ACTION_USER_STARTED for user " + userId, latch); mRunner.resumeTiming(); stopUser(userId, false); @@ -290,7 +288,7 @@ public class UserLifecycleTests { } @Test - public void lockedBootCompleted() throws Exception { + public void lockedBootCompleted() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); @@ -300,17 +298,17 @@ public class UserLifecycleTests { mRunner.resumeTiming(); mAm.switchUser(userId); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to achieve onLockedBootComplete for user " + userId, latch); mRunner.pauseTiming(); - switchUser(startUser); + switchUserNoCheck(startUser); removeUser(userId); mRunner.resumeTiming(); } } @Test - public void ephemeralUserStopped() throws Exception { + public void ephemeralUserStopped() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); @@ -331,10 +329,14 @@ public class UserLifecycleTests { mRunner.resumeTiming(); mAm.switchUser(startUser); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to achieve ACTION_USER_STOPPED for user " + userId, latch); mRunner.pauseTiming(); - switchLatch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + try { + switchLatch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Log.e(TAG, "Thread interrupted unexpectedly while waiting for switch.", e); + } removeUser(userId); mRunner.resumeTiming(); } @@ -342,7 +344,7 @@ public class UserLifecycleTests { /** Tests creating a new profile. */ @Test - public void managedProfileCreate() throws Exception { + public void managedProfileCreate() { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -357,7 +359,7 @@ public class UserLifecycleTests { /** Tests starting (unlocking) a newly-created profile. */ @Test - public void managedProfileUnlock() throws Exception { + public void managedProfileUnlock() { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -375,7 +377,7 @@ public class UserLifecycleTests { /** Tests starting (unlocking) an already-created, but no-longer-running, profile. */ @Test - public void managedProfileUnlock_stopped() throws Exception { + public void managedProfileUnlock_stopped() throws RemoteException { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -398,7 +400,7 @@ public class UserLifecycleTests { * Tests starting (unlocking) and launching an already-installed app in a newly-created profile. */ @Test - public void managedProfileUnlockAndLaunchApp() throws Exception { + public void managedProfileUnlockAndLaunchApp() throws RemoteException { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -424,7 +426,7 @@ public class UserLifecycleTests { * {@link #managedProfileUnlock_stopped}}. */ @Test - public void managedProfileUnlockAndLaunchApp_stopped() throws Exception { + public void managedProfileUnlockAndLaunchApp_stopped() throws RemoteException { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -435,7 +437,7 @@ public class UserLifecycleTests { startUserInBackgroundAndWaitForUnlock(userId); startApp(userId, DUMMY_PACKAGE_NAME); stopUser(userId, true); - TimeUnit.SECONDS.sleep(1); // Brief cool-down before re-starting profile. + SystemClock.sleep(1_000); // 1 second cool-down before re-starting profile. mRunner.resumeTiming(); startUserInBackgroundAndWaitForUnlock(userId); @@ -449,7 +451,7 @@ public class UserLifecycleTests { /** Tests installing a pre-existing app in a newly-created profile. */ @Test - public void managedProfileInstall() throws Exception { + public void managedProfileInstall() throws RemoteException { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -470,7 +472,7 @@ public class UserLifecycleTests { * and launching that app in it. */ @Test - public void managedProfileCreateUnlockInstallAndLaunchApp() throws Exception { + public void managedProfileCreateUnlockInstallAndLaunchApp() throws RemoteException { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -491,7 +493,7 @@ public class UserLifecycleTests { /** Tests stopping a profile. */ @Test - public void managedProfileStopped() throws Exception { + public void managedProfileStopped() throws RemoteException { assumeTrue(mHasManagedUserFeature); while (mRunner.keepRunning()) { @@ -511,7 +513,7 @@ public class UserLifecycleTests { // TODO: This is just a POC. Do this properly and add more. /** Tests starting (unlocking) a newly-created profile using the user-type-pkg-whitelist. */ @Test - public void managedProfileUnlock_usingWhitelist() throws Exception { + public void managedProfileUnlock_usingWhitelist() { assumeTrue(mHasManagedUserFeature); final int origMode = getUserTypePackageWhitelistMode(); setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE @@ -535,7 +537,7 @@ public class UserLifecycleTests { } /** Tests starting (unlocking) a newly-created profile NOT using the user-type-pkg-whitelist. */ @Test - public void managedProfileUnlock_notUsingWhitelist() throws Exception { + public void managedProfileUnlock_notUsingWhitelist() { assumeTrue(mHasManagedUserFeature); final int origMode = getUserTypePackageWhitelistMode(); setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE); @@ -573,10 +575,8 @@ public class UserLifecycleTests { private int createManagedProfile() { final UserInfo userInfo = mUm.createProfileForUser(TEST_USER_NAME, UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, mAm.getCurrentUser()); - if (userInfo == null) { - throw new IllegalStateException("Creating managed profile failed. Most likely there is " - + "already a pre-existing profile on the device."); - } + attestFalse("Creating managed profile failed. Most likely there is " + + "already a pre-existing profile on the device.", userInfo == null); mUsersToRemove.add(userInfo.id); return userInfo.id; } @@ -589,24 +589,40 @@ public class UserLifecycleTests { */ private void startUserInBackgroundAndWaitForUnlock(int userId) { final ProgressWaiter waiter = new ProgressWaiter(); + boolean success = false; try { mIam.startUserInBackgroundWithListener(userId, waiter); - boolean success = waiter.waitForFinish(TIMEOUT_IN_SECOND); - attestTrue("Failed to start user " + userId + " in background.", success); + success = waiter.waitForFinish(TIMEOUT_IN_SECOND); } catch (RemoteException e) { Log.e(TAG, "startUserInBackgroundAndWaitForUnlock failed", e); } + attestTrue("Failed to start user " + userId + " in background.", success); } /** Starts the given user in the foreground. */ - private void switchUser(int userId) throws Exception { + private void switchUser(int userId) throws RemoteException { + boolean success = switchUserNoCheck(userId); + attestTrue("Failed to properly switch to user " + userId, success); + } + + /** + * Starts the given user in the foreground. + * Returns true if successful. Does not fail the test if unsuccessful. + * If lack of success should fail the test, use {@link #switchUser(int)} instead. + */ + private boolean switchUserNoCheck(int userId) throws RemoteException { final CountDownLatch latch = new CountDownLatch(1); registerUserSwitchObserver(latch, null, userId); mAm.switchUser(userId); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + try { + return latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Log.e(TAG, "Thread interrupted unexpectedly.", e); + return false; + } } - private void stopUser(int userId, boolean force) throws Exception { + private void stopUser(int userId, boolean force) throws RemoteException { final CountDownLatch latch = new CountDownLatch(1); mIam.stopUser(userId, force /* force */, new IStopUserCallback.Stub() { @Override @@ -618,7 +634,7 @@ public class UserLifecycleTests { public void userStopAborted(int userId) throws RemoteException { } }); - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + waitForLatch("Failed to properly stop user " + userId, latch); } /** @@ -628,15 +644,14 @@ public class UserLifecycleTests { * @param stopNewUser whether to stop the new user after switching to otherUser. * @return userId of the newly created user. */ - private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws Exception { + private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws RemoteException { final int origUser = mAm.getCurrentUser(); // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED final int testUser = createUserNoFlags(); final CountDownLatch latch1 = new CountDownLatch(1); registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, testUser); mAm.switchUser(testUser); - attestTrue("Failed to achieve initial ACTION_USER_UNLOCKED for user " + testUser, - latch1.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS)); + waitForLatch("Failed to achieve initial ACTION_USER_UNLOCKED for user " + testUser, latch1); // Second, switch back to origUser, waiting merely for switchUser() to finish switchUser(origUser); @@ -669,11 +684,7 @@ public class UserLifecycleTests { PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, PackageManager.INSTALL_REASON_UNKNOWN, sender, userId, null); - try { - latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Thread interrupted unexpectedly.", e); - } + waitForLatch("Failed to install app " + packageName + " on user " + userId, latch); } /** @@ -691,7 +702,7 @@ public class UserLifecycleTests { } private void registerUserSwitchObserver(final CountDownLatch switchLatch, - final CountDownLatch bootCompleteLatch, final int userId) throws Exception { + final CountDownLatch bootCompleteLatch, final int userId) throws RemoteException { ActivityManager.getService().registerUserSwitchObserver( new UserSwitchObserver() { @Override @@ -747,6 +758,17 @@ public class UserLifecycleTests { } } + /** Waits TIMEOUT_IN_SECOND for the latch to complete, otherwise declares the given error. */ + private void waitForLatch(String errMsg, CountDownLatch latch) { + boolean success = false; + try { + success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Log.e(TAG, "Thread interrupted unexpectedly.", e); + } + attestTrue(errMsg, success); + } + /** Gets the PACKAGE_WHITELIST_MODE_PROP System Property. */ private int getUserTypePackageWhitelistMode() { return SystemProperties.getInt(PACKAGE_WHITELIST_MODE_PROP, @@ -786,8 +808,8 @@ public class UserLifecycleTests { Log.i(TAG, "Found previous test user " + user.id + ". Removing it."); if (mAm.getCurrentUser() == user.id) { try { - switchUser(UserHandle.USER_SYSTEM); - } catch (Exception e) { + switchUserNoCheck(UserHandle.USER_SYSTEM); + } catch (RemoteException e) { Log.e(TAG, "Failed to correctly switch to system user", e); } }