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