blob: 6b09a9f150cf57ccc4d890e83a134a675208700f [file] [log] [blame]
Sudheer Shanka53c23fd2016-08-17 19:34:58 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.multiuser;
17
18import android.app.ActivityManager;
Bookatz312da052019-04-11 09:24:54 -070019import android.app.ActivityTaskManager;
20import android.app.AppGlobals;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070021import android.app.IActivityManager;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070022import android.app.IStopUserCallback;
23import android.app.UserSwitchObserver;
Bookatz312da052019-04-11 09:24:54 -070024import android.app.WaitResult;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070025import android.content.BroadcastReceiver;
26import android.content.Context;
Bookatz312da052019-04-11 09:24:54 -070027import android.content.IIntentReceiver;
28import android.content.IIntentSender;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070029import android.content.Intent;
30import android.content.IntentFilter;
Bookatz312da052019-04-11 09:24:54 -070031import android.content.IntentSender;
32import android.content.pm.IPackageInstaller;
33import android.content.pm.PackageManager;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070034import android.content.pm.UserInfo;
Bookatz312da052019-04-11 09:24:54 -070035import android.os.Bundle;
36import android.os.IBinder;
37import android.os.IProgressListener;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070038import android.os.RemoteException;
39import android.os.UserHandle;
40import android.os.UserManager;
Bookatz52b12ac2019-02-28 17:29:26 -080041import android.util.Log;
Bookatz312da052019-04-11 09:24:54 -070042import android.view.WindowManagerGlobal;
KOUSHIK PANUGANTI130f0a52018-12-17 14:41:06 -080043
44import androidx.test.InstrumentationRegistry;
45import androidx.test.filters.LargeTest;
46import androidx.test.runner.AndroidJUnit4;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070047
48import org.junit.After;
49import org.junit.Before;
50import org.junit.Rule;
51import org.junit.Test;
52import org.junit.runner.RunWith;
53
54import java.util.ArrayList;
55import java.util.concurrent.CountDownLatch;
56import java.util.concurrent.TimeUnit;
57
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070058/**
59 * Perf tests for user life cycle events.
60 *
61 * Running the tests:
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070062 *
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070063 * make MultiUserPerfTests &&
64 * adb install -r \
65 * ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk &&
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070066 * adb shell am instrument -e class android.multiuser.UserLifecycleTests \
KOUSHIK PANUGANTI130f0a52018-12-17 14:41:06 -080067 * -w com.android.perftests.multiuser/androidx.test.runner.AndroidJUnitRunner
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070068 *
69 * or
70 *
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070071 * bit MultiUserPerfTests:android.multiuser.UserLifecycleTests
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070072 *
73 * Note: If you use bit for running the tests, benchmark results won't be printed on the host side.
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070074 * But in either case, results can be checked on the device side 'adb logcat -s UserLifecycleTests'
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070075 */
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070076@LargeTest
77@RunWith(AndroidJUnit4.class)
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070078public class UserLifecycleTests {
79 private static final String TAG = UserLifecycleTests.class.getSimpleName();
80
Bookatz312da052019-04-11 09:24:54 -070081 private static final int TIMEOUT_IN_SECOND = 30;
82 private static final int CHECK_USER_REMOVED_INTERVAL_MS = 200;
83
84 private static final String DUMMY_PACKAGE_NAME = "perftests.multiuser.apps.dummyapp";
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070085
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070086 private UserManager mUm;
87 private ActivityManager mAm;
88 private IActivityManager mIam;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070089 private ArrayList<Integer> mUsersToRemove;
90
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070091 private final BenchmarkRunner mRunner = new BenchmarkRunner();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070092 @Rule
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070093 public BenchmarkResultsReporter mReporter = new BenchmarkResultsReporter(mRunner);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070094
95 @Before
96 public void setUp() {
97 final Context context = InstrumentationRegistry.getContext();
98 mUm = UserManager.get(context);
99 mAm = context.getSystemService(ActivityManager.class);
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800100 mIam = ActivityManager.getService();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700101 mUsersToRemove = new ArrayList<>();
102 }
103
104 @After
105 public void tearDown() {
106 for (int userId : mUsersToRemove) {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700107 try {
108 mUm.removeUser(userId);
109 } catch (Exception e) {
110 // Ignore
111 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700112 }
113 }
114
115 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700116 public void createAndStartUser() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700117 while (mRunner.keepRunning()) {
Bookatz312da052019-04-11 09:24:54 -0700118 final int userId = createUser();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700119
120 final CountDownLatch latch = new CountDownLatch(1);
Bookatz312da052019-04-11 09:24:54 -0700121 registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId);
122 // Don't use this.startUserInBackground() since only waiting until ACTION_USER_STARTED.
123 mIam.startUserInBackground(userId);
Tony Makec7c6962017-05-26 15:38:09 +0100124 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700125
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700126 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700127 removeUser(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700128 mRunner.resumeTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700129 }
130 }
131
132 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700133 public void switchUser() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700134 while (mRunner.keepRunning()) {
135 mRunner.pauseTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700136 final int startUser = mAm.getCurrentUser();
Bookatz312da052019-04-11 09:24:54 -0700137 final int userId = createUser();
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700138 mRunner.resumeTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700139
Bookatz312da052019-04-11 09:24:54 -0700140 switchUser(userId);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700141
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700142 mRunner.pauseTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700143 switchUser(startUser);
Bookatz312da052019-04-11 09:24:54 -0700144 removeUser(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700145 mRunner.resumeTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700146 }
147 }
148
Bookatz52b12ac2019-02-28 17:29:26 -0800149 /** Tests switching to an already-created, but no-longer-running, user. */
150 @Test
151 public void switchUser_stopped() throws Exception {
152 while (mRunner.keepRunning()) {
153 mRunner.pauseTiming();
154 final int startUser = mAm.getCurrentUser();
155 final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
156 final CountDownLatch latch = new CountDownLatch(1);
157 registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, testUser);
158 mRunner.resumeTiming();
159
160 mAm.switchUser(testUser);
161 boolean success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
162
163 mRunner.pauseTiming();
164 attestTrue("Failed to achieve 2nd ACTION_USER_UNLOCKED for user " + testUser, success);
165 switchUser(startUser);
166 removeUser(testUser);
167 mRunner.resumeTiming();
168 }
169 }
170
171 /** Tests switching to an already-created already-running non-owner user. */
172 @Test
173 public void switchUser_running() throws Exception {
174 while (mRunner.keepRunning()) {
175 mRunner.pauseTiming();
176 final int startUser = mAm.getCurrentUser();
177 final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false);
178 mRunner.resumeTiming();
179
180 switchUser(testUser);
181
182 mRunner.pauseTiming();
183 attestTrue("Failed to switch to user " + testUser, mAm.isUserRunning(testUser));
184 switchUser(startUser);
185 removeUser(testUser);
186 mRunner.resumeTiming();
187 }
188 }
189
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700190 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700191 public void stopUser() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700192 while (mRunner.keepRunning()) {
193 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700194 final int userId = createUser();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700195 final CountDownLatch latch = new CountDownLatch(1);
Bookatz312da052019-04-11 09:24:54 -0700196 registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId);
197 mIam.startUserInBackground(userId);
Tony Makec7c6962017-05-26 15:38:09 +0100198 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700199 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700200
Bookatz312da052019-04-11 09:24:54 -0700201 stopUser(userId, false);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700202
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700203 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700204 removeUser(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700205 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700206 }
207 }
208
209 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700210 public void lockedBootCompleted() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700211 while (mRunner.keepRunning()) {
212 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700213 final int startUser = mAm.getCurrentUser();
Bookatz312da052019-04-11 09:24:54 -0700214 final int userId = createUser();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700215 final CountDownLatch latch = new CountDownLatch(1);
Bookatz312da052019-04-11 09:24:54 -0700216 registerUserSwitchObserver(null, latch, userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700217 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700218
Bookatz312da052019-04-11 09:24:54 -0700219 mAm.switchUser(userId);
Tony Makec7c6962017-05-26 15:38:09 +0100220 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700221
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700222 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700223 switchUser(startUser);
Bookatz312da052019-04-11 09:24:54 -0700224 removeUser(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700225 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700226 }
227 }
228
229 @Test
Bookatz5df3c642019-04-11 09:22:49 -0700230 public void ephemeralUserStopped() throws Exception {
231 while (mRunner.keepRunning()) {
232 mRunner.pauseTiming();
233 final int startUser = mAm.getCurrentUser();
Bookatz312da052019-04-11 09:24:54 -0700234 final int userId = createUser(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
235 switchUser(userId);
Bookatz5df3c642019-04-11 09:22:49 -0700236 final CountDownLatch latch = new CountDownLatch(1);
237 InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() {
238 @Override
239 public void onReceive(Context context, Intent intent) {
240 if (Intent.ACTION_USER_STOPPED.equals(intent.getAction()) && intent.getIntExtra(
Bookatz312da052019-04-11 09:24:54 -0700241 Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) {
Bookatz5df3c642019-04-11 09:22:49 -0700242 latch.countDown();
243 }
244 }
245 }, new IntentFilter(Intent.ACTION_USER_STOPPED));
246 final CountDownLatch switchLatch = new CountDownLatch(1);
247 registerUserSwitchObserver(switchLatch, null, startUser);
248 mRunner.resumeTiming();
249
250 mAm.switchUser(startUser);
251 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
252
253 mRunner.pauseTiming();
254 switchLatch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Bookatz312da052019-04-11 09:24:54 -0700255 removeUser(userId);
Bookatz5df3c642019-04-11 09:22:49 -0700256 mRunner.resumeTiming();
257 }
258 }
259
Bookatz312da052019-04-11 09:24:54 -0700260 /** Tests creating a new profile. */
261 @Test
262 public void managedProfileCreate() throws Exception {
263 while (mRunner.keepRunning()) {
264 final int userId = createManagedProfile();
265
266 mRunner.pauseTiming();
267 attestTrue("Failed creating profile " + userId, mUm.isManagedProfile(userId));
268 removeUser(userId);
269 mRunner.resumeTiming();
270 }
271 }
272
273 /** Tests starting (unlocking) a newly-created profile. */
Bookatz5df3c642019-04-11 09:22:49 -0700274 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700275 public void managedProfileUnlock() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700276 while (mRunner.keepRunning()) {
277 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700278 final int userId = createManagedProfile();
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700279 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700280
Bookatz312da052019-04-11 09:24:54 -0700281 startUserInBackground(userId);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700282
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700283 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700284 removeUser(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700285 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700286 }
287 }
288
Bookatz312da052019-04-11 09:24:54 -0700289 /** Tests starting (unlocking) an already-created, but no-longer-running, profile. */
Bookatz57908d92019-03-29 10:40:10 -0700290 @Test
291 public void managedProfileUnlock_stopped() throws Exception {
292 while (mRunner.keepRunning()) {
293 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700294 final int userId = createManagedProfile();
Bookatz57908d92019-03-29 10:40:10 -0700295 // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
Bookatz312da052019-04-11 09:24:54 -0700296 startUserInBackground(userId);
297 stopUser(userId, true);
Bookatz57908d92019-03-29 10:40:10 -0700298 mRunner.resumeTiming();
299
Bookatz312da052019-04-11 09:24:54 -0700300 startUserInBackground(userId);
Bookatz57908d92019-03-29 10:40:10 -0700301
302 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700303 removeUser(userId);
Bookatz57908d92019-03-29 10:40:10 -0700304 mRunner.resumeTiming();
305 }
306 }
307
Bookatz312da052019-04-11 09:24:54 -0700308 /**
309 * Tests starting (unlocking) and launching an already-installed app in a newly-created profile.
310 */
311 @Test
312 public void managedProfileUnlockAndLaunchApp() throws Exception {
313 while (mRunner.keepRunning()) {
314 mRunner.pauseTiming();
315 final int userId = createManagedProfile();
316 WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
317 installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
318 mRunner.resumeTiming();
Tony Makec7c6962017-05-26 15:38:09 +0100319
Bookatz312da052019-04-11 09:24:54 -0700320 startUserInBackground(userId);
321 startApp(userId, DUMMY_PACKAGE_NAME);
322
323 mRunner.pauseTiming();
324 removeUser(userId);
325 mRunner.resumeTiming();
326 }
327 }
328
329 /** Tests installing a pre-existing app in a newly-created profile. */
330 @Test
331 public void managedProfileInstall() throws Exception {
332 while (mRunner.keepRunning()) {
333 mRunner.pauseTiming();
334 final int userId = createManagedProfile();
335 mRunner.resumeTiming();
336
337 installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
338
339 mRunner.pauseTiming();
340 removeUser(userId);
341 mRunner.resumeTiming();
342 }
343 }
344
345 /**
346 * Tests creating a new profile, starting (unlocking) it, installing an app,
347 * and launching that app in it.
348 */
349 @Test
350 public void managedProfileCreateUnlockInstallAndLaunchApp() throws Exception {
351 final String packageName = "perftests.multiuser.apps.dummyapp";
352 while (mRunner.keepRunning()) {
353 mRunner.pauseTiming();
354 WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
355 mRunner.resumeTiming();
356
357 final int userId = createManagedProfile();
358 startUserInBackground(userId);
359 installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
360 startApp(userId, DUMMY_PACKAGE_NAME);
361
362 mRunner.pauseTiming();
363 removeUser(userId);
364 mRunner.resumeTiming();
365 }
366 }
367
368 /** Tests stopping a profile. */
Tony Makec7c6962017-05-26 15:38:09 +0100369 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700370 public void managedProfileStopped() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700371 while (mRunner.keepRunning()) {
372 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700373 final int userId = createManagedProfile();
374 startUserInBackground(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700375 mRunner.resumeTiming();
Tony Makec7c6962017-05-26 15:38:09 +0100376
Bookatz312da052019-04-11 09:24:54 -0700377 stopUser(userId, true);
Tony Makec7c6962017-05-26 15:38:09 +0100378
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700379 mRunner.pauseTiming();
Bookatz312da052019-04-11 09:24:54 -0700380 removeUser(userId);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700381 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700382 }
383 }
384
Bookatz312da052019-04-11 09:24:54 -0700385 /** Creates a new user, returning its userId. */
386 private int createUser() {
387 return createUser(0);
388 }
389
390 /** Creates a new user with the given flags, returning its userId. */
391 private int createUser(int flags) {
392 int userId = mUm.createUser("TestUser", flags).id;
393 mUsersToRemove.add(userId);
394 return userId;
395 }
396
397 /** Creates a managed (work) profile under the current user, returning its userId. */
398 private int createManagedProfile() {
399 final UserInfo userInfo = mUm.createProfileForUser("TestProfile",
400 UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
401 mUsersToRemove.add(userInfo.id);
402 return userInfo.id;
403 }
404
405 /**
406 * Start user in background and wait for it to unlock (equivalent to ACTION_USER_UNLOCKED).
407 * To start in foreground instead, see {@link #switchUser(int)}.
408 * This should always be used for profiles since profiles cannot be started in foreground.
409 */
410 private void startUserInBackground(int userId) {
411 final ProgressWaiter waiter = new ProgressWaiter();
412 try {
413 mIam.startUserInBackgroundWithListener(userId, waiter);
414 boolean success = waiter.waitForFinish(TIMEOUT_IN_SECOND);
415 attestTrue("Failed to start user " + userId + " in background.", success);
416 } catch (RemoteException e) {
417 Log.e(TAG, "startUserInBackground failed", e);
418 }
419 }
420
421 /** Starts the given user in the foreground. */
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700422 private void switchUser(int userId) throws Exception {
423 final CountDownLatch latch = new CountDownLatch(1);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700424 registerUserSwitchObserver(latch, null, userId);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700425 mAm.switchUser(userId);
Tony Makec7c6962017-05-26 15:38:09 +0100426 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700427 }
428
Tony Makec7c6962017-05-26 15:38:09 +0100429 private void stopUser(int userId, boolean force) throws Exception {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700430 final CountDownLatch latch = new CountDownLatch(1);
Tony Makec7c6962017-05-26 15:38:09 +0100431 mIam.stopUser(userId, force /* force */, new IStopUserCallback.Stub() {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700432 @Override
433 public void userStopped(int userId) throws RemoteException {
434 latch.countDown();
435 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700436
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700437 @Override
438 public void userStopAborted(int userId) throws RemoteException {
439 }
440 });
Tony Makec7c6962017-05-26 15:38:09 +0100441 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700442 }
443
Bookatz52b12ac2019-02-28 17:29:26 -0800444 /**
445 * Creates a user and waits for its ACTION_USER_UNLOCKED.
446 * Then switches to back to the original user and waits for its switchUser() to finish.
447 *
448 * @param stopNewUser whether to stop the new user after switching to otherUser.
449 * @return userId of the newly created user.
450 */
451 private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws Exception {
452 final int origUser = mAm.getCurrentUser();
453 // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED
Bookatz312da052019-04-11 09:24:54 -0700454 final int testUser = createUser();
Bookatz52b12ac2019-02-28 17:29:26 -0800455 final CountDownLatch latch1 = new CountDownLatch(1);
456 registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, testUser);
457 mAm.switchUser(testUser);
458 attestTrue("Failed to achieve initial ACTION_USER_UNLOCKED for user " + testUser,
459 latch1.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS));
460
461 // Second, switch back to origUser, waiting merely for switchUser() to finish
462 switchUser(origUser);
463 attestTrue("Didn't switch back to user, " + origUser, origUser == mAm.getCurrentUser());
464
465 if (stopNewUser) {
466 stopUser(testUser, true);
467 attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
468 }
469
470 return testUser;
471 }
472
Bookatz312da052019-04-11 09:24:54 -0700473 /**
474 * Installs the given package in the given user.
475 */
476 private void installPreexistingApp(int userId, String packageName) throws RemoteException {
477 final CountDownLatch latch = new CountDownLatch(1);
478
479 final IntentSender sender = new IntentSender((IIntentSender) new IIntentSender.Stub() {
480 @Override
481 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
482 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
483 latch.countDown();
484 }
485 });
486
487 final IPackageInstaller installer = AppGlobals.getPackageManager().getPackageInstaller();
488 installer.installExistingPackage(packageName, 0, PackageManager.INSTALL_REASON_UNKNOWN,
489 sender, userId);
490
491 try {
492 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
493 } catch (InterruptedException e) {
494 Log.e(TAG, "Thread interrupted unexpectedly.", e);
495 }
496 }
497
498 /**
499 * Launches the given package in the given user.
500 * Make sure the keyguard has been dismissed prior to calling.
501 */
502 private void startApp(int userId, String packageName) throws RemoteException {
503 final Context context = InstrumentationRegistry.getContext();
504 final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null, null,
505 context.getPackageManager().getLaunchIntentForPackage(packageName),
506 null, null, null, 0, 0, null, null,
507 userId);
508 attestTrue("User " + userId + " failed to start " + packageName,
509 result.result == ActivityManager.START_SUCCESS);
510 }
511
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700512 private void registerUserSwitchObserver(final CountDownLatch switchLatch,
513 final CountDownLatch bootCompleteLatch, final int userId) throws Exception {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800514 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700515 new UserSwitchObserver() {
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700516 @Override
517 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700518 if (switchLatch != null && userId == newUserId) {
519 switchLatch.countDown();
520 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700521 }
522
523 @Override
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700524 public void onLockedBootComplete(int newUserId) {
525 if (bootCompleteLatch != null && userId == newUserId) {
526 bootCompleteLatch.countDown();
527 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700528 }
Sudheer Shanka2d0278b2017-07-12 18:12:31 -0700529 }, TAG);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700530 }
531
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700532 private void registerBroadcastReceiver(final String action, final CountDownLatch latch,
533 final int userId) {
534 InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() {
535 @Override
536 public void onReceive(Context context, Intent intent) {
537 if (action.equals(intent.getAction()) && intent.getIntExtra(
538 Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) {
539 latch.countDown();
540 }
541 }
542 }, UserHandle.of(userId), new IntentFilter(action), null, null);
543 }
544
Bookatz312da052019-04-11 09:24:54 -0700545 private class ProgressWaiter extends IProgressListener.Stub {
546 private final CountDownLatch mFinishedLatch = new CountDownLatch(1);
547
548 @Override
549 public void onStarted(int id, Bundle extras) {}
550
551 @Override
552 public void onProgress(int id, int progress, Bundle extras) {}
553
554 @Override
555 public void onFinished(int id, Bundle extras) {
556 mFinishedLatch.countDown();
557 }
558
559 public boolean waitForFinish(long timeoutSecs) {
560 try {
561 return mFinishedLatch.await(timeoutSecs, TimeUnit.SECONDS);
562 } catch (InterruptedException e) {
563 Log.e(TAG, "Thread interrupted unexpectedly.", e);
564 return false;
565 }
566 }
567 }
568
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700569 private void removeUser(int userId) {
570 try {
571 mUm.removeUser(userId);
572 final long startTime = System.currentTimeMillis();
Tony Makec7c6962017-05-26 15:38:09 +0100573 final long timeoutInMs = TIMEOUT_IN_SECOND * 1000;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700574 while (mUm.getUserInfo(userId) != null &&
Tony Makec7c6962017-05-26 15:38:09 +0100575 System.currentTimeMillis() - startTime < timeoutInMs) {
576 TimeUnit.MILLISECONDS.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700577 }
578 } catch (InterruptedException e) {
579 Thread.currentThread().interrupt();
580 } catch (Exception e) {
581 // Ignore
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700582 }
583 if (mUm.getUserInfo(userId) != null) {
584 mUsersToRemove.add(userId);
585 }
586 }
Bookatz52b12ac2019-02-28 17:29:26 -0800587
Bookatz312da052019-04-11 09:24:54 -0700588 private void attestTrue(String message, boolean assertion) {
589 if (!assertion) {
Bookatz52b12ac2019-02-28 17:29:26 -0800590 Log.w(TAG, message);
591 }
592 }
593
Bookatz312da052019-04-11 09:24:54 -0700594 private void attestFalse(String message, boolean assertion) {
595 attestTrue(message, !assertion);
Bookatz52b12ac2019-02-28 17:29:26 -0800596 }
John Reck62e5fea2016-10-12 15:27:52 -0700597}