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