Merge "Add private profile user lifecycle tests" into main
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 762e2af..0750c8d 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -145,7 +145,9 @@
                 Intent.ACTION_USER_STARTED,
                 Intent.ACTION_MEDIA_MOUNTED,
                 Intent.ACTION_USER_UNLOCKED,
-                Intent.ACTION_USER_STOPPED);
+                Intent.ACTION_USER_STOPPED,
+                Intent.ACTION_PROFILE_AVAILABLE,
+                Intent.ACTION_PROFILE_UNAVAILABLE);
         mUserSwitchWaiter = new UserSwitchWaiter(TAG, TIMEOUT_IN_SECOND);
         removeAnyPreviousTestUsers();
         if (mAm.getCurrentUser() != UserHandle.USER_SYSTEM) {
@@ -1230,6 +1232,255 @@
         }
     }
 
+    /** Tests creating a private profile. */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void createPrivateProfile() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            Log.i(TAG, "Starting timer");
+
+            final int userId = createPrivateProfileUser();
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            waitCoolDownPeriod();
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests creating and starting a newly created private profile. This test waits for the
+     * {@link Intent.ACTION_USER_STARTED} to be received.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void createAndStartPrivateProfile_realistic() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            Log.i(TAG, "Starting timer");
+            final int userId = createPrivateProfileUser();
+
+            // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until
+            // ACTION_USER_STARTED.
+            runThenWaitForBroadcasts(userId, () -> {
+                mIam.startUserInBackground(userId);
+            }, Intent.ACTION_USER_STARTED);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            waitCoolDownPeriod();
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /** Tests for stopping the private profile. */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileStopped() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            runThenWaitForBroadcasts(userId, () -> {
+                startUserInBackgroundAndWaitForUnlock(userId);
+            }, Intent.ACTION_MEDIA_MOUNTED);
+
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            stopUser(userId);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests unlocking a newly-created private profile using the
+     * {@link UserManager#requestQuietModeEnabled} api.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileUnlock() throws RemoteException {
+
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            startUserInBackgroundAndWaitForUnlock(userId);
+            mUm.requestQuietModeEnabled(true, UserHandle.of(userId));
+            waitCoolDownPeriod();
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            mUm.requestQuietModeEnabled(false, UserHandle.of(userId));
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests unlocking a newly-created private profile using the
+     * {@link UserManager#requestQuietModeEnabled} api and waiting for the
+     * {@link Intent.ACTION_PROFILE_AVAILABLE} to be received.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileUnlock_realistic() throws RemoteException {
+
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            startUserInBackgroundAndWaitForUnlock(userId);
+            mUm.requestQuietModeEnabled(true, UserHandle.of(userId));
+            waitCoolDownPeriod();
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            runThenWaitForBroadcasts(userId, () -> {
+                mUm.requestQuietModeEnabled(false, UserHandle.of(userId));
+            }, Intent.ACTION_PROFILE_AVAILABLE);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests locking a newly-created private profile using the
+     * {@link UserManager#requestQuietModeEnabled} api.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileLock() throws RemoteException {
+
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            startUserInBackgroundAndWaitForUnlock(userId);
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            mUm.requestQuietModeEnabled(true, UserHandle.of(userId));
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests locking a newly-created private profile using the
+     * {@link UserManager#requestQuietModeEnabled} api and waiting for the
+     * {@link Intent.ACTION_PROFILE_UNAVAILABLE} to be received.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileLock_realistic() throws RemoteException {
+
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            startUserInBackgroundAndWaitForUnlock(userId);
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            runThenWaitForBroadcasts(userId, () -> {
+                mUm.requestQuietModeEnabled(true, UserHandle.of(userId));
+            }, Intent.ACTION_PROFILE_UNAVAILABLE);
+
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /** Tests removing a newly-created private profile */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileRemove() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+            removeUser(userId);
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /** Tests installing a pre-existing app in a private profile. */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileInstall() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            startUserInBackgroundAndWaitForUnlock(userId);
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            waitCoolDownPeriod();
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests creating a new private profile, starting it, installing an app, and launching that app
+     * in it.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileCreateStartInstallAndLaunchApp() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            final int userId = createPrivateProfileUser();
+            startUserInBackgroundAndWaitForUnlock(userId);
+            installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
+            startApp(userId, DUMMY_PACKAGE_NAME);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            waitCoolDownPeriod();
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
+    /**
+     * Tests starting & launching an already-installed app in a private profile.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void privateProfileStartAndLaunchApp() throws RemoteException {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createPrivateProfileUser();
+            WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
+            installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            startUserInBackgroundAndWaitForUnlock(userId);
+            startApp(userId, DUMMY_PACKAGE_NAME);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            removeUser(userId);
+            waitCoolDownPeriod();
+            mRunner.resumeTimingForNextIteration();
+        }
+    }
+
     /** Creates a new user, returning its userId. */
     private int createUserNoFlags() {
         return createUserWithFlags(/* flags= */ 0);
@@ -1252,6 +1503,18 @@
         return userInfo.id;
     }
 
+    /** Creates a private profile under the current user, returning its userId. */
+    private int createPrivateProfileUser() {
+        final UserInfo userInfo = mUm.createProfileForUser(TEST_USER_NAME,
+                UserManager.USER_TYPE_PROFILE_PRIVATE, /* flags */ 0, mAm.getCurrentUser());
+        attestFalse(
+                "Creating a private profile failed. Most likely there is already a pre-existing "
+                        + "private profile on the device.",
+                userInfo == null);
+        mUsersToRemove.add(userInfo.id);
+        return userInfo.id;
+    }
+
     /**
      * Start user in background and wait for it to unlock by waiting for
      * UserState.mUnlockProgress.finish().