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