1 /* 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 */ 16 17 package com.android.cts.deviceowner; 18 19 import static android.os.UserManager.USER_OPERATION_SUCCESS; 20 21 import static com.google.common.truth.Truth.assertWithMessage; 22 23 import static org.testng.Assert.expectThrows; 24 25 import android.app.ActivityManager; 26 import android.app.Service; 27 import android.app.admin.DeviceAdminReceiver; 28 import android.app.admin.DevicePolicyManager; 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.ServiceConnection; 33 import android.content.pm.PackageManager; 34 import android.os.IBinder; 35 import android.os.PersistableBundle; 36 import android.os.RemoteException; 37 import android.os.SystemClock; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 import android.provider.Settings; 41 import android.util.DebugUtils; 42 import android.util.Log; 43 44 import com.android.compatibility.common.util.SystemUtil; 45 46 import java.lang.reflect.InvocationTargetException; 47 import java.lang.reflect.Method; 48 import java.util.Collections; 49 import java.util.HashSet; 50 import java.util.Iterator; 51 import java.util.List; 52 import java.util.Set; 53 import java.util.concurrent.Semaphore; 54 import java.util.concurrent.TimeUnit; 55 import java.util.function.Predicate; 56 import java.util.stream.Collectors; 57 58 /** 59 * Test {@link DevicePolicyManager#createAndManageUser}. 60 */ 61 public class CreateAndManageUserTest extends BaseDeviceOwnerTest { 62 private static final String TAG = "CreateAndManageUserTest"; 63 64 private static final String AFFILIATION_ID = "affiliation.id"; 65 private static final String EXTRA_AFFILIATION_ID = "affiliationIdExtra"; 66 private static final String EXTRA_CURRENT_USER_PACKAGES = "currentUserPackages"; 67 private static final String EXTRA_METHOD_NAME = "methodName"; 68 private static final long ON_ENABLED_TIMEOUT_SECONDS = 120; 69 70 @Override tearDown()71 protected void tearDown() throws Exception { 72 mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER); 73 mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER); 74 super.tearDown(); 75 } 76 testCreateAndManageUser()77 public void testCreateAndManageUser() throws Exception { 78 UserHandle userHandle = createAndManageUser(); 79 80 assertWithMessage("New user").that(userHandle).isNotNull(); 81 } 82 testCreateAndManageUser_MaxUsers()83 public void testCreateAndManageUser_MaxUsers() throws Exception { 84 UserManager.UserOperationException e = expectThrows( 85 UserManager.UserOperationException.class, () -> createAndManageUser()); 86 87 assertUserOperationResult(e.getUserOperationResult(), 88 UserManager.USER_OPERATION_ERROR_MAX_USERS, 89 "user creation when max users is reached"); 90 } 91 92 @SuppressWarnings("unused") assertSkipSetupWizard(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)93 private static void assertSkipSetupWizard(Context context, 94 DevicePolicyManager devicePolicyManager, ComponentName componentName) throws Exception { 95 assertWithMessage("user setup settings (%s)", Settings.Secure.USER_SETUP_COMPLETE) 96 .that(Settings.Secure.getInt(context.getContentResolver(), 97 Settings.Secure.USER_SETUP_COMPLETE)) 98 .isEqualTo(1); 99 } 100 testCreateAndManageUser_SkipSetupWizard()101 public void testCreateAndManageUser_SkipSetupWizard() throws Exception { 102 runCrossUserVerification(DevicePolicyManager.SKIP_SETUP_WIZARD, "assertSkipSetupWizard"); 103 104 PrimaryUserService.assertCrossUserCallArrived(); 105 } 106 testCreateAndManageUser_GetSecondaryUsers()107 public void testCreateAndManageUser_GetSecondaryUsers() throws Exception { 108 UserHandle newUserHandle = createAndManageUser(); 109 110 List<UserHandle> secondaryUsers = mDevicePolicyManager.getSecondaryUsers(getWho()); 111 if (isHeadlessSystemUserMode()) { 112 assertWithMessage("secondary users").that(secondaryUsers) 113 .containsExactly(getCurrentUser(), newUserHandle); 114 } else { 115 assertWithMessage("secondary users").that(secondaryUsers) 116 .containsExactly(newUserHandle); 117 } 118 } 119 testCreateAndManageUser_SwitchUser()120 public void testCreateAndManageUser_SwitchUser() throws Exception { 121 UserHandle userHandle = createAndManageUser(); 122 123 List<UserHandle> usersOnBroadcasts = switchUserAndWaitForBroadcasts(userHandle); 124 125 assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle, 126 userHandle); 127 } 128 testCreateAndManageUser_CannotStopCurrentUser()129 public void testCreateAndManageUser_CannotStopCurrentUser() throws Exception { 130 UserHandle userHandle = createAndManageUser(); 131 132 switchUserAndWaitForBroadcasts(userHandle); 133 134 stopUserAndCheckResult(userHandle, UserManager.USER_OPERATION_ERROR_CURRENT_USER); 135 } 136 testCreateAndManageUser_StartInBackground()137 public void testCreateAndManageUser_StartInBackground() throws Exception { 138 UserHandle userHandle = createAndManageUser(); 139 140 List<UserHandle> usersOnBroadcasts = startUserInBackgroundAndWaitForBroadcasts(userHandle); 141 142 assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle); 143 } 144 testCreateAndManageUser_StartInBackground_MaxRunningUsers()145 public void testCreateAndManageUser_StartInBackground_MaxRunningUsers() throws Exception { 146 UserHandle userHandle = createAndManageUser(); 147 148 // Start user in background and should receive max running users error 149 startUserInBackgroundAndCheckResult(userHandle, 150 UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS); 151 } 152 testCreateAndManageUser_StopUser()153 public void testCreateAndManageUser_StopUser() throws Exception { 154 UserHandle userHandle = createAndManageUser(); 155 startUserInBackgroundAndWaitForBroadcasts(userHandle); 156 157 List<UserHandle> usersOnBroadcasts = stopUserAndWaitForBroadcasts(userHandle); 158 159 assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle); 160 } 161 testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser()162 public void testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser() throws Exception { 163 // Set DISALLOW_REMOVE_USER restriction 164 mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER); 165 166 UserHandle userHandle = createAndManageUser(DevicePolicyManager.MAKE_USER_EPHEMERAL); 167 startUserInBackgroundAndWaitForBroadcasts(userHandle); 168 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 169 getContext(), 170 BasicAdminReceiver.ACTION_USER_STOPPED, BasicAdminReceiver.ACTION_USER_REMOVED); 171 172 callback.runAndUnregisterSelf( 173 () -> stopUserAndCheckResult(userHandle, USER_OPERATION_SUCCESS)); 174 175 // It's running just one operation (which issues a ACTION_USER_STOPPED), but as the 176 // user is ephemeral, it will be automatically removed (which issues a 177 // ACTION_USER_REMOVED). 178 assertWithMessage("user on broadcasts").that(callback.getUsersOnReceivedBroadcasts()) 179 .containsExactly(userHandle, userHandle); 180 } 181 182 @SuppressWarnings("unused") logoutUser(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)183 private static void logoutUser(Context context, DevicePolicyManager devicePolicyManager, 184 ComponentName componentName) { 185 Log.d(TAG, "calling logoutUser() on user " + context.getUserId()); 186 int result = devicePolicyManager.logoutUser(componentName); 187 Log.d(TAG, "result: " + userOperationResultToString(result)); 188 assertUserOperationResult(result, USER_OPERATION_SUCCESS, "cannot logout user"); 189 } 190 clearLogoutUserIfNecessary()191 private void clearLogoutUserIfNecessary() throws Exception { 192 UserHandle userHandle = mDevicePolicyManager.getLogoutUser(); 193 Log.d(TAG, "clearLogoutUserIfNecessary(): logoutUser=" + userHandle); 194 if (userHandle == null) { 195 Log.d(TAG, "clearLogoutUserIfNecessary(): Saul Goodman!"); 196 return; 197 } 198 Log.w(TAG, "test started with a logout user (" + userHandle + "); logging out"); 199 int result = SystemUtil 200 .callWithShellPermissionIdentity(() -> mDevicePolicyManager.logoutUser()); 201 Log.d(TAG, "Result: " + userOperationResultToString(result)); 202 } 203 testCreateAndManageUser_LogoutUser()204 public void testCreateAndManageUser_LogoutUser() throws Exception { 205 clearLogoutUserIfNecessary(); 206 207 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 208 getContext(), 209 BasicAdminReceiver.ACTION_USER_STARTED, BasicAdminReceiver.ACTION_USER_STOPPED); 210 211 UserHandle userHandle = runCrossUserVerification(callback, 212 /* createAndManageUserFlags= */ 0, "logoutUser", /* currentUserPackages= */ null); 213 214 List<UserHandle> users = callback.getUsersOnReceivedBroadcasts(); 215 Log.d(TAG, "users on brodcast: " + users); 216 assertWithMessage("users on broadcast").that(users).containsExactly(userHandle, userHandle); 217 assertWithMessage("final logout user").that(mDevicePolicyManager.getLogoutUser()) 218 .isNull(); 219 } 220 testCreateAndManageUser_LogoutUser_systemApi()221 public void testCreateAndManageUser_LogoutUser_systemApi() throws Exception { 222 clearLogoutUserIfNecessary(); 223 224 UserHandle currentUser = getCurrentUser(); 225 UserHandle newUser = createAndManageUser(); 226 List<UserHandle> usersOnBroadcasts = switchUserAndWaitForBroadcasts(newUser); 227 Log.d(TAG, "users on switch broadcast: " + usersOnBroadcasts); 228 assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(newUser, 229 newUser); 230 assertWithMessage("logout user after switch").that(mDevicePolicyManager.getLogoutUser()) 231 .isEqualTo(currentUser); 232 233 List<UserHandle> users = logoutUserUsingSystemApiAndWaitForBroadcasts(); 234 Log.d(TAG, "users on logout broadcast: " + users); 235 assertWithMessage("users on broadcast").that(users).containsExactly(currentUser); 236 assertWithMessage("final logout user").that(mDevicePolicyManager.getLogoutUser()) 237 .isNull(); 238 } 239 240 @SuppressWarnings("unused") newUserDisclaimer(Context context, DevicePolicyManager dpm, ComponentName componentName)241 private static void newUserDisclaimer(Context context, DevicePolicyManager dpm, 242 ComponentName componentName) { 243 244 // Need to wait until host-side granted INTERACT_ACROSS_USERS - use getCurrentUser() to 245 // check 246 int currentUserId = UserHandle.USER_NULL; 247 long maxAttempts = ON_ENABLED_TIMEOUT_SECONDS; 248 int waitingTimeMs = 1_000; 249 int attempt = 0; 250 int myUserId = context.getUserId(); 251 do { 252 attempt++; 253 try { 254 Log.d(TAG, "checking if user " + myUserId + " is current user"); 255 currentUserId = ActivityManager.getCurrentUser(); 256 Log.d(TAG, "currentUserId: " + currentUserId); 257 } catch (SecurityException e) { 258 Log.d(TAG, "Got exception (" + e.getMessage() + ") on attempt #" + attempt 259 + ", waiting " + waitingTimeMs + "ms until app is authorized"); 260 SystemClock.sleep(waitingTimeMs); 261 262 } 263 } while (currentUserId != myUserId && attempt < maxAttempts); 264 Log.v(TAG, "Out of the loop, let's hope for the best..."); 265 266 if (currentUserId == UserHandle.USER_NULL) { 267 throw new IllegalStateException("App could was not authorized to check current user"); 268 } 269 assertWithMessage("current user").that(currentUserId).isEqualTo(myUserId); 270 271 // Now that the plumbing is done, go back to work... 272 Log.d(TAG, "Calling isNewUserDisclaimerAcknowledged()"); 273 boolean isAcked = dpm.isNewUserDisclaimerAcknowledged(); 274 275 Log.d(TAG, "is it: " + isAcked); 276 assertWithMessage("isNewUserDisclaimerAcknowledged()").that(isAcked).isFalse(); 277 Log.d(TAG, "Calling acknowledgeNewUserDisclaimer()"); 278 dpm.acknowledgeNewUserDisclaimer(); 279 280 Log.d(TAG, "Calling isNewUserDisclaimerAcknowledged() again"); 281 isAcked = dpm.isNewUserDisclaimerAcknowledged(); 282 Log.d(TAG, "is it now: " + isAcked); 283 assertWithMessage("isNewUserDisclaimerAcknowledged()").that(isAcked).isTrue(); 284 } 285 286 @SuppressWarnings("unused") assertAffiliatedUser(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)287 private static void assertAffiliatedUser(Context context, 288 DevicePolicyManager devicePolicyManager, ComponentName componentName) { 289 assertWithMessage("affiliated user").that(devicePolicyManager.isAffiliatedUser()).isTrue(); 290 } 291 testCreateAndManageUser_Affiliated()292 public void testCreateAndManageUser_Affiliated() throws Exception { 293 runCrossUserVerification(/* createAndManageUserFlags= */ 0, "assertAffiliatedUser"); 294 PrimaryUserService.assertCrossUserCallArrived(); 295 } 296 297 @SuppressWarnings("unused") assertEphemeralUser(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)298 private static void assertEphemeralUser(Context context, 299 DevicePolicyManager devicePolicyManager, ComponentName componentName) { 300 assertWithMessage("ephemeral user").that(devicePolicyManager.isEphemeralUser(componentName)) 301 .isTrue(); 302 } 303 testCreateAndManageUser_Ephemeral()304 public void testCreateAndManageUser_Ephemeral() throws Exception { 305 runCrossUserVerification(DevicePolicyManager.MAKE_USER_EPHEMERAL, "assertEphemeralUser"); 306 PrimaryUserService.assertCrossUserCallArrived(); 307 } 308 309 @SuppressWarnings("unused") assertAllSystemAppsInstalled(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName, Set<String> preInstalledSystemPackages)310 private static void assertAllSystemAppsInstalled(Context context, 311 DevicePolicyManager devicePolicyManager, ComponentName componentName, 312 Set<String> preInstalledSystemPackages) { 313 Log.d(TAG, "assertAllSystemAppsInstalled(): checking apps for user " + context.getUserId()); 314 315 PackageManager packageManager = context.getPackageManager(); 316 // First get a set of installed package names 317 Set<String> installedPackageNames = packageManager 318 .getInstalledApplications(/* flags= */ 0) 319 .stream() 320 .map(applicationInfo -> applicationInfo.packageName) 321 .collect(Collectors.toSet()); 322 // Then filter all package names by those that are not installed 323 Set<String> uninstalledPackageNames = packageManager 324 .getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES) 325 .stream() 326 .map(applicationInfo -> applicationInfo.packageName) 327 .filter(((Predicate<String>) installedPackageNames::contains).negate()) 328 .collect(Collectors.toSet()); 329 330 // Finally, filter out packages that are not pre-installed for the user 331 Iterator<String> iterator = uninstalledPackageNames.iterator(); 332 while (iterator.hasNext()) { 333 String pkg = iterator.next(); 334 if (!preInstalledSystemPackages.contains(pkg)) { 335 Log.i(TAG, "assertAllSystemAppsInstalled(): ignoring package " + pkg 336 + " as it's not pre-installed on current user"); 337 iterator.remove(); 338 } 339 } 340 341 // Assert that all expected apps are installed 342 assertWithMessage("uninstalled system apps").that(uninstalledPackageNames).isEmpty(); 343 } 344 testCreateAndManageUser_LeaveAllSystemApps()345 public void testCreateAndManageUser_LeaveAllSystemApps() throws Exception { 346 int currentUserId = ActivityManager.getCurrentUser(); 347 // TODO: instead of hard-coding the user type, calling getPreInstallableSystemPackages(), 348 // and passing the packages to runCrossUserVerification() / assertAllSystemAppsInstalled(), 349 // ideally the later should call um.getPreInstallableSystemPackages(um.getUsertype()) 350 // (where um is the UserManager with the context of the newly created user), 351 // but currently the list of pre-installed apps is passed to the new user in the bundle. 352 // Given that these tests will be refactored anyways, it's not worth to try to change it. 353 String newUserType = UserManager.USER_TYPE_FULL_SECONDARY; 354 Set<String> preInstalledSystemPackages = SystemUtil.callWithShellPermissionIdentity( 355 () -> UserManager.get(mContext).getPreInstallableSystemPackages(newUserType)); 356 if (preInstalledSystemPackages != null) { 357 Log.d(TAG, preInstalledSystemPackages.size() + " pre-installed system apps for " 358 + "new user of type " + newUserType + ": " + preInstalledSystemPackages); 359 } else { 360 Log.d(TAG, "no pre-installed system apps allowlist for new user of type" + newUserType); 361 } 362 363 runCrossUserVerification(/* callback= */ null, 364 DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED, "assertAllSystemAppsInstalled", 365 preInstalledSystemPackages); 366 PrimaryUserService.assertCrossUserCallArrived(); 367 } 368 runCrossUserVerification(int createAndManageUserFlags, String methodName)369 private UserHandle runCrossUserVerification(int createAndManageUserFlags, String methodName) 370 throws Exception { 371 return runCrossUserVerification(/* callback= */ null, createAndManageUserFlags, methodName, 372 /* currentUserPackages= */ null); 373 } 374 runCrossUserVerification(UserActionCallback callback, int createAndManageUserFlags, String methodName, Set<String> currentUserPackages)375 private UserHandle runCrossUserVerification(UserActionCallback callback, 376 int createAndManageUserFlags, String methodName, 377 Set<String> currentUserPackages) throws Exception { 378 return runCrossUserVerification(callback, createAndManageUserFlags, methodName, 379 /* switchUser= */ false, currentUserPackages); 380 } 381 runCrossUserVerification(UserActionCallback callback, int createAndManageUserFlags, String methodName, boolean switchUser, Set<String> currentUserPackages)382 private UserHandle runCrossUserVerification(UserActionCallback callback, 383 int createAndManageUserFlags, String methodName, boolean switchUser, 384 Set<String> currentUserPackages) throws Exception { 385 Log.d(TAG, "runCrossUserVerification(): flags=" + createAndManageUserFlags 386 + ", method=" + methodName); 387 String testUserName = "TestUser_" + System.currentTimeMillis(); 388 389 // Set affiliation id to allow communication. 390 mDevicePolicyManager.setAffiliationIds(getWho(), Collections.singleton(AFFILIATION_ID)); 391 392 ComponentName profileOwner = SecondaryUserAdminReceiver.getComponentName(getContext()); 393 394 // Pack the affiliation id in a bundle so the secondary user can get it. 395 PersistableBundle bundle = new PersistableBundle(); 396 bundle.putString(EXTRA_AFFILIATION_ID, AFFILIATION_ID); 397 bundle.putString(EXTRA_METHOD_NAME, methodName); 398 if (currentUserPackages != null) { 399 String[] array = new String[currentUserPackages.size()]; 400 currentUserPackages.toArray(array); 401 bundle.putStringArray(EXTRA_CURRENT_USER_PACKAGES, array); 402 } 403 404 Log.d(TAG, "creating user with PO " + profileOwner); 405 406 UserHandle userHandle = createAndManageUser(profileOwner, bundle, createAndManageUserFlags); 407 if (switchUser) { 408 switchUserAndWaitForBroadcasts(userHandle); 409 } else if (callback != null) { 410 startUserInBackgroundAndWaitForBroadcasts(callback, userHandle); 411 } else { 412 startUserInBackgroundAndWaitForBroadcasts(userHandle); 413 } 414 return userHandle; 415 } 416 417 // createAndManageUser should circumvent the DISALLOW_ADD_USER restriction testCreateAndManageUser_AddRestrictionSet()418 public void testCreateAndManageUser_AddRestrictionSet() throws Exception { 419 mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER); 420 421 createAndManageUser(); 422 } 423 testCreateAndManageUser_RemoveRestrictionSet()424 public void testCreateAndManageUser_RemoveRestrictionSet() throws Exception { 425 mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER); 426 427 UserHandle userHandle = createAndManageUser(); 428 429 // When the device owner itself has set the user restriction, it should still be allowed 430 // to remove a user. 431 List<UserHandle> usersOnBroadcasts = removeUserAndWaitForBroadcasts(userHandle); 432 433 assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle); 434 } 435 testUserAddedOrRemovedBroadcasts()436 public void testUserAddedOrRemovedBroadcasts() throws Exception { 437 UserHandle userHandle = createAndManageUser(); 438 439 List<UserHandle> userHandles = removeUserAndWaitForBroadcasts(userHandle); 440 441 assertWithMessage("user on broadcasts").that(userHandles).containsExactly(userHandle); 442 } 443 createAndManageUser()444 private UserHandle createAndManageUser() throws Exception { 445 return createAndManageUser(/* flags= */ 0); 446 } 447 createAndManageUser(int flags)448 private UserHandle createAndManageUser(int flags) throws Exception { 449 return createAndManageUser(/* profileOwner= */ getWho(), /* adminExtras= */ null, flags); 450 } 451 createAndManageUser(ComponentName profileOwner, PersistableBundle adminExtras, int flags)452 private UserHandle createAndManageUser(ComponentName profileOwner, 453 PersistableBundle adminExtras, int flags) throws Exception { 454 String testUserName = "TestUser_" + System.currentTimeMillis(); 455 456 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 457 getContext(), BasicAdminReceiver.ACTION_USER_ADDED); 458 459 UserHandle userHandle = callback.callAndUnregisterSelf(() -> 460 mDevicePolicyManager.createAndManageUser( 461 /* admin= */ getWho(), 462 testUserName, 463 profileOwner, 464 adminExtras, 465 flags)); 466 Log.d(TAG, "User '" + testUserName + "' created: " + userHandle); 467 return userHandle; 468 } 469 470 /** 471 * Switches to the given user, or fails if the user could not be switched or if the expected 472 * broadcasts were not received in time. 473 * 474 * @return users received in the broadcasts 475 */ switchUserAndWaitForBroadcasts(UserHandle userHandle)476 private List<UserHandle> switchUserAndWaitForBroadcasts(UserHandle userHandle) 477 throws Exception { 478 Log.d(TAG, "Switching to user " + userHandle); 479 480 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 481 getContext(), 482 BasicAdminReceiver.ACTION_USER_STARTED, BasicAdminReceiver.ACTION_USER_SWITCHED); 483 484 callback.runAndUnregisterSelf(() -> { 485 Log.d(TAG, "Calling switchUser() on callback"); 486 boolean switched = mDevicePolicyManager.switchUser(getWho(), userHandle); 487 Log.d(TAG, "Switched: " + switched); 488 assertWithMessage("switched to user %s", userHandle).that(switched).isTrue(); 489 }); 490 return callback.getUsersOnReceivedBroadcasts(); 491 } 492 493 /** 494 * Logouts the current user using {@link DevicePolicyManager#logoutUser()}, or fails if the 495 * user could not be logged out or if the expected broadcasts were not received in time. 496 * 497 * @return users received in the broadcasts 498 */ logoutUserUsingSystemApiAndWaitForBroadcasts()499 private List<UserHandle> logoutUserUsingSystemApiAndWaitForBroadcasts() 500 throws Exception { 501 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 502 getContext(), BasicAdminReceiver.ACTION_USER_SWITCHED); 503 Log.d(TAG, "Logging out current user (" + getCurrentUser() + ") using system API"); 504 505 callback.runAndUnregisterSelf(() -> { 506 int result = SystemUtil 507 .callWithShellPermissionIdentity(() -> mDevicePolicyManager.logoutUser()); 508 Log.d(TAG, "Result: " + userOperationResultToString(result)); 509 assertUserOperationResult(result, USER_OPERATION_SUCCESS, "logout user"); 510 }); 511 return callback.getUsersOnReceivedBroadcasts(); 512 } 513 514 /** 515 * Removes the given user, or fails if the user could not be removed or if the expected 516 * broadcasts were not received in time. 517 * 518 * @return users received in the broadcasts 519 */ removeUserAndWaitForBroadcasts(UserHandle userHandle)520 private List<UserHandle> removeUserAndWaitForBroadcasts(UserHandle userHandle) 521 throws Exception { 522 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 523 getContext(), BasicAdminReceiver.ACTION_USER_REMOVED); 524 525 callback.runAndUnregisterSelf(() -> { 526 boolean removed = mDevicePolicyManager.removeUser(getWho(), userHandle); 527 assertWithMessage("removed user %s", userHandle).that(removed).isTrue(); 528 }); 529 530 return callback.getUsersOnReceivedBroadcasts(); 531 } 532 userOperationResultToString(int result)533 private static String userOperationResultToString(int result) { 534 return DebugUtils.constantToString(UserManager.class, "USER_OPERATION_", result); 535 } 536 assertUserOperationResult(int actualResult, int expectedResult, String operationFormat, Object... operationArgs)537 private static void assertUserOperationResult(int actualResult, int expectedResult, 538 String operationFormat, Object... operationArgs) { 539 String operation = String.format(operationFormat, operationArgs); 540 assertWithMessage("result for %s (%s instead of %s)", operation, 541 userOperationResultToString(actualResult), 542 userOperationResultToString(expectedResult)) 543 .that(actualResult).isEqualTo(expectedResult); 544 } 545 startUserInBackgroundAndCheckResult(UserHandle userHandle, int expectedResult)546 private void startUserInBackgroundAndCheckResult(UserHandle userHandle, int expectedResult) { 547 int actualResult = mDevicePolicyManager.startUserInBackground(getWho(), userHandle); 548 assertUserOperationResult(actualResult, expectedResult, "starting user %s in background", 549 userHandle); 550 } 551 552 /** 553 * Starts the given user in background, or fails if the user could not be started or if the 554 * expected broadcasts were not received in time. 555 * 556 * @return users received in the broadcasts 557 */ startUserInBackgroundAndWaitForBroadcasts(UserHandle userHandle)558 private List<UserHandle> startUserInBackgroundAndWaitForBroadcasts(UserHandle userHandle) 559 throws Exception { 560 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 561 getContext(), BasicAdminReceiver.ACTION_USER_STARTED); 562 return startUserInBackgroundAndWaitForBroadcasts(callback, userHandle); 563 } 564 startUserInBackgroundAndWaitForBroadcasts(UserActionCallback callback, UserHandle userHandle)565 private List<UserHandle> startUserInBackgroundAndWaitForBroadcasts(UserActionCallback callback, 566 UserHandle userHandle) throws Exception { 567 callback.runAndUnregisterSelf( 568 () -> startUserInBackgroundAndCheckResult(userHandle, USER_OPERATION_SUCCESS)); 569 return callback.getUsersOnReceivedBroadcasts(); 570 } 571 stopUserAndCheckResult(UserHandle userHandle, int expectedResult)572 private void stopUserAndCheckResult(UserHandle userHandle, int expectedResult) { 573 int actualResult = mDevicePolicyManager.stopUser(getWho(), userHandle); 574 assertUserOperationResult(actualResult, expectedResult, "stopping user %s", userHandle); 575 } 576 577 /** 578 * Stops the given user, or fails if the user could not be stop or if the expected broadcasts 579 * were not received in time. 580 * 581 * @return users received in the broadcasts 582 */ stopUserAndWaitForBroadcasts(UserHandle userHandle)583 private List<UserHandle> stopUserAndWaitForBroadcasts(UserHandle userHandle) throws Exception { 584 UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions( 585 getContext(), BasicAdminReceiver.ACTION_USER_STOPPED); 586 callback.runAndUnregisterSelf( 587 () -> stopUserAndCheckResult(userHandle, USER_OPERATION_SUCCESS)); 588 return callback.getUsersOnReceivedBroadcasts(); 589 } 590 591 public static final class PrimaryUserService extends Service { 592 private static final Semaphore sSemaphore = new Semaphore(0); 593 private static String sError; 594 595 private final ICrossUserService.Stub mBinder = new ICrossUserService.Stub() { 596 public void onEnabledCalled(String error) { 597 Log.d(TAG, "PrimaryUserService.onEnabledCalled() on user " 598 + getApplicationContext().getUserId() + " with error " + error); 599 sError = error; 600 sSemaphore.release(); 601 } 602 }; 603 604 @Override onBind(Intent intent)605 public IBinder onBind(Intent intent) { 606 Log.d(TAG, "PrimaryUserService.onBind() on user " 607 + getApplicationContext().getUserId() + ": " + intent); 608 return mBinder; 609 } 610 assertCrossUserCallArrived()611 static void assertCrossUserCallArrived() throws Exception { 612 Log.v(TAG, "assertCrossUserCallArrived(): waiting " + ON_ENABLED_TIMEOUT_SECONDS 613 + " seconds for callback"); 614 assertWithMessage("cross-user call arrived in %ss", ON_ENABLED_TIMEOUT_SECONDS) 615 .that(sSemaphore.tryAcquire(ON_ENABLED_TIMEOUT_SECONDS, TimeUnit.SECONDS)) 616 .isTrue(); 617 if (sError != null) { 618 Log.e(TAG, "assertCrossUserCallArrived() had error: " + sError); 619 throw new Exception(sError); 620 } 621 } 622 } 623 624 public static final class SecondaryUserAdminReceiver extends DeviceAdminReceiver { 625 @Override onEnabled(Context context, Intent intent)626 public void onEnabled(Context context, Intent intent) { 627 Log.d(TAG, "SecondaryUserAdminReceiver.onEnabled() called on user " 628 + context.getUserId() + " and thread " + Thread.currentThread()); 629 630 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 631 ComponentName who = getComponentName(context); 632 633 // Set affiliation ids 634 Set<String> ids = Collections.singleton(intent.getStringExtra(EXTRA_AFFILIATION_ID)); 635 Log.d(TAG, "setting affiliation ids as " + ids); 636 dpm.setAffiliationIds(who, ids); 637 638 String error = null; 639 try { 640 Method method; 641 if (intent.hasExtra(EXTRA_CURRENT_USER_PACKAGES)) { 642 method = CreateAndManageUserTest.class.getDeclaredMethod( 643 intent.getStringExtra(EXTRA_METHOD_NAME), Context.class, 644 DevicePolicyManager.class, ComponentName.class, Set.class); 645 } else { 646 method = CreateAndManageUserTest.class.getDeclaredMethod( 647 intent.getStringExtra(EXTRA_METHOD_NAME), Context.class, 648 DevicePolicyManager.class, ComponentName.class); 649 } 650 method.setAccessible(true); 651 Log.d(TAG, "Calling method " + method); 652 if (intent.hasExtra(EXTRA_CURRENT_USER_PACKAGES)) { 653 String[] pkgsArray = intent.getStringArrayExtra(EXTRA_CURRENT_USER_PACKAGES); 654 Set<String> pkgs = new HashSet<>(pkgsArray.length); 655 for (String pkg : pkgsArray) { 656 pkgs.add(pkg); 657 } 658 method.invoke(null, context, dpm, who, pkgs); 659 } else { 660 method.invoke(null, context, dpm, who); 661 } 662 } catch (NoSuchMethodException | IllegalAccessException e) { 663 error = e.toString(); 664 } catch (InvocationTargetException e) { 665 error = e.getCause().toString(); 666 } 667 if (error != null) { 668 Log.e(TAG, "Error calling method: " + error); 669 } 670 671 // Call all affiliated users 672 final List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(who); 673 Log.d(TAG, "target users: " + targetUsers); 674 assertWithMessage("target users").that(targetUsers).hasSize(1); 675 676 pingTargetUser(context, dpm, targetUsers.get(0), error); 677 } 678 pingTargetUser(Context context, DevicePolicyManager dpm, UserHandle target, String error)679 private void pingTargetUser(Context context, DevicePolicyManager dpm, 680 UserHandle target, String error) { 681 Log.d(TAG, "Pinging target " + target + " with error " + error); 682 final ServiceConnection serviceConnection = new ServiceConnection() { 683 @Override 684 public void onServiceConnected(ComponentName name, IBinder service) { 685 Log.d(TAG, "onServiceConnected() is called in " + Thread.currentThread()); 686 ICrossUserService crossUserService = ICrossUserService 687 .Stub.asInterface(service); 688 try { 689 crossUserService.onEnabledCalled(error); 690 } catch (RemoteException re) { 691 Log.e(TAG, "Error when calling primary user", re); 692 // Do nothing, primary user will time out 693 } 694 } 695 696 @Override 697 public void onServiceDisconnected(ComponentName name) { 698 Log.d(TAG, "onServiceDisconnected() is called"); 699 } 700 }; 701 Intent serviceIntent = new Intent(context, PrimaryUserService.class); 702 boolean bound = dpm.bindDeviceAdminServiceAsUser( 703 getComponentName(context), 704 serviceIntent, 705 serviceConnection, 706 Context.BindServiceFlags.of(Context.BIND_AUTO_CREATE), 707 target); 708 assertWithMessage("bound to user %s using intent %s", target, serviceIntent).that(bound) 709 .isTrue(); 710 } 711 getComponentName(Context context)712 public static ComponentName getComponentName(Context context) { 713 return new ComponentName(context, SecondaryUserAdminReceiver.class); 714 } 715 } 716 } 717