• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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