• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      * When {@code true}, it indicates this user was created by converting a {@link #preCreated}
225      * user.
226      *
227      * <p><b>NOTE: </b>only used for debugging purposes, it's not set when marshalled to a parcel.
228      */
229     public boolean convertedFromPreCreated;
230 
231     /**
232      * Creates a UserInfo whose user type is determined automatically by the flags according to
233      * {@link #getDefaultUserType}; can only be used for user types handled there.
234      */
235     @UnsupportedAppUsage
UserInfo(int id, String name, int flags)236     public UserInfo(int id, String name, int flags) {
237         this(id, name, null, flags);
238     }
239 
240     /**
241      * Creates a UserInfo whose user type is determined automatically by the flags according to
242      * {@link #getDefaultUserType}; can only be used for user types handled there.
243      */
244     @UnsupportedAppUsage
UserInfo(int id, String name, String iconPath, int flags)245     public UserInfo(int id, String name, String iconPath, int flags) {
246         this(id, name, iconPath, flags, getDefaultUserType(flags));
247     }
248 
UserInfo(int id, String name, String iconPath, int flags, String userType)249     public UserInfo(int id, String name, String iconPath, int flags, String userType) {
250         this.id = id;
251         this.name = name;
252         this.flags = flags;
253         this.userType = userType;
254         this.iconPath = iconPath;
255         this.profileGroupId = NO_PROFILE_GROUP_ID;
256         this.restrictedProfileParentId = NO_PROFILE_GROUP_ID;
257     }
258 
259     /**
260      * Get the user type (such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}) that corresponds to
261      * the given {@link UserInfoFlag}s.
262 
263      * <p>The userInfoFlag can contain GUEST, RESTRICTED, MANAGED_PROFILE, DEMO, or else be
264      * interpreted as a regular "secondary" user. It cannot contain more than one of these.
265      * It can contain other UserInfoFlag properties (like EPHEMERAL), which will be ignored here.
266      *
267      * @throws IllegalArgumentException if userInfoFlag is more than one type of user or if it
268      *                                  is a SYSTEM user.
269      *
270      * @hide
271      */
getDefaultUserType(@serInfoFlag int userInfoFlag)272     public static @NonNull String getDefaultUserType(@UserInfoFlag int userInfoFlag) {
273         if ((userInfoFlag & FLAG_SYSTEM) != 0) {
274             throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
275                     + Integer.toHexString(userInfoFlag) + " because it corresponds to a "
276                     + "SYSTEM user type.");
277         }
278         final int supportedFlagTypes =
279                 FLAG_GUEST | FLAG_RESTRICTED | FLAG_MANAGED_PROFILE | FLAG_DEMO;
280         switch (userInfoFlag & supportedFlagTypes) {
281             case 0 :                   return UserManager.USER_TYPE_FULL_SECONDARY;
282             case FLAG_GUEST:           return UserManager.USER_TYPE_FULL_GUEST;
283             case FLAG_RESTRICTED:      return UserManager.USER_TYPE_FULL_RESTRICTED;
284             case FLAG_MANAGED_PROFILE: return UserManager.USER_TYPE_PROFILE_MANAGED;
285             case FLAG_DEMO:            return UserManager.USER_TYPE_FULL_DEMO;
286             default:
287                 throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
288                         + Integer.toHexString(userInfoFlag) + " because it doesn't correspond to a "
289                         + "valid user type.");
290         }
291     }
292 
293     @UnsupportedAppUsage
isPrimary()294     public boolean isPrimary() {
295         return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
296     }
297 
298     @UnsupportedAppUsage
isAdmin()299     public boolean isAdmin() {
300         return (flags & FLAG_ADMIN) == FLAG_ADMIN;
301     }
302 
303     @UnsupportedAppUsage
isGuest()304     public boolean isGuest() {
305         return UserManager.isUserTypeGuest(userType);
306     }
307 
308     @UnsupportedAppUsage
isRestricted()309     public boolean isRestricted() {
310         return UserManager.isUserTypeRestricted(userType);
311     }
312 
isProfile()313     public boolean isProfile() {
314         return (flags & FLAG_PROFILE) != 0;
315     }
316 
317     @UnsupportedAppUsage
isManagedProfile()318     public boolean isManagedProfile() {
319         return UserManager.isUserTypeManagedProfile(userType);
320     }
321 
322     @UnsupportedAppUsage
isEnabled()323     public boolean isEnabled() {
324         return (flags & FLAG_DISABLED) != FLAG_DISABLED;
325     }
326 
isQuietModeEnabled()327     public boolean isQuietModeEnabled() {
328         return (flags & FLAG_QUIET_MODE) == FLAG_QUIET_MODE;
329     }
330 
isEphemeral()331     public boolean isEphemeral() {
332         return (flags & FLAG_EPHEMERAL) == FLAG_EPHEMERAL;
333     }
334 
isInitialized()335     public boolean isInitialized() {
336         return (flags & FLAG_INITIALIZED) == FLAG_INITIALIZED;
337     }
338 
isDemo()339     public boolean isDemo() {
340         return UserManager.isUserTypeDemo(userType);
341     }
342 
isFull()343     public boolean isFull() {
344         return (flags & FLAG_FULL) == FLAG_FULL;
345     }
346 
347     /**
348      * Returns true if the user is a split system user.
349      * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
350      * the method always returns false.
351      */
isSystemOnly()352     public boolean isSystemOnly() {
353         return isSystemOnly(id);
354     }
355 
356     /**
357      * Returns true if the given user is a split system user.
358      * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
359      * the method always returns false.
360      */
isSystemOnly(int userId)361     public static boolean isSystemOnly(int userId) {
362         return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
363     }
364 
365     /**
366      * @return true if this user can be switched to.
367      **/
supportsSwitchTo()368     public boolean supportsSwitchTo() {
369         if (isEphemeral() && !isEnabled()) {
370             // Don't support switching to an ephemeral user with removal in progress.
371             return false;
372         }
373         if (preCreated) {
374             // Don't support switching to pre-created users until they become "real" users.
375             return false;
376         }
377         return !isProfile();
378     }
379 
380     /**
381      * @return true if this user can be switched to by end user through UI.
382      */
supportsSwitchToByUser()383     public boolean supportsSwitchToByUser() {
384         // Hide the system user when it does not represent a human user.
385         boolean hideSystemUser = UserManager.isHeadlessSystemUserMode();
386         return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
387     }
388 
389     // TODO(b/142482943): Make this logic more specific and customizable. (canHaveProfile(userType))
390     /* @hide */
canHaveProfile()391     public boolean canHaveProfile() {
392         if (isProfile() || isGuest() || isRestricted()) {
393             return false;
394         }
395         if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
396             return id != UserHandle.USER_SYSTEM;
397         } else {
398             return id == UserHandle.USER_SYSTEM;
399         }
400     }
401 
402     // TODO(b/142482943): Get rid of this (after removing it from all tests) if feasible.
403     /**
404      * @deprecated This is dangerous since it doesn't set the mandatory fields. Use a different
405      * constructor instead.
406      */
407     @Deprecated
408     @VisibleForTesting
UserInfo()409     public UserInfo() {
410     }
411 
UserInfo(UserInfo orig)412     public UserInfo(UserInfo orig) {
413         name = orig.name;
414         iconPath = orig.iconPath;
415         id = orig.id;
416         flags = orig.flags;
417         userType = orig.userType;
418         serialNumber = orig.serialNumber;
419         creationTime = orig.creationTime;
420         lastLoggedInTime = orig.lastLoggedInTime;
421         lastLoggedInFingerprint = orig.lastLoggedInFingerprint;
422         partial = orig.partial;
423         preCreated = orig.preCreated;
424         convertedFromPreCreated = orig.convertedFromPreCreated;
425         profileGroupId = orig.profileGroupId;
426         restrictedProfileParentId = orig.restrictedProfileParentId;
427         guestToRemove = orig.guestToRemove;
428         profileBadge = orig.profileBadge;
429     }
430 
431     @UnsupportedAppUsage
getUserHandle()432     public UserHandle getUserHandle() {
433         return UserHandle.of(id);
434     }
435 
436     // TODO(b/142482943): Probably include mUserType here, which means updating TestDevice, etc.
437     @Override
toString()438     public String toString() {
439         // NOTE:  do not change this string, it's used by 'pm list users', which in turn is
440         // used and parsed by TestDevice. In other words, if you change it, you'd have to change
441         // TestDevice, TestDeviceTest, and possibly others....
442         return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}";
443     }
444 
445     /** @hide */
toFullString()446     public String toFullString() {
447         return "UserInfo[id=" + id
448                 + ", name=" + name
449                 + ", type=" + userType
450                 + ", flags=" + flagsToString(flags)
451                 + (preCreated ? " (pre-created)" : "")
452                 + (convertedFromPreCreated ? " (converted)" : "")
453                 + (partial ? " (partial)" : "")
454                 + "]";
455     }
456 
457     /** @hide */
flagsToString(int flags)458     public static String flagsToString(int flags) {
459         return DebugUtils.flagsToString(UserInfo.class, "FLAG_", flags);
460     }
461 
462     @Override
describeContents()463     public int describeContents() {
464         return 0;
465     }
466 
467     @Override
writeToParcel(Parcel dest, int parcelableFlags)468     public void writeToParcel(Parcel dest, int parcelableFlags) {
469         dest.writeInt(id);
470         dest.writeString8(name);
471         dest.writeString8(iconPath);
472         dest.writeInt(flags);
473         dest.writeString8(userType);
474         dest.writeInt(serialNumber);
475         dest.writeLong(creationTime);
476         dest.writeLong(lastLoggedInTime);
477         dest.writeString8(lastLoggedInFingerprint);
478         dest.writeBoolean(partial);
479         dest.writeBoolean(preCreated);
480         dest.writeInt(profileGroupId);
481         dest.writeBoolean(guestToRemove);
482         dest.writeInt(restrictedProfileParentId);
483         dest.writeInt(profileBadge);
484     }
485 
486     @UnsupportedAppUsage
487     public static final @android.annotation.NonNull Parcelable.Creator<UserInfo> CREATOR
488             = new Parcelable.Creator<UserInfo>() {
489         public UserInfo createFromParcel(Parcel source) {
490             return new UserInfo(source);
491         }
492         public UserInfo[] newArray(int size) {
493             return new UserInfo[size];
494         }
495     };
496 
UserInfo(Parcel source)497     private UserInfo(Parcel source) {
498         id = source.readInt();
499         name = source.readString8();
500         iconPath = source.readString8();
501         flags = source.readInt();
502         userType = source.readString8();
503         serialNumber = source.readInt();
504         creationTime = source.readLong();
505         lastLoggedInTime = source.readLong();
506         lastLoggedInFingerprint = source.readString8();
507         partial = source.readBoolean();
508         preCreated = source.readBoolean();
509         profileGroupId = source.readInt();
510         guestToRemove = source.readBoolean();
511         restrictedProfileParentId = source.readInt();
512         profileBadge = source.readInt();
513     }
514 }
515