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
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user