1 /* 2 * Copyright (C) 2019 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 com.android.server.pm; 18 19 import android.annotation.ColorRes; 20 import android.annotation.DrawableRes; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.StringRes; 24 import android.content.pm.UserInfo; 25 import android.content.pm.UserInfo.UserInfoFlag; 26 import android.content.pm.UserProperties; 27 import android.content.res.Resources; 28 import android.os.Bundle; 29 import android.os.UserManager; 30 31 import com.android.internal.util.Preconditions; 32 import com.android.server.BundleUtils; 33 34 import java.io.PrintWriter; 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.List; 38 39 /** 40 * Contains the details about a multiuser "user type", such as a 41 * {@link UserManager#USER_TYPE_PROFILE_MANAGED}. 42 * 43 * Tests are located in UserManagerServiceUserTypeTest.java. 44 * @hide 45 */ 46 public final class UserTypeDetails { 47 48 /** Indicates that there is no limit to the number of users allowed. */ 49 public static final int UNLIMITED_NUMBER_OF_USERS = -1; 50 51 /** Name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}. */ 52 private final @NonNull String mName; 53 54 /** Whether users of this type can be created. */ 55 private final boolean mEnabled; 56 57 /** 58 * Resource IDs ({@link StringRes}) of the user's labels. This might be used to label a 59 * user/profile in tabbed views, etc. 60 * The values are resource IDs referring to the strings not the strings themselves. 61 * 62 * <p>This is an array because, in general, there may be multiple users of the same user type. 63 * In this case, the user is indexed according to its {@link UserInfo#profileBadge}. 64 */ 65 private final @Nullable int[] mLabels; 66 67 /** 68 * Maximum number of this user type allowed on the device. 69 * Use {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit. 70 */ 71 private final int mMaxAllowed; 72 73 /** 74 * Maximum number of this user type allowed per parent (for user types, like profiles, that 75 * have parents). 76 * Use {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit. 77 */ 78 // TODO(b/142482943): Should this also apply to restricted profiles? 79 private final int mMaxAllowedPerParent; 80 81 // TODO(b/143784345): Update doc when we clean up UserInfo. 82 /** The {@link UserInfo.UserInfoFlag} representing the base type of this user. */ 83 private final @UserInfoFlag int mBaseType; 84 85 // TODO(b/143784345): Update doc/name when we clean up UserInfo. 86 /** The {@link UserInfoFlag}s to apply by default to newly created users of this type. */ 87 private final @UserInfoFlag int mDefaultUserInfoPropertyFlags; 88 89 /** 90 * List of User Restrictions to apply by default to newly created users of this type. 91 * <p>Does not apply to SYSTEM users (since they are not formally created); for them use 92 * {@link com.android.internal.R.array#config_defaultFirstUserRestrictions} instead. 93 * The Bundle is of the form used by {@link UserRestrictionsUtils}. 94 */ 95 private final @Nullable Bundle mDefaultRestrictions; 96 97 /** 98 * List of {@link android.provider.Settings.System} to apply by default to newly created users 99 * of this type. 100 */ 101 private final @Nullable Bundle mDefaultSystemSettings; 102 103 /** 104 * List of {@link android.provider.Settings.Secure} to apply by default to newly created users 105 * of this type. 106 */ 107 private final @Nullable Bundle mDefaultSecureSettings; 108 109 /** 110 * List of {@link DefaultCrossProfileIntentFilter} to allow by default for newly created 111 * profiles. 112 */ 113 private final @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters; 114 115 /** Whether the {@link #isProfile() profile} requires having a parent (as most profiles do). */ 116 private final boolean mProfileParentRequired; 117 118 119 // Fields for profiles only, controlling the nature of their badges. 120 // All badge information should be set if {@link #hasBadge()} is true. 121 122 /** Resource ID of the badge put on icons. */ 123 private @DrawableRes final int mIconBadge; 124 /** Resource ID of the badge. Should be set if mIconBadge is set. */ 125 private @DrawableRes final int mBadgePlain; 126 /** Resource ID of the badge without a background. Should be set if mIconBadge is set. */ 127 private @DrawableRes final int mBadgeNoBackground; 128 129 /** Resource ID of the status bar icon. */ 130 private @DrawableRes final int mStatusBarIcon; 131 132 /** 133 * Resource ID ({@link StringRes}) of the labels to describe badged apps; should be the 134 * same format as com.android.internal.R.color.profile_badge_1. These are used for accessibility 135 * services. 136 * 137 * <p>This is an array because, in general, there may be multiple users of the same user type. 138 * In this case, the user is indexed according to its {@link UserInfo#profileBadge}. 139 * 140 * <p>Must be set if mIconBadge is set. 141 */ 142 private final @Nullable int[] mBadgeLabels; 143 144 /** 145 * Resource ID ({@link ColorRes}) of the colors badge put on icons. 146 * (The value is a resource ID referring to the color; it is not the color value itself). 147 * 148 * <p>This is an array because, in general, there may be multiple users of the same user type. 149 * In this case, the user is indexed according to its {@link UserInfo#profileBadge}. 150 * 151 * <p>Must be set if mIconBadge is set. 152 */ 153 private final @Nullable int[] mBadgeColors; 154 155 /** 156 * Resource ID ({@link ColorRes}) of the colors badge put on icons when in dark theme. 157 * (The value is a resource ID referring to the color; it is not the color value itself). 158 * 159 * <p>This is an array because, in general, there may be multiple users of the same user type. 160 * In this case, the user is indexed according to its {@link UserInfo#profileBadge}. 161 * 162 * <p>Must be set if mIconBadge is set. 163 */ 164 private final @Nullable int[] mDarkThemeBadgeColors; 165 166 /** 167 * Resource ID ({@link StringRes}) of the accessibility string that describes the user type. 168 * This is used by accessibility services like Talkback. 169 */ 170 private final @StringRes int mAccessibilityString; 171 172 /** 173 * The default {@link UserProperties} for the user type. 174 * <p> The uninitialized value of each property is implied by {@link UserProperties.Builder}. 175 */ 176 private final @NonNull UserProperties mDefaultUserProperties; 177 UserTypeDetails(@onNull String name, boolean enabled, int maxAllowed, @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, @Nullable int[] labels, int maxAllowedPerParent, boolean profileParentRequired, int iconBadge, int badgePlain, int badgeNoBackground, int statusBarIcon, @Nullable int[] badgeLabels, @Nullable int[] badgeColors, @Nullable int[] darkThemeBadgeColors, @Nullable Bundle defaultRestrictions, @Nullable Bundle defaultSystemSettings, @Nullable Bundle defaultSecureSettings, @Nullable List<DefaultCrossProfileIntentFilter> defaultCrossProfileIntentFilters, @StringRes int accessibilityString, @NonNull UserProperties defaultUserProperties)178 private UserTypeDetails(@NonNull String name, boolean enabled, int maxAllowed, 179 @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, 180 @Nullable int[] labels, int maxAllowedPerParent, boolean profileParentRequired, 181 int iconBadge, int badgePlain, int badgeNoBackground, 182 int statusBarIcon, 183 @Nullable int[] badgeLabels, @Nullable int[] badgeColors, 184 @Nullable int[] darkThemeBadgeColors, 185 @Nullable Bundle defaultRestrictions, 186 @Nullable Bundle defaultSystemSettings, 187 @Nullable Bundle defaultSecureSettings, 188 @Nullable List<DefaultCrossProfileIntentFilter> defaultCrossProfileIntentFilters, 189 @StringRes int accessibilityString, 190 @NonNull UserProperties defaultUserProperties) { 191 this.mName = name; 192 this.mEnabled = enabled; 193 this.mMaxAllowed = maxAllowed; 194 this.mMaxAllowedPerParent = maxAllowedPerParent; 195 this.mBaseType = baseType; 196 this.mDefaultUserInfoPropertyFlags = defaultUserInfoPropertyFlags; 197 this.mDefaultRestrictions = defaultRestrictions; 198 this.mDefaultSystemSettings = defaultSystemSettings; 199 this.mDefaultSecureSettings = defaultSecureSettings; 200 this.mDefaultCrossProfileIntentFilters = defaultCrossProfileIntentFilters; 201 this.mProfileParentRequired = profileParentRequired; 202 this.mIconBadge = iconBadge; 203 this.mBadgePlain = badgePlain; 204 this.mBadgeNoBackground = badgeNoBackground; 205 this.mStatusBarIcon = statusBarIcon; 206 this.mLabels = labels; 207 this.mBadgeLabels = badgeLabels; 208 this.mBadgeColors = badgeColors; 209 this.mDarkThemeBadgeColors = darkThemeBadgeColors; 210 this.mAccessibilityString = accessibilityString; 211 this.mDefaultUserProperties = defaultUserProperties; 212 } 213 214 /** 215 * Returns the name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}. 216 */ getName()217 public String getName() { 218 return mName; 219 } 220 221 /** 222 * Returns whether this user type is enabled. 223 * If it is not enabled, all future attempts to create users of this type will be rejected. 224 */ isEnabled()225 public boolean isEnabled() { 226 return mEnabled; 227 } 228 229 /** 230 * Returns the maximum number of this user type allowed on the device. 231 * <p>Returns {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit. 232 */ getMaxAllowed()233 public int getMaxAllowed() { 234 return mMaxAllowed; 235 } 236 237 /** 238 * Returns the maximum number of this user type allowed per parent (for user types, like 239 * profiles, that have parents). 240 * Under certain circumstances (such as after a change-user-type) the max value can actually 241 * be exceeded: this is allowed in order to keep the device in a usable state. 242 * An error is logged in {@link UserManagerService#upgradeProfileToTypeLU} 243 * <p>Returns {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit. 244 */ getMaxAllowedPerParent()245 public int getMaxAllowedPerParent() { 246 return mMaxAllowedPerParent; 247 } 248 249 // TODO(b/143784345): Update comment when UserInfo is reorganized. 250 /** The {@link UserInfoFlag}s to apply by default to newly created users of this type. */ getDefaultUserInfoFlags()251 public int getDefaultUserInfoFlags() { 252 return mDefaultUserInfoPropertyFlags | mBaseType; 253 } 254 255 /** 256 * Returns whether this type of {@link #isProfile() profile} requires having a parent. 257 * Inapplicable to non-profiles (and therefore inapplicable to restricted profiles). 258 */ isProfileParentRequired()259 public boolean isProfileParentRequired() { 260 return mProfileParentRequired; 261 } 262 263 /** 264 * Returns the resource ID corresponding to the badgeIndexth label name where the badgeIndex is 265 * expected to be the {@link UserInfo#profileBadge} of the user. If badgeIndex exceeds the 266 * number of labels, returns the label for the highest index. 267 */ getLabel(int badgeIndex)268 public @StringRes int getLabel(int badgeIndex) { 269 if (mLabels == null || mLabels.length == 0 || badgeIndex < 0) { 270 return Resources.ID_NULL; 271 } 272 return mLabels[Math.min(badgeIndex, mLabels.length - 1)]; 273 } 274 275 /** Returns whether users of this user type should be badged. */ hasBadge()276 public boolean hasBadge() { 277 return mIconBadge != Resources.ID_NULL; 278 } 279 280 /** Resource ID of the badge to put on icons. */ getIconBadge()281 public @DrawableRes int getIconBadge() { 282 return mIconBadge; 283 } 284 285 /** Resource ID of the badge. Used for {@link UserManager#getUserBadgeResId(int)}. */ getBadgePlain()286 public @DrawableRes int getBadgePlain() { 287 return mBadgePlain; 288 } 289 290 /** Resource ID of the badge without a background. */ getBadgeNoBackground()291 public @DrawableRes int getBadgeNoBackground() { 292 return mBadgeNoBackground; 293 } 294 295 /** Resource ID of the status bar icon. */ getStatusBarIcon()296 public @DrawableRes int getStatusBarIcon() { 297 return mStatusBarIcon; 298 } 299 300 /** 301 * Returns the Resource ID of the badgeIndexth badge label, where the badgeIndex is expected 302 * to be the {@link UserInfo#profileBadge} of the user. 303 * If badgeIndex exceeds the number of labels, returns the label for the highest index. 304 */ getBadgeLabel(int badgeIndex)305 public @StringRes int getBadgeLabel(int badgeIndex) { 306 if (mBadgeLabels == null || mBadgeLabels.length == 0 || badgeIndex < 0) { 307 return Resources.ID_NULL; 308 } 309 return mBadgeLabels[Math.min(badgeIndex, mBadgeLabels.length - 1)]; 310 } 311 312 /** 313 * Returns the Resource ID of the badgeIndexth badge color, where the badgeIndex is expected 314 * to be the {@link UserInfo#profileBadge} of the user. 315 * If badgeIndex exceeds the number of colors, returns the color for the highest index. 316 */ getBadgeColor(int badgeIndex)317 public @ColorRes int getBadgeColor(int badgeIndex) { 318 if (mBadgeColors == null || mBadgeColors.length == 0 || badgeIndex < 0) { 319 return Resources.ID_NULL; 320 } 321 return mBadgeColors[Math.min(badgeIndex, mBadgeColors.length - 1)]; 322 } 323 324 /** 325 * Returns the Resource ID of the badgeIndexth dark theme badge color, where the badgeIndex is 326 * expected to be the {@link UserInfo#profileBadge} of the user. 327 * If dark theme badge colors haven't been set, use the light theme badge color. 328 * If badgeIndex exceeds the number of colors, returns the color for the highest index. 329 */ getDarkThemeBadgeColor(int badgeIndex)330 public @ColorRes int getDarkThemeBadgeColor(int badgeIndex) { 331 if (mDarkThemeBadgeColors == null || mDarkThemeBadgeColors.length == 0 || badgeIndex < 0) { 332 return getBadgeColor(badgeIndex); 333 } 334 return mDarkThemeBadgeColors[Math.min(badgeIndex, mDarkThemeBadgeColors.length - 1)]; 335 } 336 337 338 /** 339 * Returns the reference to the default {@link UserProperties} for this type of user. 340 * This is not a copy. Do NOT modify this object. 341 */ getDefaultUserPropertiesReference()342 public @NonNull UserProperties getDefaultUserPropertiesReference() { 343 return mDefaultUserProperties; 344 } 345 getAccessibilityString()346 public @StringRes int getAccessibilityString() { 347 return mAccessibilityString; 348 } 349 isProfile()350 public boolean isProfile() { 351 return (mBaseType & UserInfo.FLAG_PROFILE) != 0; 352 } 353 isFull()354 public boolean isFull() { 355 return (mBaseType & UserInfo.FLAG_FULL) != 0; 356 } 357 isSystem()358 public boolean isSystem() { 359 return (mBaseType & UserInfo.FLAG_SYSTEM) != 0; 360 } 361 362 /** Returns a {@link Bundle} representing the default user restrictions. */ getDefaultRestrictions()363 @NonNull Bundle getDefaultRestrictions() { 364 return BundleUtils.clone(mDefaultRestrictions); 365 } 366 367 /** Adds the default user restrictions to the given bundle of restrictions. */ addDefaultRestrictionsTo(@onNull Bundle currentRestrictions)368 public void addDefaultRestrictionsTo(@NonNull Bundle currentRestrictions) { 369 UserRestrictionsUtils.merge(currentRestrictions, mDefaultRestrictions); 370 } 371 372 /** Returns a {@link Bundle} representing the default system settings. */ getDefaultSystemSettings()373 @NonNull Bundle getDefaultSystemSettings() { 374 return BundleUtils.clone(mDefaultSystemSettings); 375 } 376 377 /** Returns a {@link Bundle} representing the default secure settings. */ getDefaultSecureSettings()378 @NonNull Bundle getDefaultSecureSettings() { 379 return BundleUtils.clone(mDefaultSecureSettings); 380 } 381 382 /** Returns a list of default cross profile intent filters. */ getDefaultCrossProfileIntentFilters()383 @NonNull List<DefaultCrossProfileIntentFilter> getDefaultCrossProfileIntentFilters() { 384 return mDefaultCrossProfileIntentFilters != null 385 ? new ArrayList<>(mDefaultCrossProfileIntentFilters) 386 : Collections.emptyList(); 387 } 388 389 /** Dumps details of the UserTypeDetails. Do not parse this. */ dump(PrintWriter pw, String prefix)390 public void dump(PrintWriter pw, String prefix) { 391 pw.print(prefix); pw.print("mName: "); pw.println(mName); 392 pw.print(prefix); pw.print("mBaseType: "); pw.println(UserInfo.flagsToString(mBaseType)); 393 pw.print(prefix); pw.print("mEnabled: "); pw.println(mEnabled); 394 pw.print(prefix); pw.print("mMaxAllowed: "); pw.println(mMaxAllowed); 395 pw.print(prefix); pw.print("mMaxAllowedPerParent: "); pw.println(mMaxAllowedPerParent); 396 pw.print(prefix); pw.print("mDefaultUserInfoFlags: "); 397 pw.println(UserInfo.flagsToString(mDefaultUserInfoPropertyFlags)); 398 mDefaultUserProperties.println(pw, prefix); 399 400 final String restrictionsPrefix = prefix + " "; 401 if (isSystem()) { 402 pw.print(prefix); pw.println("config_defaultFirstUserRestrictions: "); 403 try { 404 final Bundle restrictions = new Bundle(); 405 final String[] defaultFirstUserRestrictions = Resources.getSystem().getStringArray( 406 com.android.internal.R.array.config_defaultFirstUserRestrictions); 407 for (String userRestriction : defaultFirstUserRestrictions) { 408 if (UserRestrictionsUtils.isValidRestriction(userRestriction)) { 409 restrictions.putBoolean(userRestriction, true); 410 } 411 } 412 UserRestrictionsUtils.dumpRestrictions(pw, restrictionsPrefix, restrictions); 413 } catch (Resources.NotFoundException e) { 414 pw.print(restrictionsPrefix); pw.println("none - resource not found"); 415 } 416 } else { 417 pw.print(prefix); pw.println("mDefaultRestrictions: "); 418 UserRestrictionsUtils.dumpRestrictions(pw, restrictionsPrefix, mDefaultRestrictions); 419 } 420 421 pw.print(prefix); pw.print("mProfileParentRequired: "); pw.println(mProfileParentRequired); 422 pw.print(prefix); pw.print("mIconBadge: "); pw.println(mIconBadge); 423 pw.print(prefix); pw.print("mBadgePlain: "); pw.println(mBadgePlain); 424 pw.print(prefix); pw.print("mBadgeNoBackground: "); pw.println(mBadgeNoBackground); 425 pw.print(prefix); pw.print("mStatusBarIcon: "); pw.println(mStatusBarIcon); 426 pw.print(prefix); pw.print("mBadgeLabels.length: "); 427 pw.println(mBadgeLabels != null ? mBadgeLabels.length : "0(null)"); 428 pw.print(prefix); pw.print("mBadgeColors.length: "); 429 pw.println(mBadgeColors != null ? mBadgeColors.length : "0(null)"); 430 pw.print(prefix); pw.print("mDarkThemeBadgeColors.length: "); 431 pw.println(mDarkThemeBadgeColors != null ? mDarkThemeBadgeColors.length : "0(null)"); 432 pw.print(prefix); pw.print("mLabels.length: "); 433 pw.println(mLabels != null ? mLabels.length : "0(null)"); 434 } 435 436 /** Builder for a {@link UserTypeDetails}; see that class for documentation. */ 437 public static final class Builder { 438 // UserTypeDetails properties and their default values. 439 private String mName; // This MUST be explicitly set. 440 private int mBaseType; // This MUST be explicitly set. 441 private int mMaxAllowed = UNLIMITED_NUMBER_OF_USERS; 442 private int mMaxAllowedPerParent = UNLIMITED_NUMBER_OF_USERS; 443 private int mDefaultUserInfoPropertyFlags = 0; 444 private @Nullable Bundle mDefaultRestrictions = null; 445 private @Nullable Bundle mDefaultSystemSettings = null; 446 private @Nullable Bundle mDefaultSecureSettings = null; 447 private @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters = 448 null; 449 private int mEnabled = 1; 450 private @Nullable int[] mLabels = null; 451 private @Nullable int[] mBadgeLabels = null; 452 private @Nullable int[] mBadgeColors = null; 453 private @Nullable int[] mDarkThemeBadgeColors = null; 454 private boolean mProfileParentRequired = false; 455 private @DrawableRes int mIconBadge = Resources.ID_NULL; 456 private @DrawableRes int mBadgePlain = Resources.ID_NULL; 457 private @DrawableRes int mBadgeNoBackground = Resources.ID_NULL; 458 private @DrawableRes int mStatusBarIcon = Resources.ID_NULL; 459 private @StringRes int mAccessibilityString = Resources.ID_NULL; 460 // Default UserProperties cannot be null but for efficiency we don't initialize it now. 461 // If it isn't set explicitly, {@link UserProperties.Builder#build()} will be used. 462 private @Nullable UserProperties mDefaultUserProperties = null; 463 setName(String name)464 public Builder setName(String name) { 465 mName = name; 466 return this; 467 } 468 setEnabled(int enabled)469 public Builder setEnabled(int enabled) { 470 mEnabled = enabled; 471 return this; 472 } 473 setMaxAllowed(int maxAllowed)474 public Builder setMaxAllowed(int maxAllowed) { 475 mMaxAllowed = maxAllowed; 476 return this; 477 } 478 setMaxAllowedPerParent(int maxAllowedPerParent)479 public Builder setMaxAllowedPerParent(int maxAllowedPerParent) { 480 mMaxAllowedPerParent = maxAllowedPerParent; 481 return this; 482 } 483 setBaseType(@serInfoFlag int baseType)484 public Builder setBaseType(@UserInfoFlag int baseType) { 485 mBaseType = baseType; 486 return this; 487 } 488 setDefaultUserInfoPropertyFlags(@serInfoFlag int flags)489 public Builder setDefaultUserInfoPropertyFlags(@UserInfoFlag int flags) { 490 mDefaultUserInfoPropertyFlags = flags; 491 return this; 492 } 493 setBadgeLabels(@tringRes int ... badgeLabels)494 public Builder setBadgeLabels(@StringRes int ... badgeLabels) { 495 mBadgeLabels = badgeLabels; 496 return this; 497 } 498 setBadgeColors(@olorRes int ... badgeColors)499 public Builder setBadgeColors(@ColorRes int ... badgeColors) { 500 mBadgeColors = badgeColors; 501 return this; 502 } 503 504 /** The badge colors when the badge is on a dark background. */ setDarkThemeBadgeColors(@olorRes int ... darkThemeBadgeColors)505 public Builder setDarkThemeBadgeColors(@ColorRes int ... darkThemeBadgeColors) { 506 mDarkThemeBadgeColors = darkThemeBadgeColors; 507 return this; 508 } 509 setProfileParentRequired(boolean profileParentRequired)510 public Builder setProfileParentRequired(boolean profileParentRequired) { 511 mProfileParentRequired = profileParentRequired; 512 return this; 513 } 514 setIconBadge(@rawableRes int badgeIcon)515 public Builder setIconBadge(@DrawableRes int badgeIcon) { 516 mIconBadge = badgeIcon; 517 return this; 518 } 519 setBadgePlain(@rawableRes int badgePlain)520 public Builder setBadgePlain(@DrawableRes int badgePlain) { 521 mBadgePlain = badgePlain; 522 return this; 523 } 524 setBadgeNoBackground(@rawableRes int badgeNoBackground)525 public Builder setBadgeNoBackground(@DrawableRes int badgeNoBackground) { 526 mBadgeNoBackground = badgeNoBackground; 527 return this; 528 } 529 setStatusBarIcon(@rawableRes int statusBarIcon)530 public Builder setStatusBarIcon(@DrawableRes int statusBarIcon) { 531 mStatusBarIcon = statusBarIcon; 532 return this; 533 } 534 setLabels(@tringRes int ... labels)535 public Builder setLabels(@StringRes int ... labels) { 536 mLabels = labels; 537 return this; 538 } 539 setDefaultRestrictions(@ullable Bundle restrictions)540 public Builder setDefaultRestrictions(@Nullable Bundle restrictions) { 541 mDefaultRestrictions = restrictions; 542 return this; 543 } 544 setDefaultSystemSettings(@ullable Bundle settings)545 public Builder setDefaultSystemSettings(@Nullable Bundle settings) { 546 mDefaultSystemSettings = settings; 547 return this; 548 } 549 setDefaultSecureSettings(@ullable Bundle settings)550 public Builder setDefaultSecureSettings(@Nullable Bundle settings) { 551 mDefaultSecureSettings = settings; 552 return this; 553 } 554 setDefaultCrossProfileIntentFilters( @ullable List<DefaultCrossProfileIntentFilter> intentFilters)555 public Builder setDefaultCrossProfileIntentFilters( 556 @Nullable List<DefaultCrossProfileIntentFilter> intentFilters) { 557 mDefaultCrossProfileIntentFilters = intentFilters; 558 return this; 559 } 560 561 /** Sets the accessibility label associated with the user */ setAccessibilityString(@tringRes int accessibilityString)562 public Builder setAccessibilityString(@StringRes int accessibilityString) { 563 mAccessibilityString = accessibilityString; 564 return this; 565 } 566 567 /** 568 * Sets (replacing if necessary) the default UserProperties object for this user type. 569 * Takes a builder, rather than a built object, to efficiently ensure that a fresh copy of 570 * properties is stored (since it later might be modified by UserProperties#updateFromXml). 571 */ setDefaultUserProperties(UserProperties.Builder userPropertiesBuilder)572 public Builder setDefaultUserProperties(UserProperties.Builder userPropertiesBuilder) { 573 mDefaultUserProperties = userPropertiesBuilder.build(); 574 return this; 575 } 576 getDefaultUserProperties()577 public @NonNull UserProperties getDefaultUserProperties() { 578 if (mDefaultUserProperties == null) { 579 mDefaultUserProperties = new UserProperties.Builder().build(); 580 } 581 return mDefaultUserProperties; 582 } 583 getBaseType()584 @UserInfoFlag int getBaseType() { 585 return mBaseType; 586 } 587 createUserTypeDetails()588 public UserTypeDetails createUserTypeDetails() { 589 Preconditions.checkArgument(mName != null, 590 "Cannot create a UserTypeDetails with no name."); 591 Preconditions.checkArgument(hasValidBaseType(), 592 "UserTypeDetails " + mName + " has invalid baseType: " + mBaseType); 593 Preconditions.checkArgument(hasValidPropertyFlags(), 594 "UserTypeDetails " + mName + " has invalid flags: " 595 + Integer.toHexString(mDefaultUserInfoPropertyFlags)); 596 checkSystemAndMainUserPreconditions(); 597 if (hasBadge()) { 598 Preconditions.checkArgument(mBadgeLabels != null && mBadgeLabels.length != 0, 599 "UserTypeDetails " + mName + " has badge but no badgeLabels."); 600 Preconditions.checkArgument(mBadgeColors != null && mBadgeColors.length != 0, 601 "UserTypeDetails " + mName + " has badge but no badgeColors."); 602 } 603 if (!isProfile()) { 604 Preconditions.checkArgument(mDefaultCrossProfileIntentFilters == null 605 || mDefaultCrossProfileIntentFilters.isEmpty(), 606 "UserTypeDetails %s has a non empty " 607 + "defaultCrossProfileIntentFilters", mName); 608 Preconditions.checkArgument(!mProfileParentRequired, 609 "UserTypeDetails %s requires a parent but isn't a profile", mName); 610 } 611 return new UserTypeDetails( 612 mName, 613 mEnabled != 0, 614 mMaxAllowed, 615 mBaseType, 616 mDefaultUserInfoPropertyFlags, 617 mLabels, 618 mMaxAllowedPerParent, 619 mProfileParentRequired, 620 mIconBadge, 621 mBadgePlain, 622 mBadgeNoBackground, 623 mStatusBarIcon, 624 mBadgeLabels, 625 mBadgeColors, 626 mDarkThemeBadgeColors == null ? mBadgeColors : mDarkThemeBadgeColors, 627 mDefaultRestrictions, 628 mDefaultSystemSettings, 629 mDefaultSecureSettings, 630 mDefaultCrossProfileIntentFilters, 631 mAccessibilityString, 632 getDefaultUserProperties()); 633 } 634 hasBadge()635 private boolean hasBadge() { 636 return mIconBadge != Resources.ID_NULL; 637 } 638 isProfile()639 private boolean isProfile() { 640 return (mBaseType & UserInfo.FLAG_PROFILE) != 0; 641 } 642 643 // TODO(b/143784345): Refactor this when we clean up UserInfo. hasValidBaseType()644 private boolean hasValidBaseType() { 645 return mBaseType == UserInfo.FLAG_FULL 646 || mBaseType == UserInfo.FLAG_PROFILE 647 || mBaseType == UserInfo.FLAG_SYSTEM 648 || mBaseType == (UserInfo.FLAG_FULL | UserInfo.FLAG_SYSTEM); 649 } 650 651 // TODO(b/143784345): Refactor this when we clean up UserInfo. hasValidPropertyFlags()652 private boolean hasValidPropertyFlags() { 653 final int forbiddenMask = 654 UserInfo.FLAG_INITIALIZED | 655 UserInfo.FLAG_QUIET_MODE | 656 UserInfo.FLAG_FULL | 657 UserInfo.FLAG_SYSTEM | 658 UserInfo.FLAG_PROFILE; 659 return (mDefaultUserInfoPropertyFlags & forbiddenMask) == 0; 660 } 661 checkSystemAndMainUserPreconditions()662 private void checkSystemAndMainUserPreconditions() { 663 // Primary must be synonymous with System. 664 Preconditions.checkArgument( 665 ((mBaseType & UserInfo.FLAG_SYSTEM) != 0) == 666 ((mDefaultUserInfoPropertyFlags & UserInfo.FLAG_PRIMARY) != 0), 667 "UserTypeDetails " + mName + " cannot be SYSTEM xor PRIMARY."); 668 // At most one MainUser is ever allowed at a time. 669 Preconditions.checkArgument( 670 ((mDefaultUserInfoPropertyFlags & UserInfo.FLAG_MAIN) == 0) || mMaxAllowed == 1, 671 "UserTypeDetails " + mName + " must not sanction more than one MainUser."); 672 } 673 } 674 675 /** 676 * Returns whether the user type is a managed profile 677 * (i.e. {@link UserManager#USER_TYPE_PROFILE_MANAGED}). 678 */ isManagedProfile()679 public boolean isManagedProfile() { 680 return UserManager.isUserTypeManagedProfile(mName); 681 } 682 683 /** 684 * Returns whether the user type is a communal profile 685 * (i.e. {@link UserManager#USER_TYPE_PROFILE_COMMUNAL}). 686 */ isCommunalProfile()687 public boolean isCommunalProfile() { 688 return UserManager.isUserTypeCommunalProfile(mName); 689 } 690 691 /** 692 * Returns whether the user type is a private profile 693 * (i.e. {@link UserManager#USER_TYPE_PROFILE_PRIVATE}). 694 */ isPrivateProfile()695 public boolean isPrivateProfile() { 696 return UserManager.isUserTypePrivateProfile(mName); 697 } 698 } 699