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