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