1 /* 2 * Copyright (C) 2020 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 android.multiuser.cts; 18 19 import static android.Manifest.permission.CREATE_USERS; 20 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 21 import static android.Manifest.permission.QUERY_USERS; 22 import static android.content.pm.PackageManager.FEATURE_MANAGED_USERS; 23 import static android.multiuser.cts.PermissionHelper.adoptShellPermissionIdentity; 24 import static android.multiuser.cts.TestingUtils.getBooleanProperty; 25 import static android.os.UserManager.USER_OPERATION_SUCCESS; 26 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY; 27 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED; 28 29 import static com.google.common.truth.Truth.assertThat; 30 import static com.google.common.truth.Truth.assertWithMessage; 31 32 import static org.junit.Assume.assumeNoException; 33 import static org.junit.Assume.assumeTrue; 34 35 import android.app.Instrumentation; 36 import android.content.Context; 37 import android.content.pm.PackageManager; 38 import android.content.pm.UserInfo; 39 import android.graphics.Bitmap; 40 import android.os.Build; 41 import android.os.NewUserRequest; 42 import android.os.NewUserResponse; 43 import android.os.PersistableBundle; 44 import android.os.UserHandle; 45 import android.os.UserManager; 46 import android.platform.test.annotations.AppModeFull; 47 import android.platform.test.annotations.SystemUserOnly; 48 49 import androidx.test.platform.app.InstrumentationRegistry; 50 51 import com.android.bedstead.harrier.BedsteadJUnit4; 52 import com.android.bedstead.harrier.DeviceState; 53 import com.android.bedstead.harrier.annotations.EnsureHasPermission; 54 import com.android.bedstead.harrier.annotations.RequireFeature; 55 import com.android.bedstead.nene.TestApis; 56 import com.android.bedstead.nene.users.UserReference; 57 import com.android.bedstead.nene.users.UserType; 58 59 import org.junit.Before; 60 import org.junit.ClassRule; 61 import org.junit.Rule; 62 import org.junit.Test; 63 import org.junit.runner.RunWith; 64 65 import java.util.ArrayDeque; 66 import java.util.HashSet; 67 import java.util.List; 68 import java.util.Set; 69 import java.util.stream.Collectors; 70 71 @RunWith(BedsteadJUnit4.class) 72 public final class UserManagerTest { 73 74 @ClassRule 75 @Rule 76 public static final DeviceState sDeviceState = new DeviceState(); 77 78 private static final Context sContext = TestApis.context().instrumentedContext(); 79 80 private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); 81 private UserManager mUserManager; 82 83 private final String mAccountName = "test_account_name"; 84 private final String mAccountType = "test_account_type"; 85 86 @Before setUp()87 public void setUp() { 88 mUserManager = sContext.getSystemService(UserManager.class); 89 assertWithMessage("UserManager service").that(mUserManager).isNotNull(); 90 } 91 removeUser(UserHandle userHandle)92 private void removeUser(UserHandle userHandle) { 93 if (userHandle == null) { 94 return; 95 } 96 97 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 98 assertThat(mUserManager.removeUser(userHandle)).isTrue(); 99 } 100 } 101 102 /** 103 * Verify that the isUserAGoat() method always returns false for API level 30. This is 104 * because apps targeting R no longer have access to package queries by default. 105 */ 106 @Test testUserGoat_api30()107 public void testUserGoat_api30() { 108 assertWithMessage("isUserAGoat()").that(mUserManager.isUserAGoat()).isFalse(); 109 } 110 111 @Test testIsRemoveResultSuccessful()112 public void testIsRemoveResultSuccessful() { 113 assertThat(UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_REMOVED)) 114 .isTrue(); 115 assertThat(UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_DEFERRED)) 116 .isTrue(); 117 assertThat(UserManager 118 .isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED)) 119 .isTrue(); 120 assertThat(UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_UNKNOWN)) 121 .isFalse(); 122 assertThat(UserManager 123 .isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION)) 124 .isFalse(); 125 assertThat(UserManager 126 .isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND)) 127 .isFalse(); 128 assertThat( 129 UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER)) 130 .isFalse(); 131 } 132 133 @Test testIsHeadlessSystemUserMode()134 public void testIsHeadlessSystemUserMode() throws Exception { 135 boolean expected = getBooleanProperty(mInstrumentation, 136 "ro.fw.mu.headless_system_user"); 137 assertWithMessage("isHeadlessSystemUserMode()") 138 .that(UserManager.isHeadlessSystemUserMode()).isEqualTo(expected); 139 } 140 141 @Test testIsUserForeground_currentUser()142 public void testIsUserForeground_currentUser() throws Exception { 143 assertWithMessage("isUserForeground() for current user") 144 .that(mUserManager.isUserForeground()).isTrue(); 145 } 146 // TODO(b/173541467): add testIsUserForeground_backgroundUser() 147 // TODO(b/179163496): add testIsUserForeground_ tests for profile users 148 149 @Test testCloneProfile()150 public void testCloneProfile() throws Exception { 151 UserHandle userHandle = null; 152 153 // Need CREATE_USERS permission to create user in test 154 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 155 try { 156 userHandle = mUserManager.createProfile( 157 "Clone profile", UserManager.USER_TYPE_PROFILE_CLONE, new HashSet<>()); 158 } catch (UserManager.UserOperationException e) { 159 // Not all devices and user types support these profiles; skip if this one doesn't. 160 assumeNoException("Couldn't create clone profile", e); 161 return; 162 } 163 assertThat(userHandle).isNotNull(); 164 165 final Context userContext = sContext.createPackageContextAsUser("system", 0, 166 userHandle); 167 final UserManager cloneUserManager = userContext.getSystemService(UserManager.class); 168 assertThat(cloneUserManager.isMediaSharedWithParent()).isTrue(); 169 assertThat(cloneUserManager.isCredentialSharableWithParent()).isTrue(); 170 assertThat(cloneUserManager.isCloneProfile()).isTrue(); 171 assertThat(cloneUserManager.isProfile()).isTrue(); 172 assertThat(cloneUserManager.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)).isTrue(); 173 174 final List<UserInfo> list = mUserManager.getUsers(true, true, true); 175 final UserHandle finalUserHandle = userHandle; 176 final List<UserInfo> cloneUsers = list.stream().filter( 177 user -> (user.id == finalUserHandle.getIdentifier() 178 && user.isCloneProfile())) 179 .collect(Collectors.toList()); 180 assertThat(cloneUsers.size()).isEqualTo(1); 181 } finally { 182 removeUser(userHandle); 183 } 184 } 185 186 @Test 187 @RequireFeature(FEATURE_MANAGED_USERS) 188 @EnsureHasPermission({CREATE_USERS, QUERY_USERS}) testManagedProfile()189 public void testManagedProfile() throws Exception { 190 UserHandle userHandle = null; 191 192 try { 193 try { 194 userHandle = mUserManager.createProfile( 195 "Managed profile", UserManager.USER_TYPE_PROFILE_MANAGED, new HashSet<>()); 196 } catch (UserManager.UserOperationException e) { 197 // Not all devices and user types support these profiles; skip if this one doesn't. 198 assumeNoException("Couldn't create managed profile", e); 199 return; 200 } 201 assertThat(userHandle).isNotNull(); 202 203 final UserManager umOfProfile = sContext 204 .createPackageContextAsUser("android", 0, userHandle) 205 .getSystemService(UserManager.class); 206 207 // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump. 208 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { 209 assertThat(umOfProfile.isManagedProfile()).isTrue(); 210 } 211 assertThat(umOfProfile.isManagedProfile(userHandle.getIdentifier())).isTrue(); 212 assertThat(umOfProfile.isProfile()).isTrue(); 213 assertThat(umOfProfile.isUserOfType(UserManager.USER_TYPE_PROFILE_MANAGED)).isTrue(); 214 } finally { 215 removeUser(userHandle); 216 } 217 } 218 219 @Test 220 @EnsureHasPermission({QUERY_USERS}) testSystemUser()221 public void testSystemUser() throws Exception { 222 final UserManager umOfSys = sContext 223 .createPackageContextAsUser("android", 0, UserHandle.SYSTEM) 224 .getSystemService(UserManager.class); 225 226 // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump. 227 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { 228 assertThat(umOfSys.isSystemUser()).isTrue(); 229 } 230 231 // We cannot demand what type of user SYSTEM is, but we can say some things it isn't. 232 assertThat(umOfSys.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)).isFalse(); 233 assertThat(umOfSys.isUserOfType(UserManager.USER_TYPE_PROFILE_MANAGED)).isFalse(); 234 assertThat(umOfSys.isUserOfType(UserManager.USER_TYPE_FULL_GUEST)).isFalse(); 235 236 assertThat(umOfSys.isProfile()).isFalse(); 237 assertThat(umOfSys.isManagedProfile()).isFalse(); 238 assertThat(umOfSys.isManagedProfile(UserHandle.USER_SYSTEM)).isFalse(); 239 assertThat(umOfSys.isCloneProfile()).isFalse(); 240 } 241 242 @Test 243 @SystemUserOnly(reason = "Restricted users are only supported on system user.") testRestrictedUser()244 public void testRestrictedUser() throws Exception { 245 UserHandle user = null; 246 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 247 // Check that the SYSTEM user is not restricted. 248 assertThat(mUserManager.isRestrictedProfile()).isFalse(); 249 assertThat(mUserManager.isRestrictedProfile(UserHandle.SYSTEM)).isFalse(); 250 assertThat(mUserManager.getRestrictedProfileParent()).isNull(); 251 252 final UserInfo info = mUserManager.createRestrictedProfile("Restricted user"); 253 254 // If the device supports Restricted users, it must report it correctly. 255 assumeTrue("Couldn't create a restricted profile", info != null); 256 257 user = UserHandle.of(info.id); 258 assertThat(mUserManager.isRestrictedProfile(user)).isTrue(); 259 260 final Context userContext = sContext.createPackageContextAsUser("system", 0, user); 261 final UserManager userUm = userContext.getSystemService(UserManager.class); 262 // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump. 263 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { 264 assertThat(userUm.isRestrictedProfile()).isTrue(); 265 } 266 assertThat(userUm.getRestrictedProfileParent().isSystem()).isTrue(); 267 } finally { 268 removeUser(user); 269 } 270 } 271 newUserRequest()272 private NewUserRequest newUserRequest() { 273 final PersistableBundle accountOptions = new PersistableBundle(); 274 accountOptions.putString("test_account_option_key", "test_account_option_value"); 275 276 return new NewUserRequest.Builder() 277 .setName("test_user") 278 .setUserType(USER_TYPE_FULL_SECONDARY) 279 .setUserIcon(Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565)) 280 .setAccountName(mAccountName) 281 .setAccountType(mAccountType) 282 .setAccountOptions(accountOptions) 283 .build(); 284 } 285 286 @Test testSomeUserHasAccount()287 public void testSomeUserHasAccount() { 288 // TODO: (b/233197356): Replace with bedstead annotation. 289 assumeTrue(mUserManager.supportsMultipleUsers()); 290 UserHandle user = null; 291 292 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 293 assertThat(mUserManager.someUserHasAccount(mAccountName, mAccountType)).isFalse(); 294 user = mUserManager.createUser(newUserRequest()).getUser(); 295 assertThat(mUserManager.someUserHasAccount(mAccountName, mAccountType)).isTrue(); 296 } finally { 297 removeUser(user); 298 } 299 } 300 301 @Test testSomeUserHasAccount_shouldIgnoreToBeRemovedUsers()302 public void testSomeUserHasAccount_shouldIgnoreToBeRemovedUsers() { 303 // TODO: (b/233197356): Replace with bedstead annotation. 304 assumeTrue(mUserManager.supportsMultipleUsers()); 305 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 306 final NewUserResponse response = mUserManager.createUser(newUserRequest()); 307 assertThat(response.getOperationResult()).isEqualTo(USER_OPERATION_SUCCESS); 308 mUserManager.removeUser(response.getUser()); 309 assertThat(mUserManager.someUserHasAccount(mAccountName, mAccountType)).isFalse(); 310 } 311 } 312 313 @Test testCreateUser_withNewUserRequest_shouldCreateUserWithCorrectProperties()314 public void testCreateUser_withNewUserRequest_shouldCreateUserWithCorrectProperties() 315 throws PackageManager.NameNotFoundException { 316 // TODO: (b/233197356): Replace with bedstead annotation. 317 assumeTrue(mUserManager.supportsMultipleUsers()); 318 UserHandle user = null; 319 320 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 321 final NewUserRequest request = newUserRequest(); 322 final NewUserResponse response = mUserManager.createUser(request); 323 user = response.getUser(); 324 325 assertThat(response.getOperationResult()).isEqualTo(USER_OPERATION_SUCCESS); 326 assertThat(response.isSuccessful()).isTrue(); 327 assertThat(user).isNotNull(); 328 329 UserManager userManagerOfNewUser = sContext 330 .createPackageContextAsUser("android", 0, user) 331 .getSystemService(UserManager.class); 332 333 assertThat(userManagerOfNewUser.getUserName()).isEqualTo(request.getName()); 334 // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump. 335 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { 336 assertThat(userManagerOfNewUser.isUserNameSet()).isTrue(); 337 } 338 assertThat(userManagerOfNewUser.getUserType()).isEqualTo(request.getUserType()); 339 assertThat(userManagerOfNewUser.isUserOfType(request.getUserType())).isEqualTo(true); 340 // We can not test userIcon and accountOptions, 341 // because getters require MANAGE_USERS permission. 342 // And we are already testing accountName and accountType 343 // are set correctly in testSomeUserHasAccount method. 344 } finally { 345 removeUser(user); 346 } 347 } 348 349 @Test testCreateUser_withNewUserRequest_shouldNotAllowDuplicateUserAccounts()350 public void testCreateUser_withNewUserRequest_shouldNotAllowDuplicateUserAccounts() { 351 // TODO: (b/233197356): Replace with bedstead annotation. 352 assumeTrue(mUserManager.supportsMultipleUsers()); 353 UserHandle user1 = null; 354 UserHandle user2 = null; 355 356 try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) { 357 final NewUserResponse response1 = mUserManager.createUser(newUserRequest()); 358 user1 = response1.getUser(); 359 360 assertThat(response1.getOperationResult()).isEqualTo(USER_OPERATION_SUCCESS); 361 assertThat(response1.isSuccessful()).isTrue(); 362 assertThat(user1).isNotNull(); 363 364 final NewUserResponse response2 = mUserManager.createUser(newUserRequest()); 365 user2 = response2.getUser(); 366 367 assertThat(response2.getOperationResult()).isEqualTo( 368 UserManager.USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS); 369 assertThat(response2.isSuccessful()).isFalse(); 370 assertThat(user2).isNull(); 371 } finally { 372 removeUser(user1); 373 removeUser(user2); 374 } 375 } 376 377 @Test 378 @AppModeFull 379 @RequireFeature(FEATURE_MANAGED_USERS) 380 @EnsureHasPermission(INTERACT_ACROSS_USERS) getProfileParent_withNewlyCreatedProfile()381 public void getProfileParent_withNewlyCreatedProfile() { 382 final UserReference parent = TestApis.users().instrumented(); 383 try (UserReference profile = TestApis.users().createUser() 384 .parent(parent) 385 .type(TestApis.users().supportedType(UserType.MANAGED_PROFILE_TYPE_NAME)) 386 .createAndStart()) { 387 assertThat(mUserManager.getProfileParent(profile.userHandle())) 388 .isEqualTo(parent.userHandle()); 389 } 390 } 391 392 @Test 393 @AppModeFull 394 @EnsureHasPermission(INTERACT_ACROSS_USERS) getProfileParent_returnsNullForNonProfile()395 public void getProfileParent_returnsNullForNonProfile() { 396 assertThat(mUserManager.getProfileParent(TestApis.users().system().userHandle())).isNull(); 397 } 398 399 @Test 400 @EnsureHasPermission({CREATE_USERS, QUERY_USERS}) testGetRemainingCreatableUserCount()401 public void testGetRemainingCreatableUserCount() { 402 final int maxAllowedIterations = 15; 403 final String userType = USER_TYPE_FULL_SECONDARY; 404 final NewUserRequest request = new NewUserRequest.Builder().build(); 405 final ArrayDeque<UserHandle> usersCreated = new ArrayDeque<>(); 406 407 try { 408 final int initialRemainingCount = mUserManager.getRemainingCreatableUserCount(userType); 409 assertThat(initialRemainingCount).isAtLeast(0); 410 411 final int numUsersToAdd = Math.min(maxAllowedIterations, initialRemainingCount); 412 413 for (int i = 0; i < numUsersToAdd; i++) { 414 usersCreated.push(mUserManager.createUser(request).getUser()); 415 assertThat(mUserManager.getRemainingCreatableUserCount(userType)) 416 .isEqualTo(initialRemainingCount - usersCreated.size()); 417 } 418 for (int i = 0; i < numUsersToAdd; i++) { 419 mUserManager.removeUser(usersCreated.pop()); 420 assertThat(mUserManager.getRemainingCreatableUserCount(userType)) 421 .isEqualTo(initialRemainingCount - usersCreated.size()); 422 } 423 } finally { 424 usersCreated.forEach(this::removeUser); 425 } 426 } 427 428 @Test 429 @EnsureHasPermission({CREATE_USERS, QUERY_USERS}) testGetRemainingCreatableProfileCount()430 public void testGetRemainingCreatableProfileCount() { 431 final int maxAllowedIterations = 15; 432 final String type = USER_TYPE_PROFILE_MANAGED; 433 final ArrayDeque<UserHandle> profilesCreated = new ArrayDeque<>(); 434 final Set<String> disallowedPackages = new HashSet<>(); 435 try { 436 final int initialRemainingCount = 437 mUserManager.getRemainingCreatableProfileCount(type); 438 assertThat(initialRemainingCount).isAtLeast(0); 439 440 final int numUsersToAdd = Math.min(maxAllowedIterations, initialRemainingCount); 441 442 for (int i = 0; i < numUsersToAdd; i++) { 443 profilesCreated.push(mUserManager.createProfile(null, type, disallowedPackages)); 444 assertThat(mUserManager.getRemainingCreatableProfileCount(type)) 445 .isEqualTo(initialRemainingCount - profilesCreated.size()); 446 } 447 for (int i = 0; i < numUsersToAdd; i++) { 448 mUserManager.removeUser(profilesCreated.pop()); 449 assertThat(mUserManager.getRemainingCreatableProfileCount(type)) 450 .isEqualTo(initialRemainingCount - profilesCreated.size()); 451 } 452 } finally { 453 profilesCreated.forEach(this::removeUser); 454 } 455 } 456 } 457