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