Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1226ec46 authored by Adam Bookatz's avatar Adam Bookatz
Browse files

UserLifecycleTests: wait on storage before restart

When a user is stopped shortly after having started, the timing
results depend heavily on whether StorageManagerService had managed to
forge its connections yet. If it didn't, then stopping takes an
unrealistically short time. If it did, but is still in the process of
dealing with them, then stopping takes an unrealistically long time.

The solution is, for all appliable tests, to wait until storage is ready
before proceeding to stop or switch the user.

Also, some javadoc comments are added and clarified.

Bug: 169449457
Test: atest MultiUserPerfTests:android.multiuser.UserLifecycleTests
Change-Id: Ide848685637abac43488c8d89a3d6f6567c7deca
parent afb99dd5
Loading
Loading
Loading
Loading
+62 −10
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.app.IStopUserCallback;
import android.app.UserSwitchObserver;
import android.app.WaitResult;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -142,6 +143,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests creating a new user. */
    @Test
    public void createUser() {
        while (mRunner.keepRunning()) {
@@ -155,6 +157,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests creating and starting a new user. */
    @Test
    public void createAndStartUser() throws RemoteException {
        while (mRunner.keepRunning()) {
@@ -176,6 +179,7 @@ public class UserLifecycleTests {
    }

    /**
     * Tests starting an uninitialized user.
     * Measures the time until ACTION_USER_STARTED is received.
     */
    @Test
@@ -199,6 +203,7 @@ public class UserLifecycleTests {
    }

    /**
     * Tests starting & unlocking an uninitialized user.
     * Measures the time until unlock listener is triggered and user is unlocked.
     */
    @Test
@@ -219,6 +224,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests switching to an uninitialized user. */
    @Test
    public void switchUser() throws RemoteException {
        while (mRunner.keepRunning()) {
@@ -238,7 +244,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests switching to an already-created, but no-longer-running, user. */
    /** Tests switching to a previously-started, but no-longer-running, user. */
    @Test
    public void switchUser_stopped() throws RemoteException {
        while (mRunner.keepRunning()) {
@@ -262,7 +268,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests switching to an already-created already-running non-owner user. */
    /** Tests switching to an already-created already-running non-owner background user. */
    @Test
    public void switchUser_running() throws RemoteException {
        while (mRunner.keepRunning()) {
@@ -282,15 +288,19 @@ public class UserLifecycleTests {
        }
    }

    /** Tests stopping a background user. */
    @Test
    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);
            final CountDownLatch latch1 = new CountDownLatch(1);
            final CountDownLatch latch2 = new CountDownLatch(1);
            registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch1, userId);
            registerMediaBroadcastReceiver(latch2, userId);
            mIam.startUserInBackground(userId);
            waitForLatch("Failed to achieve ACTION_USER_STARTED for user " + userId, latch);
            waitForLatch("Failed to achieve ACTION_USER_STARTED for user " + userId, latch1);
            waitForLatch("Failed to achieve ACTION_MEDIA_MOUNTED for user " + userId, latch2);
            Log.i(TAG, "Starting timer");
            mRunner.resumeTiming();

@@ -303,6 +313,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests reaching LOOKED_BOOT_COMPLETE when switching to uninitialized user. */
    @Test
    public void lockedBootCompleted() throws RemoteException {
        while (mRunner.keepRunning()) {
@@ -325,13 +336,17 @@ public class UserLifecycleTests {
        }
    }

    /** Tests stopping an ephemeral foreground user. */
    @Test
    public void ephemeralUserStopped() throws RemoteException {
        while (mRunner.keepRunning()) {
            mRunner.pauseTiming();
            final int startUser = mAm.getCurrentUser();
            final int userId = createUserWithFlags(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
            final CountDownLatch prelatch = new CountDownLatch(1);
            registerMediaBroadcastReceiver(prelatch, userId);
            switchUser(userId);
            waitForLatch("Failed to achieve ACTION_MEDIA_MOUNTED for user " + userId, prelatch);
            final CountDownLatch latch = new CountDownLatch(1);
            InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() {
                @Override
@@ -379,7 +394,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests starting (unlocking) a newly-created profile. */
    /** Tests starting (unlocking) an uninitialized profile. */
    @Test
    public void managedProfileUnlock() {
        assumeTrue(mHasManagedUserFeature);
@@ -399,7 +414,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests starting (unlocking) an already-created, but no-longer-running, profile. */
    /** Tests starting (unlocking) a previously-started, but no-longer-running, profile. */
    @Test
    public void managedProfileUnlock_stopped() throws RemoteException {
        assumeTrue(mHasManagedUserFeature);
@@ -423,7 +438,7 @@ public class UserLifecycleTests {
    }

    /**
     * Tests starting (unlocking) and launching an already-installed app in a newly-created profile.
     * Tests starting (unlocking) & launching an already-installed app in an uninitialized profile.
     */
    @Test
    public void managedProfileUnlockAndLaunchApp() throws RemoteException {
@@ -449,7 +464,7 @@ public class UserLifecycleTests {

    /**
     * Tests starting (unlocking) and launching a previously-launched app
     * in an already-created, but no-longer-running, profile.
     * in a previously-started, but no-longer-running, profile.
     * A sort of combination of {@link #managedProfileUnlockAndLaunchApp} and
     * {@link #managedProfileUnlock_stopped}}.
     */
@@ -479,7 +494,7 @@ public class UserLifecycleTests {
        }
    }

    /** Tests installing a pre-existing app in a newly-created profile. */
    /** Tests installing a pre-existing app in an uninitialized profile. */
    @Test
    public void managedProfileInstall() throws RemoteException {
        assumeTrue(mHasManagedUserFeature);
@@ -533,7 +548,10 @@ public class UserLifecycleTests {
        while (mRunner.keepRunning()) {
            mRunner.pauseTiming();
            final int userId = createManagedProfile();
            final CountDownLatch prelatch = new CountDownLatch(1);
            registerMediaBroadcastReceiver(prelatch, userId);
            startUserInBackgroundAndWaitForUnlock(userId);
            waitForLatch("Failed to achieve ACTION_MEDIA_MOUNTED for user " + userId, prelatch);
            Log.i(TAG, "Starting timer");
            mRunner.resumeTiming();

@@ -689,9 +707,12 @@ public class UserLifecycleTests {
        // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED
        final int testUser = createUserNoFlags();
        final CountDownLatch latch1 = new CountDownLatch(1);
        final CountDownLatch latch2 = new CountDownLatch(1);
        registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, testUser);
        registerMediaBroadcastReceiver(latch2, testUser);
        mAm.switchUser(testUser);
        waitForLatch("Failed to achieve initial ACTION_USER_UNLOCKED for user " + testUser, latch1);
        waitForLatch("Failed to achieve initial ACTION_MEDIA_MOUNTED for user " + testUser, latch2);

        // Second, switch back to origUser, waiting merely for switchUser() to finish
        switchUser(origUser);
@@ -774,6 +795,37 @@ public class UserLifecycleTests {
        }, UserHandle.of(userId), new IntentFilter(action), null, null);
    }

    /**
     * Register for a broadcast to indicate that Storage has processed the given user.
     * Without this as part of setup, for tests dealing with already-switched users, Storage may not
     * have finished, making the resulting processing inconsistent.
     *
     * Strictly speaking, the receiver should always be unregistered afterwards, but we don't
     * necessarily bother since receivers from failed tests will be removed on test uninstallation.
     */
    private void registerMediaBroadcastReceiver(final CountDownLatch latch, final int userId) {
        final String action = Intent.ACTION_MEDIA_MOUNTED;

        final IntentFilter filter = new IntentFilter();
        filter.addAction(action);
        filter.addDataScheme(ContentResolver.SCHEME_FILE);

        final Context context = InstrumentationRegistry.getContext();
        context.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String data = intent.getDataString();
                if (action.equals(intent.getAction())) {
                    Log.d(TAG, "Received ACTION_MEDIA_MOUNTED with " + data);
                    if (data != null && data.contains("/" + userId)) {
                        latch.countDown();
                        context.unregisterReceiver(this);
                    }
                }
            }
        }, UserHandle.of(userId), filter, null, null);
    }

    private class ProgressWaiter extends IProgressListener.Stub {
        private final CountDownLatch mFinishedLatch = new CountDownLatch(1);