diff options
author | Sudheer Shanka <sudheersai@google.com> | 2016-08-27 20:53:28 -0700 |
---|---|---|
committer | Sudheer Shanka <sudheersai@google.com> | 2016-09-08 13:30:34 -0700 |
commit | 2c4522cc1bf3a3d0178688427a33b860ddfe4bba (patch) | |
tree | 70c8d7cf9d0e7280dcae14fe499b890e7e1b638f | |
parent | 9af92f3cca4894190f2638dce21aef334c032ccd (diff) |
Add usermanager related perf tests - part2
- Add onLockedBootComplete callback to UserSwitchObserver.
Bug: 30948225
Test: adb shell am instrument -e class android.multiuser.UserLifecycleTest -w com.android.perftests.multiuser/android.support.test.runner.AndroidJUnitRunner
Change-Id: I87533094805a81fbd85d4f492e637b3304ecd5e2
9 files changed, 234 insertions, 52 deletions
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java index bd0139f7811d..cdbca63fc5fa 100644 --- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java +++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java @@ -18,7 +18,8 @@ package android.multiuser; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.IActivityManager; -import android.app.SynchronousUserSwitchObserver; +import android.app.IStopUserCallback; +import android.app.UserSwitchObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -43,18 +44,36 @@ import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +/** + * Perf tests for user life cycle events. + * + * Running the tests: + * make MultiUserPerfTests && + * adb install -r \ + * ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk && + * adb shell am instrument -e class android.multiuser.UserLifecycleTest \ + * -w com.android.perftests.multiuser/android.support.test.runner.AndroidJUnitRunner + */ @LargeTest @RunWith(AndroidJUnit4.class) public class UserLifecycleTest { private final int MIN_REPEAT_TIMES = 4; - private final int TIMEOUT_REMOVE_USER_SEC = 4; + private final int TIMEOUT_REMOVE_USER_MS = 4 * 1000; // 4 sec private final int CHECK_USER_REMOVED_INTERVAL_MS = 200; // 0.2 sec private final int TIMEOUT_USER_START_SEC = 4; // 4 sec private final int TIMEOUT_USER_SWITCH_SEC = 8; // 8 sec + private final int TIMEOUT_USER_STOP_SEC = 1; // 1 sec + + private final int TIMEOUT_MANAGED_PROFILE_UNLOCK_SEC = 2; // 2 sec + + private final int TIMEOUT_LOCKED_BOOT_COMPLETE_MS = 5 * 1000; // 5 sec + + private final int TIMEOUT_EPHERMAL_USER_STOP_SEC = 6; // 6 sec + private UserManager mUm; private ActivityManager mAm; private IActivityManager mIam; @@ -78,7 +97,11 @@ public class UserLifecycleTest { @After public void tearDown() { for (int userId : mUsersToRemove) { - mUm.removeUser(userId); + try { + mUm.removeUser(userId); + } catch (Exception e) { + // Ignore + } } } @@ -88,14 +111,7 @@ public class UserLifecycleTest { final UserInfo userInfo = mUm.createUser("TestUser", 0); final CountDownLatch latch = new CountDownLatch(1); - InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { - latch.countDown(); - } - } - }, UserHandle.ALL, new IntentFilter(Intent.ACTION_USER_STARTED), null, null); + registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id); mIam.startUserInBackground(userInfo.id); latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS); @@ -122,37 +138,163 @@ public class UserLifecycleTest { } } + @Test + public void stopUserPerf() throws Exception { + while (mState.keepRunning()) { + mState.pauseTiming(); + final UserInfo userInfo = mUm.createUser("TestUser", 0); + final CountDownLatch latch = new CountDownLatch(1); + registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id); + mIam.startUserInBackground(userInfo.id); + latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS); + mState.resumeTiming(); + + stopUser(userInfo.id); + + mState.pauseTiming(); + removeUser(userInfo.id); + mState.resumeTiming(); + } + } + + @Test + public void lockedBootCompletedPerf() throws Exception { + while (mState.keepRunning()) { + mState.pauseTiming(); + final int startUser = mAm.getCurrentUser(); + final UserInfo userInfo = mUm.createUser("TestUser", 0); + final CountDownLatch latch = new CountDownLatch(1); + registerUserSwitchObserver(null, latch, userInfo.id); + mState.resumeTiming(); + + mAm.switchUser(userInfo.id); + latch.await(TIMEOUT_LOCKED_BOOT_COMPLETE_MS, TimeUnit.SECONDS); + + mState.pauseTiming(); + switchUser(startUser); + removeUser(userInfo.id); + mState.resumeTiming(); + } + } + + @Test + public void managedProfileUnlockPerf() throws Exception { + while (mState.keepRunning()) { + mState.pauseTiming(); + final UserInfo userInfo = mUm.createProfileForUser("TestUser", + UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser()); + final CountDownLatch latch = new CountDownLatch(1); + registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, userInfo.id); + mState.resumeTiming(); + + mIam.startUserInBackground(userInfo.id); + latch.await(TIMEOUT_MANAGED_PROFILE_UNLOCK_SEC, TimeUnit.SECONDS); + + mState.pauseTiming(); + removeUser(userInfo.id); + mState.resumeTiming(); + } + } + + @Test + public void ephemeralUserStoppedPerf() throws Exception { + while (mState.keepRunning()) { + mState.pauseTiming(); + final int startUser = mAm.getCurrentUser(); + final UserInfo userInfo = mUm.createUser("TestUser", + UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO); + switchUser(userInfo.id); + final CountDownLatch latch = new CountDownLatch(1); + InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_USER_STOPPED.equals(intent.getAction()) && intent.getIntExtra( + Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userInfo.id) { + latch.countDown(); + } + } + }, new IntentFilter(Intent.ACTION_USER_STOPPED)); + final CountDownLatch switchLatch = new CountDownLatch(1); + registerUserSwitchObserver(switchLatch, null, startUser); + mState.resumeTiming(); + + mAm.switchUser(startUser); + latch.await(TIMEOUT_EPHERMAL_USER_STOP_SEC, TimeUnit.SECONDS); + + mState.pauseTiming(); + switchLatch.await(TIMEOUT_USER_SWITCH_SEC, TimeUnit.SECONDS); + removeUser(userInfo.id); + mState.resumeTiming(); + } + } + private void switchUser(int userId) throws Exception { final CountDownLatch latch = new CountDownLatch(1); - registerUserSwitchObserver(latch); + registerUserSwitchObserver(latch, null, userId); mAm.switchUser(userId); latch.await(TIMEOUT_USER_SWITCH_SEC, TimeUnit.SECONDS); } - private void registerUserSwitchObserver(final CountDownLatch latch) throws Exception { - ActivityManagerNative.getDefault().registerUserSwitchObserver( - new SynchronousUserSwitchObserver() { - @Override - public void onUserSwitching(int newUserId) throws RemoteException { - } + private void stopUser(int userId) throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + mIam.stopUser(userId, false /* force */, new IStopUserCallback.Stub() { + @Override + public void userStopped(int userId) throws RemoteException { + latch.countDown(); + } + @Override + public void userStopAborted(int userId) throws RemoteException { + } + }); + latch.await(TIMEOUT_USER_STOP_SEC, TimeUnit.SECONDS); + } + + private void registerUserSwitchObserver(final CountDownLatch switchLatch, + final CountDownLatch bootCompleteLatch, final int userId) throws Exception { + ActivityManagerNative.getDefault().registerUserSwitchObserver( + new UserSwitchObserver() { @Override public void onUserSwitchComplete(int newUserId) throws RemoteException { - latch.countDown(); + if (switchLatch != null && userId == newUserId) { + switchLatch.countDown(); + } } @Override - public void onForegroundProfileSwitch(int newProfileId) throws RemoteException { + public void onLockedBootComplete(int newUserId) { + if (bootCompleteLatch != null && userId == newUserId) { + bootCompleteLatch.countDown(); + } } }, "UserLifecycleTest"); } - private void removeUser(int userId) throws Exception { - mUm.removeUser(userId); - final long startTime = System.currentTimeMillis(); - while (mUm.getUserInfo(userId) != null && - System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_SEC) { - Thread.sleep(CHECK_USER_REMOVED_INTERVAL_MS); + private void registerBroadcastReceiver(final String action, final CountDownLatch latch, + final int userId) { + InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (action.equals(intent.getAction()) && intent.getIntExtra( + Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) { + latch.countDown(); + } + } + }, UserHandle.of(userId), new IntentFilter(action), null, null); + } + + private void removeUser(int userId) { + try { + mUm.removeUser(userId); + final long startTime = System.currentTimeMillis(); + while (mUm.getUserInfo(userId) != null && + System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_MS) { + Thread.sleep(CHECK_USER_REMOVED_INTERVAL_MS); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception e) { + // Ignore } if (mUm.getUserInfo(userId) != null) { mUsersToRemove.add(userId); diff --git a/core/java/android/app/IUserSwitchObserver.aidl b/core/java/android/app/IUserSwitchObserver.aidl index caee14fa5d1e..234da8f36e96 100644 --- a/core/java/android/app/IUserSwitchObserver.aidl +++ b/core/java/android/app/IUserSwitchObserver.aidl @@ -23,4 +23,5 @@ oneway interface IUserSwitchObserver { void onUserSwitching(int newUserId, IRemoteCallback reply); void onUserSwitchComplete(int newUserId); void onForegroundProfileSwitch(int newProfileId); + void onLockedBootComplete(int newUserId); } diff --git a/core/java/android/app/SynchronousUserSwitchObserver.java b/core/java/android/app/SynchronousUserSwitchObserver.java index 6d929f90e4de..3a7388860ea8 100644 --- a/core/java/android/app/SynchronousUserSwitchObserver.java +++ b/core/java/android/app/SynchronousUserSwitchObserver.java @@ -25,7 +25,7 @@ import android.os.RemoteException; * * @hide */ -public abstract class SynchronousUserSwitchObserver extends IUserSwitchObserver.Stub { +public abstract class SynchronousUserSwitchObserver extends UserSwitchObserver { /** * Calls {@link #onUserSwitching(int)} and notifies {@code reply} by calling * {@link IRemoteCallback#sendResult(Bundle)}. diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java new file mode 100644 index 000000000000..c0f7a4cd63b7 --- /dev/null +++ b/core/java/android/app/UserSwitchObserver.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.app; + +import android.os.IRemoteCallback; +import android.os.RemoteException; + +/** + * @hide + */ +public class UserSwitchObserver extends IUserSwitchObserver.Stub { + @Override + public void onUserSwitching(int newUserId, IRemoteCallback reply) throws RemoteException { + if (reply != null) { + reply.sendResult(null); + } + } + + @Override + public void onUserSwitchComplete(int newUserId) throws RemoteException {} + + @Override + public void onForegroundProfileSwitch(int newProfileId) throws RemoteException {} + + @Override + public void onLockedBootComplete(int newUserId) throws RemoteException {} +}
\ No newline at end of file diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 0566177e1880..9275f2eb77ba 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -29,8 +29,8 @@ import static android.os.BatteryManager.EXTRA_STATUS; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AlarmManager; -import android.app.IUserSwitchObserver; import android.app.PendingIntent; +import android.app.UserSwitchObserver; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; import android.content.BroadcastReceiver; @@ -1053,7 +1053,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); try { ActivityManagerNative.getDefault().registerUserSwitchObserver( - new IUserSwitchObserver.Stub() { + new UserSwitchObserver() { @Override public void onUserSwitching(int newUserId, IRemoteCallback reply) { mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING, @@ -1064,10 +1064,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE, newUserId, 0)); } - @Override - public void onForegroundProfileSwitch(int newProfileId) { - // Ignore. - } }, TAG); } catch (RemoteException e) { e.rethrowAsRuntimeException(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 146684fc86b5..add74fadd963 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1534,6 +1534,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69; static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 70; static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 71; + static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 72; static final int START_USER_SWITCH_FG_MSG = 712; static final int FIRST_ACTIVITY_STACK_MSG = 100; @@ -2281,6 +2282,9 @@ public final class ActivityManagerService extends ActivityManagerNative case REPORT_USER_SWITCH_COMPLETE_MSG: { mUserController.dispatchUserSwitchComplete(msg.arg1); } break; + case REPORT_LOCKED_BOOT_COMPLETE_MSG: { + mUserController.dispatchLockedBootComplete(msg.arg1); + } break; case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: { IUiAutomationConnection connection = (IUiAutomationConnection) msg.obj; try { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 0407361759dc..ba42d3f7f29a 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -32,6 +32,7 @@ import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY; import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL; import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE; import static com.android.server.am.ActivityManagerService.MY_PID; +import static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG; import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG; import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG; import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG; @@ -259,6 +260,8 @@ final class UserController { MetricsLogger.histogram(mInjector.getContext(), "framework_locked_boot_completed", uptimeSeconds); + mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG, + userId, 0)); Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT @@ -1053,6 +1056,18 @@ final class UserController { mUserSwitchObservers.finishBroadcast(); } + void dispatchLockedBootComplete(int userId) { + final int observerCount = mUserSwitchObservers.beginBroadcast(); + for (int i = 0; i < observerCount; i++) { + try { + mUserSwitchObservers.getBroadcastItem(i).onLockedBootComplete(userId); + } catch (RemoteException e) { + // Ignore + } + } + mUserSwitchObservers.finishBroadcast(); + } + private void stopBackgroundUsersIfEnforced(int oldUserId) { // Never stop system user if (oldUserId == UserHandle.USER_SYSTEM) { diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 73c8469ca709..5addffbeb426 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -1068,14 +1068,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) .sendToTarget(); } - @Override - public void onUserSwitchComplete(int newUserId) throws RemoteException { - // Ignore. - } - @Override - public void onForegroundProfileSwitch(int newProfileId) { - // Ignore. - } }, TAG); } catch (RemoteException e) { Slog.w(TAG, "Failed to listen for user switching event" ,e); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 3075102bc641..169446de0fe5 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -27,10 +27,10 @@ import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.app.AppOpsManager; -import android.app.IUserSwitchObserver; import android.app.IWallpaperManager; import android.app.IWallpaperManagerCallback; import android.app.PendingIntent; +import android.app.UserSwitchObserver; import android.app.WallpaperInfo; import android.app.WallpaperManager; import android.app.admin.DevicePolicyManager; @@ -904,20 +904,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { try { ActivityManagerNative.getDefault().registerUserSwitchObserver( - new IUserSwitchObserver.Stub() { + new UserSwitchObserver() { @Override public void onUserSwitching(int newUserId, IRemoteCallback reply) { switchUser(newUserId, reply); } - - @Override - public void onUserSwitchComplete(int newUserId) throws RemoteException { - } - - @Override - public void onForegroundProfileSwitch(int newProfileId) { - // Ignore. - } }, TAG); } catch (RemoteException e) { e.rethrowAsRuntimeException(); |