1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content.pm;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.UserIdInt;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.os.UserHandle;
26 import android.os.UserManager;
27 import android.util.DebugUtils;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 /**
35  * Per-user information.
36  *
37  * <p>There are 3 base properties of users: {@link #FLAG_SYSTEM}, {@link #FLAG_FULL}, and
38  * {@link #FLAG_PROFILE}. Every user must have one of the following combination of these
39  * flags:
40  * <ul>
41  *    <li>FLAG_SYSTEM (user {@link UserHandle#USER_SYSTEM} on a headless-user-0 device)</li>
42  *    <li>FLAG_SYSTEM and FLAG_FULL (user {@link UserHandle#USER_SYSTEM} on a regular device)</li>
43  *    <li>FLAG_FULL (non-profile secondary user)</li>
44  *    <li>FLAG_PROFILE (profile users)</li>
45  * </ul>
46  * Users can have also have additional flags (such as FLAG_GUEST) as appropriate.
47  *
48  * @hide
49  */
50 public class UserInfo implements Parcelable {
51 
52     /**
53      * *************************** NOTE ***************************
54      * These flag values CAN NOT CHANGE because they are written
55      * directly to storage.
56      */
57 
58     /**
59      * Primary user. Only one user can have this flag set. It identifies the first human user
60      * on a device. This flag is not supported in headless system user mode.
61      */
62     @UnsupportedAppUsage
63     public static final int FLAG_PRIMARY = 0x00000001;
64 
65     /**
66      * User with administrative privileges. Such a user can create and
67      * delete users.
68      */
69     public static final int FLAG_ADMIN   = 0x00000002;
70 
71     /**
72      * Indicates a guest user that may be transient.
73      * @deprecated Use {@link UserManager#USER_TYPE_FULL_GUEST} instead.
74      */
75     @Deprecated
76     public static final int FLAG_GUEST   = 0x00000004;
77 
78     /**
79      * Indicates the user has restrictions in privileges, in addition to those for normal users.
80      * Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
81      * @deprecated Use {@link UserManager#USER_TYPE_FULL_RESTRICTED} instead.
82      */
83     @Deprecated
84     public static final int FLAG_RESTRICTED = 0x00000008;
85 
86     /**
87      * Indicates that this user has gone through its first-time initialization.
88      */
89     public static final int FLAG_INITIALIZED = 0x00000010;
90 
91     /**
92      * Indicates that this user is a profile of another user, for example holding a users
93      * corporate data.
94      * @deprecated Use {@link UserManager#USER_TYPE_PROFILE_MANAGED} instead.
95      */
96     @Deprecated
97     public static final int FLAG_MANAGED_PROFILE = 0x00000020;
98 
99     /**
100      * Indicates that this user is disabled.
101      *
102      * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
103      * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
104      */
105     public static final int FLAG_DISABLED = 0x00000040;
106 
107     public static final int FLAG_QUIET_MODE = 0x00000080;
108 
109     /**
110      * Indicates that this user is ephemeral. I.e. the user will be removed after leaving
111      * the foreground.
112      */
113     public static final int FLAG_EPHEMERAL = 0x00000100;
114 
115     /**
116      * User is for demo purposes only and can be removed at any time.
117      * @deprecated Use {@link UserManager#USER_TYPE_FULL_DEMO} instead.
118      */
119     @Deprecated
120     public static final int FLAG_DEMO = 0x00000200;
121 
122     /**
123      * Indicates that this user is a non-profile human user.
124      *
125      * <p>When creating a new (non-system) user, this flag will always be forced true unless the
126      * user is a {@link #FLAG_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
127      * human user, it must also be flagged as FULL.
128      */
129     public static final int FLAG_FULL = 0x00000400;
130 
131     /**
132      * Indicates that this user is {@link UserHandle#USER_SYSTEM}. Not applicable to created users.
133      */
134     public static final int FLAG_SYSTEM = 0x00000800;
135 
136     /**
137      * Indicates that this user is a profile human user, such as a managed profile.
138      * Mutually exclusive with {@link #FLAG_FULL}.
139      */
140     public static final int FLAG_PROFILE = 0x00001000;
141 
142     /**
143      * @hide
144      */
145     @IntDef(flag = true, prefix = "FLAG_", value = {
146             FLAG_PRIMARY,
147             FLAG_ADMIN,
148             FLAG_GUEST,
149             FLAG_RESTRICTED,
150             FLAG_INITIALIZED,
151             FLAG_MANAGED_PROFILE,
152             FLAG_DISABLED,
153             FLAG_QUIET_MODE,
154             FLAG_EPHEMERAL,
155             FLAG_DEMO,
156             FLAG_FULL,
157             FLAG_SYSTEM,
158             FLAG_PROFILE
159     })
160     @Retention(RetentionPolicy.SOURCE)
161     public @interface UserInfoFlag {
162     }
163 
164     public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;
165 
166     @UnsupportedAppUsage
167     public @UserIdInt int id;
168     @UnsupportedAppUsage
169     public int serialNumber;
170     @UnsupportedAppUsage
171     public String name;
172     @UnsupportedAppUsage
173     public String iconPath;
174     @UnsupportedAppUsage
175     public @UserInfoFlag int flags;
176     @UnsupportedAppUsage
177     public long creationTime;
178     @UnsupportedAppUsage
179     public long lastLoggedInTime;
180     public String lastLoggedInFingerprint;
181 
182     /**
183      * Type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}, corresponding to
184      * {@link com.android.server.pm.UserTypeDetails#getName()}.
185      */
186     public String userType;
187 
188     /**
189      * If this user is a parent user, it would be its own user id.
190      * If this user is a child user, it would be its parent user id.
191      * Otherwise, it would be {@link #NO_PROFILE_GROUP_ID}.
192      */
193     @UnsupportedAppUsage
194     public int profileGroupId;
195     public int restrictedProfileParentId;
196 
197     /**
198      * Index for distinguishing different profiles with the same parent and user type for the
199      * purpose of badging.
200      * It is used for determining which badge color/label to use (if applicable) from
201      * the options available for a particular user type.
202      */
203     public int profileBadge;
204 
205     /** User is only partially created. */
206     @UnsupportedAppUsage
207     public boolean partial;
208     @UnsupportedAppUsage
209     public boolean guestToRemove;
210 
211     /**
212      * This is used to optimize the creation of an user, i.e. OEMs might choose to pre-create a
213      * number of users at the first boot, so the actual creation later is faster.
214      *
215      * <p>A {@code preCreated} user is not a real user yet, so it should not show up on regular
216      * user operations (other than user creation per se).
217      *
218      * <p>Once the pre-created is used to create a "real" user later on, {@code preCreate} is set to
219      * {@code false}.
220      */
221     public boolean preCreated;
222 
223     /**
224      * Creates a UserInfo whose user type is determined automatically by the flags according to
225      * {@link #getDefaultUserType}; can only be used for user types handled there.
226      */
227     @UnsupportedAppUsage
UserInfo(int id, String name, int flags)228     public UserInfo(int id, String name, int flags) {
229         this(id, name, null, flags);
230     }
231 
232     /**
233      * Creates a UserInfo whose user type is determined automatically by the flags according to
234      * {@link #getDefaultUserType}; can only be used for user types handled there.
235      */
236     @UnsupportedAppUsage
UserInfo(int id, String name, String iconPath, int flags)237     public UserInfo(int id, String name, String iconPath, int flags) {
238         this(id, name, iconPath, flags, getDefaultUserType(flags));
239     }
240 
UserInfo(int id, String name, String iconPath, int flags, String userType)241     public UserInfo(int id, String name, String iconPath, int flags, String userType) {
242         this.id = id;
243         this.name = name;
244         this.flags = flags;
245         this.userType = userType;
246         this.iconPath = iconPath;
247         this.profileGroupId = NO_PROFILE_GROUP_ID;
248         this.restrictedProfileParentId = NO_PROFILE_GROUP_ID;
249     }
250 
251     /**
252      * Get the user type (such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}) that corresponds to
253      * the given {@link UserInfoFlag}s.
254 
255      * <p>The userInfoFlag can contain GUEST, RESTRICTED, MANAGED_PROFILE, DEMO, or else be
256      * interpreted as a regular "secondary" user. It cannot contain more than one of these.
257      * It can contain other UserInfoFlag properties (like EPHEMERAL), which will be ignored here.
258      *
259      * @throws IllegalArgumentException if userInfoFlag is more than one type of user or if it
260      *                                  is a SYSTEM user.
261      *
262      * @hide
263      */
getDefaultUserType(@serInfoFlag int userInfoFlag)264     public static @NonNull String getDefaultUserType(@UserInfoFlag int userInfoFlag) {
265         if ((userInfoFlag & FLAG_SYSTEM) != 0) {
266             throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
267                     + Integer.toHexString(userInfoFlag) + " because it corresponds to a "
268                     + "SYSTEM user type.");
269         }
270         final int supportedFlagTypes =
271                 FLAG_GUEST | FLAG_RESTRICTED | FLAG_MANAGED_PROFILE | FLAG_DEMO;
272         switch (userInfoFlag & supportedFlagTypes) {
273             case 0 :                   return UserManager.USER_TYPE_FULL_SECONDARY;
274             case FLAG_GUEST:           return UserManager.USER_TYPE_FULL_GUEST;
275             case FLAG_RESTRICTED:      return UserManager.USER_TYPE_FULL_RESTRICTED;
276             case FLAG_MANAGED_PROFILE: return UserManager.USER_TYPE_PROFILE_MANAGED;
277             case FLAG_DEMO:            return UserManager.USER_TYPE_FULL_DEMO;
278             default:
279                 throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
280                         + Integer.toHexString(userInfoFlag) + " because it doesn't correspond to a "
281                         + "valid user type.");
282         }
283     }
284 
285     @UnsupportedAppUsage
isPrimary()286     public boolean isPrimary() {
287         return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
288     }
289 
290     @UnsupportedAppUsage
isAdmin()291     public boolean isAdmin() {
292         return (flags & FLAG_ADMIN) == FLAG_ADMIN;
293     }
294 
295     @UnsupportedAppUsage
isGuest()296     public boolean isGuest() {
297         return UserManager.isUserTypeGuest(userType);
298     }
299 
300     @UnsupportedAppUsage
isRestricted()301     public boolean isRestricted() {
302         return UserManager.isUserTypeRestricted(userType);
303     }
304 
isProfile()305     public boolean isProfile() {
306         return (flags & FLAG_PROFILE) != 0;
307     }
308 
309     @UnsupportedAppUsage
isManagedProfile()310     public boolean isManagedProfile() {
311         return UserManager.isUserTypeManagedProfile(userType);
312     }
313 
314     @UnsupportedAppUsage
isEnabled()315     public boolean isEnabled() {
316         return (flags & FLAG_DISABLED) != FLAG_DISABLED;
317     }
318 
isQuietModeEnabled()319     public boolean isQuietModeEnabled() {
320         return (flags & FLAG_QUIET_MODE) == FLAG_QUIET_MODE;
321     }
322 
isEphemeral()323     public boolean isEphemeral() {
324         return (flags & FLAG_EPHEMERAL) == FLAG_EPHEMERAL;
325     }
326 
isInitialized()327     public boolean isInitialized() {
328         return (flags & FLAG_INITIALIZED) == FLAG_INITIALIZED;
329     }
330 
isDemo()331     public boolean isDemo() {
332         return UserManager.isUserTypeDemo(userType);
333     }
334 
isFull()335     public boolean isFull() {
336         return (flags & FLAG_FULL) == FLAG_FULL;
337     }
338 
339     /**
340      * Returns true if the user is a split system user.
341      * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
342      * the method always returns false.
343      */
isSystemOnly()344     public boolean isSystemOnly() {
345         return isSystemOnly(id);
346     }
347 
348     /**
349      * Returns true if the given user is a split system user.
350      * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
351      * the method always returns false.
352      */
isSystemOnly(int userId)353     public static boolean isSystemOnly(int userId) {
354         return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
355     }
356 
357     /**
358      * @return true if this user can be switched to.
359      **/
supportsSwitchTo()360     public boolean supportsSwitchTo() {
361         if (isEphemeral() && !isEnabled()) {
362             // Don't support switching to an ephemeral user with removal in progress.
363             return false;
364         }
365         if (preCreated) {
366             // Don't support switching to pre-created users until they become "real" users.
367             return false;
368         }
369         return !isProfile();
370     }
371 
372     /**
373      * @return true if this user can be switched to by end user through UI.
374      */
supportsSwitchToByUser()375     public boolean supportsSwitchToByUser() {
376         // Hide the system user when it does not represent a human user.
377         boolean hideSystemUser = UserManager.isHeadlessSystemUserMode();
378         return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
379     }
380 
381     // TODO(b/142482943): Make this logic more specific and customizable. (canHaveProfile(userType))
382     /* @hide */
canHaveProfile()383     public boolean canHaveProfile() {
384         if (isProfile() || isGuest() || isRestricted()) {
385             return false;
386         }
387         if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
388             return id != UserHandle.USER_SYSTEM;
389         } else {
390             return id == UserHandle.USER_SYSTEM;
391         }
392     }
393 
394     // TODO(b/142482943): Get rid of this (after removing it from all tests) if feasible.
395     /**
396      * @deprecated This is dangerous since it doesn't set the mandatory fields. Use a different
397      * constructor instead.
398      */
399     @Deprecated
400     @VisibleForTesting
UserInfo()401     public UserInfo() {
402     }
403 
UserInfo(UserInfo orig)404     public UserInfo(UserInfo orig) {
405         name = orig.name;
406         iconPath = orig.iconPath;
407         id = orig.id;
408         flags = orig.flags;
409         userType = orig.userType;
410         serialNumber = orig.serialNumber;
411         creationTime = orig.creationTime;
412         lastLoggedInTime = orig.lastLoggedInTime;
413         lastLoggedInFingerprint = orig.lastLoggedInFingerprint;
414         partial = orig.partial;
415         preCreated = orig.preCreated;
416         profileGroupId = orig.profileGroupId;
417         restrictedProfileParentId = orig.restrictedProfileParentId;
418         guestToRemove = orig.guestToRemove;
419         profileBadge = orig.profileBadge;
420     }
421 
422     @UnsupportedAppUsage
getUserHandle()423     public UserHandle getUserHandle() {
424         return UserHandle.of(id);
425     }
426 
427     // TODO(b/142482943): Probably include mUserType here, which means updating TestDevice, etc.
428     @Override
toString()429     public String toString() {
430         // NOTE:  do not change this string, it's used by 'pm list users', which in turn is
431         // used and parsed by TestDevice. In other words, if you change it, you'd have to change
432         // TestDevice, TestDeviceTest, and possibly others....
433         return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}";
434     }
435 
436     /** @hide */
toFullString()437     public String toFullString() {
438         return "UserInfo[id=" + id
439                 + ", name=" + name
440                 + ", type=" + userType
441                 + ", flags=" + flagsToString(flags)
442                 + (preCreated ? " (pre-created)" : "")
443                 + (partial ? " (partial)" : "")
444                 + "]";
445     }
446 
447     /** @hide */
flagsToString(int flags)448     public static String flagsToString(int flags) {
449         return DebugUtils.flagsToString(UserInfo.class, "FLAG_", flags);
450     }
451 
452     @Override
describeContents()453     public int describeContents() {
454         return 0;
455     }
456 
457     @Override
writeToParcel(Parcel dest, int parcelableFlags)458     public void writeToParcel(Parcel dest, int parcelableFlags) {
459         dest.writeInt(id);
460         dest.writeString8(name);
461         dest.writeString8(iconPath);
462         dest.writeInt(flags);
463         dest.writeString8(userType);
464         dest.writeInt(serialNumber);
465         dest.writeLong(creationTime);
466         dest.writeLong(lastLoggedInTime);
467         dest.writeString8(lastLoggedInFingerprint);
468         dest.writeBoolean(partial);
469         dest.writeBoolean(preCreated);
470         dest.writeInt(profileGroupId);
471         dest.writeBoolean(guestToRemove);
472         dest.writeInt(restrictedProfileParentId);
473         dest.writeInt(profileBadge);
474     }
475 
476     @UnsupportedAppUsage
477     public static final @android.annotation.NonNull Parcelable.Creator<UserInfo> CREATOR
478             = new Parcelable.Creator<UserInfo>() {
479         public UserInfo createFromParcel(Parcel source) {
480             return new UserInfo(source);
481         }
482         public UserInfo[] newArray(int size) {
483             return new UserInfo[size];
484         }
485     };
486 
UserInfo(Parcel source)487     private UserInfo(Parcel source) {
488         id = source.readInt();
489         name = source.readString8();
490         iconPath = source.readString8();
491         flags = source.readInt();
492         userType = source.readString8();
493         serialNumber = source.readInt();
494         creationTime = source.readLong();
495         lastLoggedInTime = source.readLong();
496         lastLoggedInFingerprint = source.readString8();
497         partial = source.readBoolean();
498         preCreated = source.readBoolean();
499         profileGroupId = source.readInt();
500         guestToRemove = source.readBoolean();
501         restrictedProfileParentId = source.readInt();
502         profileBadge = source.readInt();
503     }
504 }
505