1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.M; 4 import static android.os.Build.VERSION_CODES.N; 5 import static android.os.Build.VERSION_CODES.N_MR1; 6 import static android.os.Build.VERSION_CODES.O; 7 import static android.os.Build.VERSION_CODES.P; 8 import static android.os.Build.VERSION_CODES.Q; 9 import static android.os.Build.VERSION_CODES.R; 10 import static android.os.Build.VERSION_CODES.S; 11 import static android.os.Build.VERSION_CODES.TIRAMISU; 12 import static android.os.UserManager.RESTRICTION_SOURCE_SYSTEM; 13 import static android.os.UserManager.USER_TYPE_FULL_GUEST; 14 import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED; 15 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY; 16 import static org.robolectric.util.reflector.Reflector.reflector; 17 18 import android.Manifest.permission; 19 import android.accounts.Account; 20 import android.annotation.UserIdInt; 21 import android.app.Application; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.pm.PackageManager; 25 import android.content.pm.UserInfo; 26 import android.graphics.Bitmap; 27 import android.os.Build; 28 import android.os.Bundle; 29 import android.os.IUserManager; 30 import android.os.PersistableBundle; 31 import android.os.Process; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.os.UserManager.EnforcingUser; 35 import com.google.common.base.Preconditions; 36 import com.google.common.collect.BiMap; 37 import com.google.common.collect.HashBiMap; 38 import com.google.common.collect.ImmutableList; 39 import java.util.ArrayList; 40 import java.util.HashMap; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.Set; 45 import org.robolectric.RuntimeEnvironment; 46 import org.robolectric.annotation.HiddenApi; 47 import org.robolectric.annotation.Implementation; 48 import org.robolectric.annotation.Implements; 49 import org.robolectric.annotation.RealObject; 50 import org.robolectric.annotation.Resetter; 51 import org.robolectric.shadow.api.Shadow; 52 import org.robolectric.util.ReflectionHelpers.ClassParameter; 53 import org.robolectric.util.reflector.Accessor; 54 import org.robolectric.util.reflector.Direct; 55 import org.robolectric.util.reflector.ForType; 56 57 /** Robolectric implementation of {@link android.os.UserManager}. */ 58 @Implements(value = UserManager.class) 59 public class ShadowUserManager { 60 61 /** 62 * The default user ID user for secondary user testing, when the ID is not otherwise specified. 63 */ 64 public static final int DEFAULT_SECONDARY_USER_ID = 10; 65 66 private static final int DEFAULT_MAX_SUPPORTED_USERS = 1; 67 68 public static final int FLAG_PRIMARY = UserInfo.FLAG_PRIMARY; 69 public static final int FLAG_ADMIN = UserInfo.FLAG_ADMIN; 70 public static final int FLAG_GUEST = UserInfo.FLAG_GUEST; 71 public static final int FLAG_RESTRICTED = UserInfo.FLAG_RESTRICTED; 72 public static final int FLAG_DEMO = UserInfo.FLAG_DEMO; 73 public static final int FLAG_MANAGED_PROFILE = UserInfo.FLAG_MANAGED_PROFILE; 74 public static final int FLAG_PROFILE = UserInfo.FLAG_PROFILE; 75 public static final int FLAG_FULL = UserInfo.FLAG_FULL; 76 public static final int FLAG_SYSTEM = UserInfo.FLAG_SYSTEM; 77 public static final int FLAG_MAIN = UserInfo.FLAG_MAIN; 78 79 private final Object lock = new Object(); 80 81 @RealObject private UserManager realObject; 82 private static UserManagerState userManagerState = new UserManagerState(); 83 84 private Context context; 85 getContext()86 private Context getContext() { 87 return context; 88 } 89 90 /** 91 * Shadowing this is currently required because the real UserManager constructor stores the result 92 * of context.getApplicationContext(), which may be null due to a separate Robolectric bug. 93 */ 94 @Implementation __constructor__(Context context, IUserManager service)95 protected void __constructor__(Context context, IUserManager service) { 96 Shadow.invokeConstructor( 97 UserManager.class, 98 realObject, 99 ClassParameter.from(Context.class, context), 100 ClassParameter.from(IUserManager.class, service)); 101 this.context = context; 102 } 103 104 /** 105 * Global UserManager state. Shared across {@link UserManager}s created in different {@link 106 * Context}s. 107 */ 108 static class UserManagerState { 109 private int maxSupportedUsers = DEFAULT_MAX_SUPPORTED_USERS; 110 private boolean isMultiUserSupported = false; 111 private boolean isHeadlessSystemUserMode = false; 112 private Boolean managedProfile; 113 private Boolean cloneProfile; 114 private boolean userUnlocked = true; 115 private boolean isSystemUser = true; 116 private volatile boolean isForegroundUser = true; 117 118 private String seedAccountName; 119 private String seedAccountType; 120 private PersistableBundle seedAccountOptions; 121 private boolean enforcePermissions; 122 private int userSwitchability = UserManager.SWITCHABILITY_STATUS_OK; 123 private final Set<Account> userAccounts = new HashSet<>(); 124 125 private final Map<Integer, Integer> userPidMap = new HashMap<>(); 126 127 /** Holds the serial numbers for all users and profiles, indexed by UserHandle.id */ 128 private final BiMap<Integer, Long> userSerialNumbers = HashBiMap.create(); 129 130 /** Holds all UserStates, indexed by UserHandle.id */ 131 private final Map<Integer, UserState> userState = new HashMap<>(); 132 133 /** Holds the UserInfo for all registered users and profiles, indexed by UserHandle.id */ 134 private final Map<Integer, UserInfo> userInfoMap = new HashMap<>(); 135 136 /** 137 * Each user holds a list of UserHandles of associated profiles and user itself. User is indexed 138 * by UserHandle.id. See UserManager.getProfiles(userId). 139 */ 140 private final Map<Integer, List<UserHandle>> userProfilesListMap = new HashMap<>(); 141 142 private final Map<Integer, Bundle> userRestrictions = new HashMap<>(); 143 private final Map<String, Bundle> applicationRestrictions = new HashMap<>(); 144 145 /** 146 * Holds whether or not a managed profile can be unlocked. If a profile is not in this map, it 147 * is assume it can be unlocked. 148 */ 149 private final Map<Integer, Boolean> profileIsLocked = new HashMap<>(); 150 151 private final Map<Integer, Bitmap> userIcon = new HashMap<>(); 152 153 private int nextUserId = DEFAULT_SECONDARY_USER_ID; 154 UserManagerState()155 public UserManagerState() { 156 int id = UserHandle.USER_SYSTEM; 157 String name = "system_user"; 158 int flags = UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN; 159 160 userSerialNumbers.put(id, (long) id); 161 // Start the user as shut down. 162 userState.put(id, UserState.STATE_SHUTDOWN); 163 164 // Update UserInfo regardless if was added or not 165 userInfoMap.put(id, new UserInfo(id, name, flags)); 166 userProfilesListMap.put(id, new ArrayList<>()); 167 // getUserProfiles() includes user's handle 168 userProfilesListMap.get(id).add(new UserHandle(id)); 169 userPidMap.put(id, Process.myUid()); 170 } 171 } 172 173 /** 174 * Compared to real Android, there is no check that the package name matches the application 175 * package name and the method returns instantly. 176 * 177 * @see #setApplicationRestrictions(String, Bundle) 178 */ 179 @Implementation getApplicationRestrictions(String packageName)180 protected Bundle getApplicationRestrictions(String packageName) { 181 Bundle bundle = userManagerState.applicationRestrictions.get(packageName); 182 return bundle != null ? bundle : new Bundle(); 183 } 184 185 /** Sets the value returned by {@link UserManager#getApplicationRestrictions(String)}. */ setApplicationRestrictions(String packageName, Bundle restrictions)186 public void setApplicationRestrictions(String packageName, Bundle restrictions) { 187 userManagerState.applicationRestrictions.put(packageName, restrictions); 188 } 189 190 /** 191 * Adds a profile associated for the user that the calling process is running on. 192 * 193 * <p>The user is assigned an arbitrary unique serial number. 194 * 195 * @return the user's serial number 196 * @deprecated use either addUser() or addProfile() 197 */ 198 @Deprecated addUserProfile(UserHandle userHandle)199 public long addUserProfile(UserHandle userHandle) { 200 addProfile(UserHandle.myUserId(), userHandle.getIdentifier(), "", 0); 201 return userManagerState.userSerialNumbers.get(userHandle.getIdentifier()); 202 } 203 204 @Implementation getUserProfiles()205 protected List<UserHandle> getUserProfiles() { 206 ImmutableList.Builder<UserHandle> builder = new ImmutableList.Builder<>(); 207 List<UserHandle> profiles = userManagerState.userProfilesListMap.get(UserHandle.myUserId()); 208 if (profiles != null) { 209 return builder.addAll(profiles).build(); 210 } 211 for (List<UserHandle> profileList : userManagerState.userProfilesListMap.values()) { 212 if (profileList.contains(Process.myUserHandle())) { 213 return builder.addAll(profileList).build(); 214 } 215 } 216 return ImmutableList.of(Process.myUserHandle()); 217 } 218 219 /** 220 * If any profiles have been added using {@link #addProfile}, return those profiles. 221 * 222 * <p>Otherwise follow real android behaviour. 223 */ 224 @Implementation getProfiles(int userHandle)225 protected List<UserInfo> getProfiles(int userHandle) { 226 if (userManagerState.userProfilesListMap.containsKey(userHandle)) { 227 ArrayList<UserInfo> infos = new ArrayList<>(); 228 for (UserHandle profileHandle : userManagerState.userProfilesListMap.get(userHandle)) { 229 infos.add(userManagerState.userInfoMap.get(profileHandle.getIdentifier())); 230 } 231 return infos; 232 } 233 return reflector(UserManagerReflector.class, realObject).getProfiles(userHandle); 234 } 235 236 @Implementation(minSdk = R) getEnabledProfiles()237 protected List<UserHandle> getEnabledProfiles() { 238 ArrayList<UserHandle> userHandles = new ArrayList<>(); 239 for (UserHandle profileHandle : getAllProfiles()) { 240 if (userManagerState.userInfoMap.get(profileHandle.getIdentifier()).isEnabled()) { 241 userHandles.add(profileHandle); 242 } 243 } 244 245 return userHandles; 246 } 247 248 @Implementation(minSdk = R) getAllProfiles()249 protected List<UserHandle> getAllProfiles() { 250 ArrayList<UserHandle> userHandles = new ArrayList<>(); 251 if (userManagerState.userProfilesListMap.containsKey(getContext().getUserId())) { 252 userHandles.addAll(userManagerState.userProfilesListMap.get(getContext().getUserId())); 253 return userHandles; 254 } 255 256 userHandles.add(UserHandle.of(getContext().getUserId())); 257 return userHandles; 258 } 259 260 @Implementation getProfileParent(int userId)261 protected UserInfo getProfileParent(int userId) { 262 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 263 throw new SecurityException("Requires MANAGE_USERS permission"); 264 } 265 UserInfo profile = getUserInfo(userId); 266 if (profile == null) { 267 return null; 268 } 269 int parentUserId = profile.profileGroupId; 270 if (parentUserId == userId || parentUserId == UserInfo.NO_PROFILE_GROUP_ID) { 271 return null; 272 } else { 273 return getUserInfo(parentUserId); 274 } 275 } 276 277 @Implementation(minSdk = R) createProfile(String name, String userType, Set<String> disallowedPackages)278 protected UserHandle createProfile(String name, String userType, Set<String> disallowedPackages) { 279 int flags = getDefaultUserTypeFlags(userType); 280 flags |= FLAG_PROFILE; // assume createProfile used with a profile userType 281 if (userManagerState.enforcePermissions 282 && !hasManageUsersPermission() 283 && !hasCreateUsersPermission()) { 284 throw new SecurityException( 285 "You either need MANAGE_USERS or CREATE_USERS " 286 + "permission to create a user with flags: " 287 + flags); 288 } 289 290 if (userManagerState.userInfoMap.size() >= getMaxSupportedUsers()) { 291 return null; 292 } 293 294 int profileId = userManagerState.nextUserId++; 295 addProfile(getContext().getUserId(), profileId, name, flags); 296 userManagerState.userInfoMap.get(profileId).userType = userType; 297 return UserHandle.of(profileId); 298 } 299 getDefaultUserTypeFlags(String userType)300 private static int getDefaultUserTypeFlags(String userType) { 301 switch (userType) { 302 case UserManager.USER_TYPE_PROFILE_MANAGED: 303 return FLAG_PROFILE | FLAG_MANAGED_PROFILE; 304 case UserManager.USER_TYPE_FULL_SECONDARY: 305 return FLAG_FULL; 306 case UserManager.USER_TYPE_FULL_GUEST: 307 return FLAG_FULL | FLAG_GUEST; 308 case UserManager.USER_TYPE_FULL_DEMO: 309 return FLAG_FULL | FLAG_DEMO; 310 case UserManager.USER_TYPE_FULL_RESTRICTED: 311 return FLAG_FULL | FLAG_RESTRICTED; 312 case UserManager.USER_TYPE_FULL_SYSTEM: 313 return FLAG_FULL | FLAG_SYSTEM; 314 case UserManager.USER_TYPE_SYSTEM_HEADLESS: 315 return FLAG_SYSTEM; 316 default: 317 return 0; 318 } 319 } 320 321 /** Add a profile to be returned by {@link #getProfiles(int)}. */ addProfile( int userHandle, int profileUserHandle, String profileName, int profileFlags)322 public void addProfile( 323 int userHandle, int profileUserHandle, String profileName, int profileFlags) { 324 UserInfo profileUserInfo = new UserInfo(profileUserHandle, profileName, profileFlags); 325 addProfile(userHandle, profileUserHandle, profileUserInfo); 326 } 327 328 /** Add a profile to be returned by {@link #getProfiles(int)}. */ addProfile(int userHandle, int profileUserHandle, UserInfo profileUserInfo)329 public void addProfile(int userHandle, int profileUserHandle, UserInfo profileUserInfo) { 330 // Don't override serial number set by setSerialNumberForUser() 331 if (!userManagerState.userSerialNumbers.containsKey(profileUserHandle)) { 332 // use UserHandle id as serial number unless setSerialNumberForUser() is used 333 userManagerState.userSerialNumbers.put(profileUserHandle, (long) profileUserHandle); 334 } 335 profileUserInfo.profileGroupId = userHandle; 336 UserInfo parentUserInfo = getUserInfo(userHandle); 337 if (parentUserInfo != null) { 338 parentUserInfo.profileGroupId = userHandle; 339 } 340 userManagerState.userInfoMap.put(profileUserHandle, profileUserInfo); 341 // Insert profile to the belonging user's userProfilesList 342 userManagerState.userProfilesListMap.putIfAbsent(userHandle, new ArrayList<>()); 343 List<UserHandle> list = userManagerState.userProfilesListMap.get(userHandle); 344 UserHandle handle = new UserHandle(profileUserHandle); 345 if (!list.contains(handle)) { 346 list.add(handle); 347 } 348 } 349 350 /** Setter for {@link UserManager#isUserUnlocked()} */ setUserUnlocked(boolean userUnlocked)351 public void setUserUnlocked(boolean userUnlocked) { 352 userManagerState.userUnlocked = userUnlocked; 353 } 354 355 @Implementation(minSdk = N) isUserUnlocked()356 protected boolean isUserUnlocked() { 357 return userManagerState.userUnlocked; 358 } 359 360 /** 361 * @see #setUserState(UserHandle, UserState) 362 */ 363 @Implementation(minSdk = 24) isUserUnlocked(UserHandle handle)364 protected boolean isUserUnlocked(UserHandle handle) { 365 checkPermissions(); 366 UserState state = userManagerState.userState.get(handle.getIdentifier()); 367 368 return state == UserState.STATE_RUNNING_UNLOCKED; 369 } 370 371 /** 372 * If permissions are enforced (see {@link #enforcePermissionChecks(boolean)}) and the application 373 * doesn't have the {@link android.Manifest.permission#MANAGE_USERS} permission, throws a {@link 374 * SecurityManager} exception. 375 * 376 * @return false by default, or the value specified via {@link #setManagedProfile(boolean)} 377 * @see #enforcePermissionChecks(boolean) 378 * @see #setManagedProfile(boolean) 379 */ 380 @Implementation isManagedProfile()381 protected boolean isManagedProfile() { 382 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 383 throw new SecurityException( 384 "You need MANAGE_USERS permission to: check if specified user a " 385 + "managed profile outside your profile group"); 386 } 387 388 if (userManagerState.managedProfile != null) { 389 return userManagerState.managedProfile; 390 } 391 392 if (RuntimeEnvironment.getApiLevel() >= R) { 393 return isManagedProfile(getContext().getUserId()); 394 } 395 396 return false; 397 } 398 399 /** 400 * If permissions are enforced (see {@link #enforcePermissionChecks(boolean)}) and the application 401 * doesn't have the {@link android.Manifest.permission#MANAGE_USERS} permission, throws a {@link 402 * SecurityManager} exception. 403 * 404 * @return true if the profile added has FLAG_MANAGED_PROFILE 405 * @see #enforcePermissionChecks(boolean) 406 * @see #addProfile(int, int, String, int) 407 * @see #addUser(int, String, int) 408 */ 409 @Implementation(minSdk = N) isManagedProfile(int userHandle)410 protected boolean isManagedProfile(int userHandle) { 411 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 412 throw new SecurityException( 413 "You need MANAGE_USERS permission to: check if specified user a " 414 + "managed profile outside your profile group"); 415 } 416 UserInfo info = getUserInfo(userHandle); 417 return info != null && ((info.flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE); 418 } 419 enforcePermissionChecks(boolean enforcePermissions)420 public void enforcePermissionChecks(boolean enforcePermissions) { 421 userManagerState.enforcePermissions = enforcePermissions; 422 } 423 424 /** Setter for {@link UserManager#isManagedProfile()}. */ setManagedProfile(boolean managedProfile)425 public void setManagedProfile(boolean managedProfile) { 426 userManagerState.managedProfile = managedProfile; 427 } 428 429 /** 430 * If permissions are enforced (see {@link #enforcePermissionChecks(boolean)}) and the application 431 * doesn't have the {@link android.Manifest.permission#MANAGE_USERS} permission, throws a {@link 432 * SecurityManager} exception. 433 * 434 * @return true if the user is clone, or the value specified via {@link #setCloneProfile(boolean)} 435 * @see #enforcePermissionChecks(boolean) 436 * @see #setCloneProfile(boolean) 437 */ 438 @Implementation(minSdk = S) isCloneProfile()439 protected boolean isCloneProfile() { 440 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 441 throw new SecurityException("You need MANAGE_USERS permission to: check isCloneProfile"); 442 } 443 444 if (userManagerState.cloneProfile != null) { 445 return userManagerState.cloneProfile; 446 } 447 448 UserInfo info = getUserInfo(getContext().getUserId()); 449 return info != null && info.isCloneProfile(); 450 } 451 452 /** Setter for {@link UserManager#isCloneProfile()}. */ setCloneProfile(boolean cloneProfile)453 public void setCloneProfile(boolean cloneProfile) { 454 userManagerState.cloneProfile = cloneProfile; 455 } 456 457 @Implementation(minSdk = R) isProfile()458 protected boolean isProfile() { 459 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 460 throw new SecurityException( 461 "You need INTERACT_ACROSS_USERS or MANAGE_USERS permission to: check isProfile"); 462 } 463 464 return getUserInfo(getContext().getUserId()).isProfile(); 465 } 466 467 @Implementation(minSdk = R) isUserOfType(String userType)468 protected boolean isUserOfType(String userType) { 469 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 470 throw new SecurityException("You need MANAGE_USERS permission to: check user type"); 471 } 472 473 UserInfo info = getUserInfo(getContext().getUserId()); 474 return info != null && info.userType != null && info.userType.equals(userType); 475 } 476 477 @Implementation(minSdk = R) isSameProfileGroup(UserHandle user, UserHandle otherUser)478 protected boolean isSameProfileGroup(UserHandle user, UserHandle otherUser) { 479 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 480 throw new SecurityException( 481 "You need MANAGE_USERS permission to: check if in the same profile group"); 482 } 483 484 UserInfo userInfo = userManagerState.userInfoMap.get(user.getIdentifier()); 485 UserInfo otherUserInfo = userManagerState.userInfoMap.get(otherUser.getIdentifier()); 486 487 if (userInfo == null 488 || otherUserInfo == null 489 || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID 490 || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 491 return false; 492 } 493 494 return userInfo.profileGroupId == otherUserInfo.profileGroupId; 495 } 496 497 @Implementation hasUserRestriction(String restrictionKey, UserHandle userHandle)498 protected boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) { 499 synchronized (lock) { 500 Bundle bundle = userManagerState.userRestrictions.get(userHandle.getIdentifier()); 501 return bundle != null && bundle.getBoolean(restrictionKey); 502 } 503 } 504 505 /** 506 * Shadows UserManager.setUserRestriction() API. This allows UserManager.hasUserRestriction() to 507 * return meaningful results in test environment; thus, allowing test to verify the invoking of 508 * UserManager.setUserRestriction(). 509 */ 510 @Implementation setUserRestriction(String key, boolean value, UserHandle userHandle)511 protected void setUserRestriction(String key, boolean value, UserHandle userHandle) { 512 Bundle bundle = getUserRestrictionsForUser(userHandle); 513 synchronized (lock) { 514 bundle.putBoolean(key, value); 515 } 516 } 517 518 @Implementation setUserRestriction(String key, boolean value)519 protected void setUserRestriction(String key, boolean value) { 520 setUserRestriction(key, value, Process.myUserHandle()); 521 } 522 523 /** 524 * @deprecated When possible, please use the real Android framework API {@link 525 * UserManager#setUserRestriction()}. 526 */ 527 @Deprecated setUserRestriction(UserHandle userHandle, String restrictionKey, boolean value)528 public void setUserRestriction(UserHandle userHandle, String restrictionKey, boolean value) { 529 setUserRestriction(restrictionKey, value, userHandle); 530 } 531 532 /** Removes all user restrictions set of a user identified by {@code userHandle}. */ clearUserRestrictions(UserHandle userHandle)533 public void clearUserRestrictions(UserHandle userHandle) { 534 userManagerState.userRestrictions.remove(userHandle.getIdentifier()); 535 } 536 537 @Implementation getUserRestrictions(UserHandle userHandle)538 protected Bundle getUserRestrictions(UserHandle userHandle) { 539 return new Bundle(getUserRestrictionsForUser(userHandle)); 540 } 541 getUserRestrictionsForUser(UserHandle userHandle)542 private Bundle getUserRestrictionsForUser(UserHandle userHandle) { 543 synchronized (lock) { 544 Bundle bundle = userManagerState.userRestrictions.get(userHandle.getIdentifier()); 545 if (bundle == null) { 546 bundle = new Bundle(); 547 userManagerState.userRestrictions.put(userHandle.getIdentifier(), bundle); 548 } 549 return bundle; 550 } 551 } 552 553 /** 554 * @see #addProfile(int, int, String, int) 555 * @see #addUser(int, String, int) 556 */ 557 @Implementation getSerialNumberForUser(UserHandle userHandle)558 protected long getSerialNumberForUser(UserHandle userHandle) { 559 Long result = userManagerState.userSerialNumbers.get(userHandle.getIdentifier()); 560 return result == null ? -1L : result; 561 } 562 563 /** 564 * {@link #addUser} uses UserHandle for serialNumber. setSerialNumberForUser() allows assigning an 565 * arbitrary serialNumber. Some test use serialNumber!=0 as secondary user check, so it's 566 * necessary to "fake" the serialNumber to a non-zero value. 567 */ setSerialNumberForUser(UserHandle userHandle, long serialNumber)568 public void setSerialNumberForUser(UserHandle userHandle, long serialNumber) { 569 userManagerState.userSerialNumbers.put(userHandle.getIdentifier(), serialNumber); 570 } 571 572 /** 573 * @see #addProfile(int, int, String, int) 574 * @see #addUser(int, String, int) 575 */ 576 @Implementation getUserForSerialNumber(long serialNumber)577 protected UserHandle getUserForSerialNumber(long serialNumber) { 578 Integer userHandle = userManagerState.userSerialNumbers.inverse().get(serialNumber); 579 return userHandle == null ? null : new UserHandle(userHandle); 580 } 581 582 /** 583 * @see #addProfile(int, int, String, int) 584 * @see #addUser(int, String, int) 585 */ 586 @Implementation getUserSerialNumber(@serIdInt int userHandle)587 protected int getUserSerialNumber(@UserIdInt int userHandle) { 588 Long result = userManagerState.userSerialNumbers.get(userHandle); 589 return result != null ? result.intValue() : -1; 590 } 591 getUserName(@serIdInt int userHandle)592 private String getUserName(@UserIdInt int userHandle) { 593 UserInfo user = getUserInfo(userHandle); 594 return user == null ? "" : user.name; 595 } 596 597 /** 598 * Returns the name of the user. 599 * 600 * <p>On real Android, if a UserHandle.USER_SYSTEM user is found but does not have a name, it will 601 * return a name like "Owner". In Robolectric, the USER_SYSTEM user always has a name. 602 */ 603 @Implementation(minSdk = Q) getUserName()604 protected String getUserName() { 605 if (RuntimeEnvironment.getApiLevel() >= R) { 606 return getUserName(getContext().getUserId()); 607 } 608 609 return getUserName(UserHandle.myUserId()); 610 } 611 612 @Implementation(minSdk = R) setUserName(String name)613 protected void setUserName(String name) { 614 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 615 throw new SecurityException("You need MANAGE_USERS permission to: rename users"); 616 } 617 UserInfo user = getUserInfo(getContext().getUserId()); 618 user.name = name; 619 } 620 621 @Implementation(minSdk = Q) getUserIcon()622 protected Bitmap getUserIcon() { 623 if (userManagerState.enforcePermissions 624 && !hasManageUsersPermission() 625 && !hasGetAccountsPrivilegedPermission()) { 626 throw new SecurityException( 627 "You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED permissions to: get user icon"); 628 } 629 630 int userId = UserHandle.myUserId(); 631 if (RuntimeEnvironment.getApiLevel() >= R) { 632 userId = getContext().getUserId(); 633 } 634 635 return userManagerState.userIcon.get(userId); 636 } 637 638 @Implementation(minSdk = Q) setUserIcon(Bitmap icon)639 protected void setUserIcon(Bitmap icon) { 640 if (userManagerState.enforcePermissions && !hasManageUsersPermission()) { 641 throw new SecurityException("You need MANAGE_USERS permission to: update users"); 642 } 643 644 int userId = UserHandle.myUserId(); 645 if (RuntimeEnvironment.getApiLevel() >= R) { 646 userId = getContext().getUserId(); 647 } 648 649 userManagerState.userIcon.put(userId, icon); 650 } 651 652 /** 653 * @return user id for given user serial number. 654 */ 655 @HiddenApi 656 @Implementation 657 @UserIdInt getUserHandle(int serialNumber)658 protected int getUserHandle(int serialNumber) { 659 Integer userHandle = userManagerState.userSerialNumbers.inverse().get((long) serialNumber); 660 return userHandle == null ? -1 : userHandle; 661 } 662 663 @HiddenApi 664 @Implementation(minSdk = R) getUserHandles(boolean excludeDying)665 protected List<UserHandle> getUserHandles(boolean excludeDying) { 666 ArrayList<UserHandle> userHandles = new ArrayList<>(); 667 for (int id : userManagerState.userSerialNumbers.keySet()) { 668 userHandles.addAll(userManagerState.userProfilesListMap.get(id)); 669 } 670 return userHandles; 671 } 672 673 @HiddenApi 674 @Implementation getMaxSupportedUsers()675 protected static int getMaxSupportedUsers() { 676 return userManagerState.maxSupportedUsers; 677 } 678 setMaxSupportedUsers(int maxSupportedUsers)679 public void setMaxSupportedUsers(int maxSupportedUsers) { 680 userManagerState.maxSupportedUsers = maxSupportedUsers; 681 } 682 hasManageUsersPermission()683 private boolean hasManageUsersPermission() { 684 return getContext() 685 .getPackageManager() 686 .checkPermission(permission.MANAGE_USERS, getContext().getPackageName()) 687 == PackageManager.PERMISSION_GRANTED; 688 } 689 hasCreateUsersPermission()690 private boolean hasCreateUsersPermission() { 691 return getContext() 692 .getPackageManager() 693 .checkPermission(permission.CREATE_USERS, getContext().getPackageName()) 694 == PackageManager.PERMISSION_GRANTED; 695 } 696 hasModifyQuietModePermission()697 private boolean hasModifyQuietModePermission() { 698 return getContext() 699 .getPackageManager() 700 .checkPermission(permission.MODIFY_QUIET_MODE, getContext().getPackageName()) 701 == PackageManager.PERMISSION_GRANTED; 702 } 703 hasGetAccountsPrivilegedPermission()704 private boolean hasGetAccountsPrivilegedPermission() { 705 return getContext() 706 .getPackageManager() 707 .checkPermission(permission.GET_ACCOUNTS_PRIVILEGED, getContext().getPackageName()) 708 == PackageManager.PERMISSION_GRANTED; 709 } 710 checkPermissions()711 private void checkPermissions() { 712 // TODO Ensure permissions 713 // throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS 714 // permission " 715 // + "to: check " + name);throw new SecurityException(); 716 } 717 718 /** 719 * @return false by default, or the value specified via {@link #setIsDemoUser(boolean)} 720 */ 721 @Implementation(minSdk = N_MR1) isDemoUser()722 protected boolean isDemoUser() { 723 return getUserInfo(UserHandle.myUserId()).isDemo(); 724 } 725 726 /** 727 * Sets that the current user is a demo user; controls the return value of {@link 728 * UserManager#isDemoUser()}. 729 * 730 * @deprecated Use {@link ShadowUserManager#addUser(int, String, int)} to create a demo user 731 * instead of changing default user flags. 732 */ 733 @Deprecated setIsDemoUser(boolean isDemoUser)734 public void setIsDemoUser(boolean isDemoUser) { 735 UserInfo userInfo = getUserInfo(UserHandle.myUserId()); 736 if (isDemoUser) { 737 userInfo.flags |= UserInfo.FLAG_DEMO; 738 } else { 739 userInfo.flags &= ~UserInfo.FLAG_DEMO; 740 } 741 } 742 743 /** 744 * @return 'true' by default, or the value specified via {@link #setIsSystemUser(boolean)} 745 */ 746 @Implementation(minSdk = M) isSystemUser()747 protected boolean isSystemUser() { 748 if (userManagerState.isSystemUser == false) { 749 return false; 750 } else { 751 return reflector(UserManagerReflector.class, realObject).isSystemUser(); 752 } 753 } 754 755 /** 756 * Sets that the current user is the system user; controls the return value of {@link 757 * UserManager#isSystemUser()}. 758 * 759 * @deprecated Use {@link ShadowUserManager#addUser(int, String, int)} to create a system user 760 * instead of changing default user flags. 761 */ 762 @Deprecated setIsSystemUser(boolean isSystemUser)763 public void setIsSystemUser(boolean isSystemUser) { 764 userManagerState.isSystemUser = isSystemUser; 765 } 766 767 /** 768 * Sets that the current user is the primary user; controls the return value of {@link 769 * UserManager#isPrimaryUser()}. 770 * 771 * @deprecated Use {@link ShadowUserManager#addUser(int, String, int)} to create a primary user 772 * instead of changing default user flags. 773 */ 774 @Deprecated setIsPrimaryUser(boolean isPrimaryUser)775 public void setIsPrimaryUser(boolean isPrimaryUser) { 776 UserInfo userInfo = getUserInfo(UserHandle.myUserId()); 777 if (isPrimaryUser) { 778 userInfo.flags |= UserInfo.FLAG_PRIMARY; 779 } else { 780 userInfo.flags &= ~UserInfo.FLAG_PRIMARY; 781 } 782 } 783 784 /** 785 * @return 'false' by default, or the value specified via {@link #setIsLinkedUser(boolean)} 786 */ 787 @Implementation isLinkedUser()788 protected boolean isLinkedUser() { 789 return isRestrictedProfile(); 790 } 791 792 /** 793 * Sets that the current user is the linked user; controls the return value of {@link 794 * UserManager#isLinkedUser()}. 795 * 796 * @deprecated Use {@link ShadowUserManager#addUser(int, String, int)} to create a linked user 797 * instead of changing default user flags. 798 */ 799 @Deprecated setIsLinkedUser(boolean isLinkedUser)800 public void setIsLinkedUser(boolean isLinkedUser) { 801 setIsRestrictedProfile(isLinkedUser); 802 } 803 804 /** 805 * Returns 'false' by default, or the value specified via {@link 806 * #setIsRestrictedProfile(boolean)}. 807 */ 808 @Implementation(minSdk = P) isRestrictedProfile()809 protected boolean isRestrictedProfile() { 810 return getUserInfo(UserHandle.myUserId()).isRestricted(); 811 } 812 813 /** 814 * Sets this process running under a restricted profile; controls the return value of {@link 815 * UserManager#isRestrictedProfile()}. 816 * 817 * @deprecated use {@link ShadowUserManager#addUser()} instead 818 */ 819 @Deprecated setIsRestrictedProfile(boolean isRestrictedProfile)820 public void setIsRestrictedProfile(boolean isRestrictedProfile) { 821 if (RuntimeEnvironment.getApiLevel() >= R) { 822 setUserType(isRestrictedProfile ? USER_TYPE_FULL_RESTRICTED : USER_TYPE_FULL_SECONDARY); 823 return; 824 } 825 UserInfo userInfo = getUserInfo(UserHandle.myUserId()); 826 if (isRestrictedProfile) { 827 userInfo.flags |= UserInfo.FLAG_RESTRICTED; 828 } else { 829 userInfo.flags &= ~UserInfo.FLAG_RESTRICTED; 830 } 831 } 832 833 /** 834 * Sets that the current user is the guest user; controls the return value of {@link 835 * UserManager#isGuestUser()}. 836 * 837 * @deprecated Use {@link ShadowUserManager#addUser(int, String, int)} to create a guest user 838 * instead of changing default user flags. 839 */ 840 @Deprecated setIsGuestUser(boolean isGuestUser)841 public void setIsGuestUser(boolean isGuestUser) { 842 if (RuntimeEnvironment.getApiLevel() >= R) { 843 setUserType(isGuestUser ? USER_TYPE_FULL_GUEST : USER_TYPE_FULL_SECONDARY); 844 return; 845 } 846 UserInfo userInfo = getUserInfo(UserHandle.myUserId()); 847 if (isGuestUser) { 848 userInfo.flags |= UserInfo.FLAG_GUEST; 849 } else { 850 userInfo.flags &= ~UserInfo.FLAG_GUEST; 851 } 852 } 853 setIsUserEnabled(int userId, boolean enabled)854 public void setIsUserEnabled(int userId, boolean enabled) { 855 UserInfo userInfo = getUserInfo(userId); 856 if (enabled) { 857 userInfo.flags &= ~UserInfo.FLAG_DISABLED; 858 } else { 859 userInfo.flags |= UserInfo.FLAG_DISABLED; 860 } 861 } 862 863 /** 864 * @see #setUserState(UserHandle, UserState) 865 */ 866 @Implementation isUserRunning(UserHandle handle)867 protected boolean isUserRunning(UserHandle handle) { 868 checkPermissions(); 869 UserState state = userManagerState.userState.get(handle.getIdentifier()); 870 871 if (state == UserState.STATE_RUNNING_LOCKED 872 || state == UserState.STATE_RUNNING_UNLOCKED 873 || state == UserState.STATE_RUNNING_UNLOCKING) { 874 return true; 875 } else { 876 return false; 877 } 878 } 879 880 /** 881 * @see #setUserState(UserHandle, UserState) 882 */ 883 @Implementation isUserRunningOrStopping(UserHandle handle)884 protected boolean isUserRunningOrStopping(UserHandle handle) { 885 checkPermissions(); 886 UserState state = userManagerState.userState.get(handle.getIdentifier()); 887 888 if (state == UserState.STATE_RUNNING_LOCKED 889 || state == UserState.STATE_RUNNING_UNLOCKED 890 || state == UserState.STATE_RUNNING_UNLOCKING 891 || state == UserState.STATE_STOPPING) { 892 return true; 893 } else { 894 return false; 895 } 896 } 897 898 /** 899 * @see #setUserState(UserHandle, UserState) 900 */ 901 @Implementation(minSdk = R) isUserUnlockingOrUnlocked(UserHandle handle)902 protected boolean isUserUnlockingOrUnlocked(UserHandle handle) { 903 checkPermissions(); 904 UserState state = userManagerState.userState.get(handle.getIdentifier()); 905 906 return state == UserState.STATE_RUNNING_UNLOCKING || state == UserState.STATE_RUNNING_UNLOCKED; 907 } 908 909 /** 910 * Describes the current state of the user. State can be set using {@link 911 * #setUserState(UserHandle, UserState)}. 912 */ 913 public enum UserState { 914 // User is first coming up. 915 STATE_BOOTING, 916 // User is in the locked state. 917 STATE_RUNNING_LOCKED, 918 // User is in the unlocking state. 919 STATE_RUNNING_UNLOCKING, 920 // User is in the running state. 921 STATE_RUNNING_UNLOCKED, 922 // User is in the initial process of being stopped. 923 STATE_STOPPING, 924 // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN. 925 STATE_SHUTDOWN 926 } 927 928 /** 929 * Sets the current state for a given user, see {@link UserManager#isUserRunning(UserHandle)} and 930 * {@link UserManager#isUserRunningOrStopping(UserHandle)} 931 */ setUserState(UserHandle handle, UserState state)932 public void setUserState(UserHandle handle, UserState state) { 933 userManagerState.userState.put(handle.getIdentifier(), state); 934 } 935 936 /** 937 * Query whether the quiet mode is enabled for a managed profile. 938 * 939 * <p>This method checks whether the user handle corresponds to a managed profile, and then query 940 * its state. When quiet, the user is not running. 941 */ 942 @Implementation(minSdk = N) isQuietModeEnabled(UserHandle userHandle)943 protected boolean isQuietModeEnabled(UserHandle userHandle) { 944 // Return false if this is not a managed profile (this is the OS's behavior). 945 if (!isManagedProfileWithoutPermission(userHandle)) { 946 return false; 947 } 948 949 UserInfo info = getUserInfo(userHandle.getIdentifier()); 950 return (info.flags & UserInfo.FLAG_QUIET_MODE) == UserInfo.FLAG_QUIET_MODE; 951 } 952 953 /** 954 * Request the quiet mode. 955 * 956 * <p>This will succeed unless {@link #setProfileIsLocked(UserHandle, boolean)} is called with 957 * {@code true} for the managed profile, in which case it will always fail. 958 */ 959 @Implementation(minSdk = Q) requestQuietModeEnabled(boolean enableQuietMode, UserHandle userHandle)960 protected boolean requestQuietModeEnabled(boolean enableQuietMode, UserHandle userHandle) { 961 if (userManagerState.enforcePermissions 962 && !hasManageUsersPermission() 963 && !hasModifyQuietModePermission()) { 964 throw new SecurityException("Requires MANAGE_USERS or MODIFY_QUIET_MODE permission"); 965 } 966 Preconditions.checkArgument(isManagedProfileWithoutPermission(userHandle)); 967 int userProfileHandle = userHandle.getIdentifier(); 968 UserInfo info = getUserInfo(userHandle.getIdentifier()); 969 if (enableQuietMode) { 970 userManagerState.userState.put(userProfileHandle, UserState.STATE_SHUTDOWN); 971 info.flags |= UserInfo.FLAG_QUIET_MODE; 972 } else { 973 if (userManagerState.profileIsLocked.getOrDefault(userProfileHandle, false)) { 974 return false; 975 } 976 userManagerState.userState.put(userProfileHandle, UserState.STATE_RUNNING_UNLOCKED); 977 info.flags &= ~UserInfo.FLAG_QUIET_MODE; 978 } 979 980 if (enableQuietMode) { 981 sendQuietModeBroadcast(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE, userHandle); 982 } else { 983 sendQuietModeBroadcast(Intent.ACTION_MANAGED_PROFILE_AVAILABLE, userHandle); 984 sendQuietModeBroadcast(Intent.ACTION_MANAGED_PROFILE_UNLOCKED, userHandle); 985 } 986 987 return true; 988 } 989 990 /** 991 * If the current application has the necessary rights, it will receive the background action too. 992 */ sendQuietModeBroadcast(String action, UserHandle profileHandle)993 protected void sendQuietModeBroadcast(String action, UserHandle profileHandle) { 994 Intent intent = new Intent(action); 995 intent.putExtra(Intent.EXTRA_USER, profileHandle); 996 intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY); 997 // Send the broadcast to the context-registered receivers. 998 getContext().sendBroadcast(intent); 999 } 1000 1001 /** 1002 * Check if a profile is managed, not checking permissions. 1003 * 1004 * <p>This is useful to implement other methods. 1005 */ isManagedProfileWithoutPermission(UserHandle userHandle)1006 private boolean isManagedProfileWithoutPermission(UserHandle userHandle) { 1007 UserInfo info = getUserInfo(userHandle.getIdentifier()); 1008 return (info != null && ((info.flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE)); 1009 } 1010 setProfileIsLocked(UserHandle profileHandle, boolean isLocked)1011 public void setProfileIsLocked(UserHandle profileHandle, boolean isLocked) { 1012 userManagerState.profileIsLocked.put(profileHandle.getIdentifier(), isLocked); 1013 } 1014 1015 @Implementation(minSdk = Build.VERSION_CODES.N) getSerialNumbersOfUsers(boolean excludeDying)1016 protected long[] getSerialNumbersOfUsers(boolean excludeDying) { 1017 return getUsers().stream() 1018 .map(userInfo -> getUserSerialNumber(userInfo.getUserHandle().getIdentifier())) 1019 .mapToLong(l -> l) 1020 .toArray(); 1021 } 1022 1023 @Implementation getUsers()1024 protected List<UserInfo> getUsers() { 1025 return new ArrayList<>(userManagerState.userInfoMap.values()); 1026 } 1027 1028 @Implementation getUserInfo(int userHandle)1029 protected UserInfo getUserInfo(int userHandle) { 1030 return userManagerState.userInfoMap.get(userHandle); 1031 } 1032 1033 /** 1034 * Sets whether switching users is allowed or not; controls the return value of {@link 1035 * UserManager#canSwitchUser()} 1036 * 1037 * @deprecated use {@link #setUserSwitchability} instead 1038 */ 1039 @Deprecated setCanSwitchUser(boolean canSwitchUser)1040 public void setCanSwitchUser(boolean canSwitchUser) { 1041 setUserSwitchability( 1042 canSwitchUser 1043 ? UserManager.SWITCHABILITY_STATUS_OK 1044 : UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED); 1045 } 1046 1047 @Implementation(minSdk = Build.VERSION_CODES.N) getSeedAccountName()1048 protected String getSeedAccountName() { 1049 return userManagerState.seedAccountName; 1050 } 1051 1052 /** Setter for {@link UserManager#getSeedAccountName()} */ setSeedAccountName(String seedAccountName)1053 public void setSeedAccountName(String seedAccountName) { 1054 userManagerState.seedAccountName = seedAccountName; 1055 } 1056 1057 @Implementation(minSdk = Build.VERSION_CODES.N) getSeedAccountType()1058 protected String getSeedAccountType() { 1059 return userManagerState.seedAccountType; 1060 } 1061 1062 /** Setter for {@link UserManager#getSeedAccountType()} */ setSeedAccountType(String seedAccountType)1063 public void setSeedAccountType(String seedAccountType) { 1064 userManagerState.seedAccountType = seedAccountType; 1065 } 1066 1067 @Implementation(minSdk = Build.VERSION_CODES.N) getSeedAccountOptions()1068 protected PersistableBundle getSeedAccountOptions() { 1069 return userManagerState.seedAccountOptions; 1070 } 1071 1072 /** Setter for {@link UserManager#getSeedAccountOptions()} */ setSeedAccountOptions(PersistableBundle seedAccountOptions)1073 public void setSeedAccountOptions(PersistableBundle seedAccountOptions) { 1074 userManagerState.seedAccountOptions = seedAccountOptions; 1075 } 1076 1077 @Implementation(minSdk = Build.VERSION_CODES.N) clearSeedAccountData()1078 protected void clearSeedAccountData() { 1079 userManagerState.seedAccountName = null; 1080 userManagerState.seedAccountType = null; 1081 userManagerState.seedAccountOptions = null; 1082 } 1083 1084 @Implementation removeUser(int userHandle)1085 protected boolean removeUser(int userHandle) { 1086 if (!userManagerState.userInfoMap.containsKey(userHandle)) { 1087 return false; 1088 } 1089 userManagerState.userInfoMap.remove(userHandle); 1090 userManagerState.userPidMap.remove(userHandle); 1091 userManagerState.userSerialNumbers.remove(userHandle); 1092 userManagerState.userState.remove(userHandle); 1093 userManagerState.userRestrictions.remove(userHandle); 1094 userManagerState.profileIsLocked.remove(userHandle); 1095 userManagerState.userIcon.remove(userHandle); 1096 userManagerState.userProfilesListMap.remove(userHandle); 1097 // if it's a profile, remove from the belong list in userManagerState.userProfilesListMap 1098 UserHandle profileHandle = new UserHandle(userHandle); 1099 for (List<UserHandle> list : userManagerState.userProfilesListMap.values()) { 1100 if (list.remove(profileHandle)) { 1101 break; 1102 } 1103 } 1104 return true; 1105 } 1106 1107 @Implementation(minSdk = Q) removeUser(UserHandle user)1108 protected boolean removeUser(UserHandle user) { 1109 return removeUser(user.getIdentifier()); 1110 } 1111 1112 @Implementation(minSdk = TIRAMISU) removeUserWhenPossible(UserHandle user, boolean overrideDevicePolicy)1113 protected int removeUserWhenPossible(UserHandle user, boolean overrideDevicePolicy) { 1114 return removeUser(user.getIdentifier()) 1115 ? UserManager.REMOVE_RESULT_REMOVED 1116 : UserManager.REMOVE_RESULT_ERROR_UNKNOWN; 1117 } 1118 1119 @Implementation(minSdk = N) supportsMultipleUsers()1120 protected static boolean supportsMultipleUsers() { 1121 return userManagerState.isMultiUserSupported; 1122 } 1123 1124 /** 1125 * Sets whether multiple users are supported; controls the return value of {@link 1126 * UserManager#supportsMultipleUser}. 1127 */ setSupportsMultipleUsers(boolean isMultiUserSupported)1128 public void setSupportsMultipleUsers(boolean isMultiUserSupported) { 1129 userManagerState.isMultiUserSupported = isMultiUserSupported; 1130 } 1131 1132 /** 1133 * Switches the current user to {@code userHandle}. 1134 * 1135 * @param userId the integer handle of the user, where 0 is the primary user. 1136 */ switchUser(int userId)1137 public void switchUser(int userId) { 1138 if (!userManagerState.userInfoMap.containsKey(userId)) { 1139 throw new UnsupportedOperationException("Must add user before switching to it"); 1140 } 1141 1142 ShadowProcess.setUid(userManagerState.userPidMap.get(userId)); 1143 1144 Application application = (Application) getContext().getApplicationContext(); 1145 ShadowContextImpl shadowContext = Shadow.extract(application.getBaseContext()); 1146 shadowContext.setUserId(userId); 1147 1148 if (RuntimeEnvironment.getApiLevel() >= R) { 1149 reflector(UserManagerReflector.class, realObject).setUserId(userId); 1150 } 1151 } 1152 1153 /** 1154 * Creates a user with the specified name, userId and flags. 1155 * 1156 * @param id the unique id of user 1157 * @param name name of the user 1158 * @param flags 16 bits for user type. See {@link UserInfo#flags} 1159 * @return a handle to the new user 1160 */ addUser(int id, String name, int flags)1161 public UserHandle addUser(int id, String name, int flags) { 1162 UserHandle userHandle = 1163 id == UserHandle.USER_SYSTEM ? Process.myUserHandle() : new UserHandle(id); 1164 1165 // Don't override serial number set by setSerialNumberForUser() 1166 if (!userManagerState.userSerialNumbers.containsKey(id)) { 1167 // use UserHandle id as serial number unless setSerialNumberForUser() is used 1168 userManagerState.userSerialNumbers.put(id, (long) id); 1169 } 1170 // Start the user as shut down. 1171 userManagerState.userState.put(id, UserState.STATE_SHUTDOWN); 1172 1173 // Update UserInfo regardless if was added or not 1174 userManagerState.userInfoMap.put(id, new UserInfo(id, name, flags)); 1175 if (!userManagerState.userProfilesListMap.containsKey(id)) { 1176 userManagerState.userProfilesListMap.put(id, new ArrayList<>()); 1177 // getUserProfiles() includes user's handle 1178 userManagerState.userProfilesListMap.get(id).add(new UserHandle(id)); 1179 userManagerState.userPidMap.put( 1180 id, 1181 id == UserHandle.USER_SYSTEM 1182 ? Process.myUid() 1183 : id * UserHandle.PER_USER_RANGE + ShadowProcess.getRandomApplicationUid()); 1184 } 1185 return userHandle; 1186 } 1187 1188 /** 1189 * Returns {@code true} by default, or the value specified via {@link #setCanSwitchUser(boolean)}. 1190 */ 1191 @Implementation(minSdk = N, maxSdk = Q) canSwitchUsers()1192 protected boolean canSwitchUsers() { 1193 return getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK; 1194 } 1195 1196 @Implementation(minSdk = Q) getUserSwitchability()1197 protected int getUserSwitchability() { 1198 return userManagerState.userSwitchability; 1199 } 1200 1201 /** Sets the user switchability for all users. */ setUserSwitchability(int switchability)1202 public void setUserSwitchability(int switchability) { 1203 userManagerState.userSwitchability = switchability; 1204 } 1205 1206 @Implementation(minSdk = R) hasUserRestrictionForUser(String restrictionKey, UserHandle userHandle)1207 protected boolean hasUserRestrictionForUser(String restrictionKey, UserHandle userHandle) { 1208 return hasUserRestriction(restrictionKey, userHandle); 1209 } 1210 setUserType(String userType)1211 private void setUserType(String userType) { 1212 UserInfo userInfo = getUserInfo(UserHandle.myUserId()); 1213 userInfo.userType = userType; 1214 } 1215 1216 /** 1217 * Request the quiet mode. 1218 * 1219 * <p>If {@link #setProfileIsLocked(UserHandle, boolean)} is called with {@code true} for the 1220 * managed profile a request to disable the quiet mode will fail and return {@code false} (i.e. as 1221 * if the user refused to authenticate). Otherwise, the call will always succeed and return {@code 1222 * true}. 1223 * 1224 * <p>This method simply re-directs to {@link ShadowUserManager#requestQuietModeEnabled(boolean, 1225 * UserHandle)} as it already has the desired behavior irrespective of the flag's value. 1226 */ 1227 @Implementation(minSdk = R) requestQuietModeEnabled( boolean enableQuietMode, UserHandle userHandle, int flags)1228 protected boolean requestQuietModeEnabled( 1229 boolean enableQuietMode, UserHandle userHandle, int flags) { 1230 return requestQuietModeEnabled(enableQuietMode, userHandle); 1231 } 1232 1233 @Implementation(minSdk = S) isHeadlessSystemUserMode()1234 protected static boolean isHeadlessSystemUserMode() { 1235 return userManagerState.isHeadlessSystemUserMode; 1236 } 1237 1238 /** Updates headless system user mode. */ setHeadlessSystemUserMode(boolean isEnabled)1239 public static void setHeadlessSystemUserMode(boolean isEnabled) { 1240 userManagerState.isHeadlessSystemUserMode = isEnabled; 1241 } 1242 1243 @Implementation(minSdk = TIRAMISU) getUserRestrictions()1244 protected Bundle getUserRestrictions() { 1245 return getUserRestrictions(UserHandle.getUserHandleForUid(Process.myUid())); 1246 } 1247 1248 @Implementation(minSdk = TIRAMISU) hasUserRestrictionForUser(String restrictionKey, int userId)1249 protected boolean hasUserRestrictionForUser(String restrictionKey, int userId) { 1250 Bundle bundle = getUserRestrictions(UserHandle.getUserHandleForUid(userId)); 1251 return bundle != null && bundle.getBoolean(restrictionKey); 1252 } 1253 1254 @Resetter reset()1255 public static void reset() { 1256 userManagerState = new UserManagerState(); 1257 } 1258 1259 @ForType(UserManager.class) 1260 interface UserManagerReflector { 1261 1262 @Direct getProfiles(int userHandle)1263 List getProfiles(int userHandle); 1264 1265 @Direct isSystemUser()1266 boolean isSystemUser(); 1267 1268 @Accessor("mUserId") setUserId(int userId)1269 void setUserId(int userId); 1270 } 1271 1272 @Implementation(minSdk = TIRAMISU) someUserHasAccount(String accountName, String accountType)1273 protected boolean someUserHasAccount(String accountName, String accountType) { 1274 return userManagerState.userAccounts.contains(new Account(accountName, accountType)); 1275 } 1276 1277 /** Setter for {@link UserManager#someUserHasAccount(String, String)}. */ setSomeUserHasAccount(String accountName, String accountType)1278 public void setSomeUserHasAccount(String accountName, String accountType) { 1279 userManagerState.userAccounts.add(new Account(accountName, accountType)); 1280 } 1281 1282 /** Removes user account set via {@link #setSomeUserHasAccount(String, String)}. */ removeSomeUserHasAccount(String accountName, String accountType)1283 public void removeSomeUserHasAccount(String accountName, String accountType) { 1284 userManagerState.userAccounts.remove(new Account(accountName, accountType)); 1285 } 1286 1287 /** Sets whether or not the current user is the foreground user. */ setUserForeground(boolean foreground)1288 public void setUserForeground(boolean foreground) { 1289 userManagerState.isForegroundUser = foreground; 1290 } 1291 1292 @Implementation(minSdk = S) isUserForeground()1293 protected boolean isUserForeground() { 1294 return userManagerState.isForegroundUser; 1295 } 1296 1297 @Implementation(minSdk = O) getUserRestrictionSources( String restriction, UserHandle userHandle)1298 protected List<EnforcingUser> getUserRestrictionSources( 1299 String restriction, UserHandle userHandle) { 1300 List<EnforcingUser> sources = new ArrayList<>(); 1301 if (hasUserRestriction(restriction, userHandle)) { 1302 sources.add(new EnforcingUser(userHandle.getIdentifier(), RESTRICTION_SOURCE_SYSTEM)); 1303 } 1304 return sources; 1305 } 1306 } 1307