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