• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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