Loading services/core/java/com/android/server/pm/UserManagerService.java +2 −2 Original line number Diff line number Diff line Loading @@ -5784,8 +5784,8 @@ public class UserManagerService extends IUserManager.Stub { final boolean isRestricted = UserManager.isUserTypeRestricted(userType); final boolean isDemo = UserManager.isUserTypeDemo(userType); final boolean isManagedProfile = UserManager.isUserTypeManagedProfile(userType); final boolean isCommunalProfile = UserManager.isUserTypeCommunalProfile(userType); final boolean isPrivateProfile = UserManager.isUserTypePrivateProfile(userType); final boolean requiresProfileParent = userTypeDetails.isProfileParentRequired(); final long ident = Binder.clearCallingIdentity(); UserInfo userInfo; Loading Loading @@ -5825,7 +5825,7 @@ public class UserManagerService extends IUserManager.Stub { UserManager.USER_OPERATION_ERROR_MAX_USERS); } // TODO(b/142482943): Perhaps let the following code apply to restricted users too. if (isProfile && !isCommunalProfile && if (requiresProfileParent && !canAddMoreProfilesToUser(userType, parentId, false)) { throwCheckedUserOperationException( "Cannot add more profiles of type " + userType Loading services/core/java/com/android/server/pm/UserTypeDetails.java +25 −7 Original line number Diff line number Diff line Loading @@ -112,6 +112,9 @@ public final class UserTypeDetails { */ private final @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters; /** Whether the {@link #isProfile() profile} requires having a parent (as most profiles do). */ private final boolean mProfileParentRequired; // Fields for profiles only, controlling the nature of their badges. // All badge information should be set if {@link #hasBadge()} is true. Loading Loading @@ -174,7 +177,7 @@ public final class UserTypeDetails { private UserTypeDetails(@NonNull String name, boolean enabled, int maxAllowed, @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, @Nullable int[] labels, int maxAllowedPerParent, @Nullable int[] labels, int maxAllowedPerParent, boolean profileParentRequired, int iconBadge, int badgePlain, int badgeNoBackground, int statusBarIcon, @Nullable int[] badgeLabels, @Nullable int[] badgeColors, Loading @@ -195,6 +198,7 @@ public final class UserTypeDetails { this.mDefaultSystemSettings = defaultSystemSettings; this.mDefaultSecureSettings = defaultSecureSettings; this.mDefaultCrossProfileIntentFilters = defaultCrossProfileIntentFilters; this.mProfileParentRequired = profileParentRequired; this.mIconBadge = iconBadge; this.mBadgePlain = badgePlain; this.mBadgeNoBackground = badgeNoBackground; Loading Loading @@ -248,6 +252,14 @@ public final class UserTypeDetails { return mDefaultUserInfoPropertyFlags | mBaseType; } /** * Returns whether this type of {@link #isProfile() profile} requires having a parent. * Inapplicable to non-profiles (and therefore inapplicable to restricted profiles). */ public boolean isProfileParentRequired() { return mProfileParentRequired; } /** * Returns the resource ID corresponding to the badgeIndexth label name where the badgeIndex is * expected to be the {@link UserInfo#profileBadge} of the user. If badgeIndex exceeds the Loading Loading @@ -406,6 +418,7 @@ public final class UserTypeDetails { UserRestrictionsUtils.dumpRestrictions(pw, restrictionsPrefix, mDefaultRestrictions); } pw.print(prefix); pw.print("mProfileParentRequired: "); pw.println(mProfileParentRequired); pw.print(prefix); pw.print("mIconBadge: "); pw.println(mIconBadge); pw.print(prefix); pw.print("mBadgePlain: "); pw.println(mBadgePlain); pw.print(prefix); pw.print("mBadgeNoBackground: "); pw.println(mBadgeNoBackground); Loading Loading @@ -438,6 +451,7 @@ public final class UserTypeDetails { private @Nullable int[] mBadgeLabels = null; private @Nullable int[] mBadgeColors = null; private @Nullable int[] mDarkThemeBadgeColors = null; private boolean mProfileParentRequired = false; private @DrawableRes int mIconBadge = Resources.ID_NULL; private @DrawableRes int mBadgePlain = Resources.ID_NULL; private @DrawableRes int mBadgeNoBackground = Resources.ID_NULL; Loading Loading @@ -487,14 +501,17 @@ public final class UserTypeDetails { return this; } /** * The badge colors when the badge is on a dark background. */ /** The badge colors when the badge is on a dark background. */ public Builder setDarkThemeBadgeColors(@ColorRes int ... darkThemeBadgeColors) { mDarkThemeBadgeColors = darkThemeBadgeColors; return this; } public Builder setProfileParentRequired(boolean profileParentRequired) { mProfileParentRequired = profileParentRequired; return this; } public Builder setIconBadge(@DrawableRes int badgeIcon) { mIconBadge = badgeIcon; return this; Loading Loading @@ -541,9 +558,7 @@ public final class UserTypeDetails { return this; } /** * Sets the accessibility label associated with the user */ /** Sets the accessibility label associated with the user */ public Builder setAccessibilityString(@StringRes int accessibilityString) { mAccessibilityString = accessibilityString; return this; Loading Loading @@ -590,6 +605,8 @@ public final class UserTypeDetails { || mDefaultCrossProfileIntentFilters.isEmpty(), "UserTypeDetails %s has a non empty " + "defaultCrossProfileIntentFilters", mName); Preconditions.checkArgument(!mProfileParentRequired, "UserTypeDetails %s requires a parent but isn't a profile", mName); } return new UserTypeDetails( mName, Loading @@ -599,6 +616,7 @@ public final class UserTypeDetails { mDefaultUserInfoPropertyFlags, mLabels, mMaxAllowedPerParent, mProfileParentRequired, mIconBadge, mBadgePlain, mBadgeNoBackground, Loading services/core/java/com/android/server/pm/UserTypeFactory.java +8 −0 Original line number Diff line number Diff line Loading @@ -128,6 +128,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_CLONE) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(1) .setProfileParentRequired(true) .setLabels(R.string.profile_label_clone) .setIconBadge(com.android.internal.R.drawable.ic_clone_icon_badge) .setBadgePlain(com.android.internal.R.drawable.ic_clone_badge) Loading Loading @@ -177,6 +178,7 @@ public final class UserTypeFactory { .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE) .setMaxAllowedPerParent(1) .setProfileParentRequired(true) .setLabels( R.string.profile_label_work, R.string.profile_label_work_2, Loading Loading @@ -226,6 +228,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_TEST) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(2) .setProfileParentRequired(true) .setLabels( R.string.profile_label_test, R.string.profile_label_test, Loading Loading @@ -259,6 +262,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_COMMUNAL) .setBaseType(FLAG_PROFILE) .setMaxAllowed(1) .setProfileParentRequired(false) .setEnabled(UserManager.isCommunalProfileEnabled() ? 1 : 0) .setLabels(R.string.profile_label_communal) .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment) Loading Loading @@ -295,6 +299,7 @@ public final class UserTypeFactory { return new UserTypeDetails.Builder() .setName(USER_TYPE_PROFILE_PRIVATE) .setBaseType(FLAG_PROFILE) .setProfileParentRequired(true) .setMaxAllowedPerParent(1) .setEnabled(UserManager.isPrivateProfileEnabled() ? 1 : 0) .setLabels(R.string.profile_label_private) Loading Loading @@ -387,6 +392,7 @@ public final class UserTypeFactory { .setBaseType(FLAG_FULL) .setDefaultUserInfoPropertyFlags(FLAG_RESTRICTED) .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS) .setProfileParentRequired(false) // they have a "parent", but not a profile parent // NB: UserManagerService.createRestrictedProfile() applies hardcoded restrictions. .setDefaultRestrictions(null); } Loading Loading @@ -541,6 +547,8 @@ public final class UserTypeFactory { builder = new UserTypeDetails.Builder(); builder.setName(typeName); builder.setBaseType(FLAG_PROFILE); // Custom parentless profiles are not yet supported. builder.setProfileParentRequired(true); builders.put(typeName, builder); } else { throw new IllegalArgumentException("Creation of non-profile user type " Loading services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +6 −3 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ public class UserManagerServiceUserTypeTest { .setMaxAllowed(21) .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL) .setProfileParentRequired(true) .setBadgeLabels(23, 24, 25) .setBadgeColors(26, 27) .setIconBadge(28) Loading @@ -125,6 +126,7 @@ public class UserManagerServiceUserTypeTest { assertTrue(type.isEnabled()); assertEquals(21, type.getMaxAllowed()); assertEquals(FLAG_PROFILE | FLAG_EPHEMERAL, type.getDefaultUserInfoFlags()); assertTrue(type.isProfileParentRequired()); assertEquals(28, type.getIconBadge()); assertEquals(29, type.getBadgePlain()); assertEquals(30, type.getBadgeNoBackground()); Loading Loading @@ -452,9 +454,10 @@ public class UserManagerServiceUserTypeTest { assertTrue(aospType.getDefaultUserPropertiesReference().areItemsRestrictedOnHomeScreen()); // userTypeOem1 should be created. UserTypeDetails.Builder customType = builders.get(userTypeOem1); assertNotNull(customType); assertEquals(14, customType.createUserTypeDetails().getMaxAllowedPerParent()); assertNotNull(builders.get(userTypeOem1)); UserTypeDetails customType = builders.get(userTypeOem1).createUserTypeDetails(); assertEquals(14, customType.getMaxAllowedPerParent()); assertTrue(customType.isProfileParentRequired()); } /** Tests {@link UserTypeFactory#customizeBuilders} for customizing a FULL user. */ Loading Loading
services/core/java/com/android/server/pm/UserManagerService.java +2 −2 Original line number Diff line number Diff line Loading @@ -5784,8 +5784,8 @@ public class UserManagerService extends IUserManager.Stub { final boolean isRestricted = UserManager.isUserTypeRestricted(userType); final boolean isDemo = UserManager.isUserTypeDemo(userType); final boolean isManagedProfile = UserManager.isUserTypeManagedProfile(userType); final boolean isCommunalProfile = UserManager.isUserTypeCommunalProfile(userType); final boolean isPrivateProfile = UserManager.isUserTypePrivateProfile(userType); final boolean requiresProfileParent = userTypeDetails.isProfileParentRequired(); final long ident = Binder.clearCallingIdentity(); UserInfo userInfo; Loading Loading @@ -5825,7 +5825,7 @@ public class UserManagerService extends IUserManager.Stub { UserManager.USER_OPERATION_ERROR_MAX_USERS); } // TODO(b/142482943): Perhaps let the following code apply to restricted users too. if (isProfile && !isCommunalProfile && if (requiresProfileParent && !canAddMoreProfilesToUser(userType, parentId, false)) { throwCheckedUserOperationException( "Cannot add more profiles of type " + userType Loading
services/core/java/com/android/server/pm/UserTypeDetails.java +25 −7 Original line number Diff line number Diff line Loading @@ -112,6 +112,9 @@ public final class UserTypeDetails { */ private final @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters; /** Whether the {@link #isProfile() profile} requires having a parent (as most profiles do). */ private final boolean mProfileParentRequired; // Fields for profiles only, controlling the nature of their badges. // All badge information should be set if {@link #hasBadge()} is true. Loading Loading @@ -174,7 +177,7 @@ public final class UserTypeDetails { private UserTypeDetails(@NonNull String name, boolean enabled, int maxAllowed, @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, @Nullable int[] labels, int maxAllowedPerParent, @Nullable int[] labels, int maxAllowedPerParent, boolean profileParentRequired, int iconBadge, int badgePlain, int badgeNoBackground, int statusBarIcon, @Nullable int[] badgeLabels, @Nullable int[] badgeColors, Loading @@ -195,6 +198,7 @@ public final class UserTypeDetails { this.mDefaultSystemSettings = defaultSystemSettings; this.mDefaultSecureSettings = defaultSecureSettings; this.mDefaultCrossProfileIntentFilters = defaultCrossProfileIntentFilters; this.mProfileParentRequired = profileParentRequired; this.mIconBadge = iconBadge; this.mBadgePlain = badgePlain; this.mBadgeNoBackground = badgeNoBackground; Loading Loading @@ -248,6 +252,14 @@ public final class UserTypeDetails { return mDefaultUserInfoPropertyFlags | mBaseType; } /** * Returns whether this type of {@link #isProfile() profile} requires having a parent. * Inapplicable to non-profiles (and therefore inapplicable to restricted profiles). */ public boolean isProfileParentRequired() { return mProfileParentRequired; } /** * Returns the resource ID corresponding to the badgeIndexth label name where the badgeIndex is * expected to be the {@link UserInfo#profileBadge} of the user. If badgeIndex exceeds the Loading Loading @@ -406,6 +418,7 @@ public final class UserTypeDetails { UserRestrictionsUtils.dumpRestrictions(pw, restrictionsPrefix, mDefaultRestrictions); } pw.print(prefix); pw.print("mProfileParentRequired: "); pw.println(mProfileParentRequired); pw.print(prefix); pw.print("mIconBadge: "); pw.println(mIconBadge); pw.print(prefix); pw.print("mBadgePlain: "); pw.println(mBadgePlain); pw.print(prefix); pw.print("mBadgeNoBackground: "); pw.println(mBadgeNoBackground); Loading Loading @@ -438,6 +451,7 @@ public final class UserTypeDetails { private @Nullable int[] mBadgeLabels = null; private @Nullable int[] mBadgeColors = null; private @Nullable int[] mDarkThemeBadgeColors = null; private boolean mProfileParentRequired = false; private @DrawableRes int mIconBadge = Resources.ID_NULL; private @DrawableRes int mBadgePlain = Resources.ID_NULL; private @DrawableRes int mBadgeNoBackground = Resources.ID_NULL; Loading Loading @@ -487,14 +501,17 @@ public final class UserTypeDetails { return this; } /** * The badge colors when the badge is on a dark background. */ /** The badge colors when the badge is on a dark background. */ public Builder setDarkThemeBadgeColors(@ColorRes int ... darkThemeBadgeColors) { mDarkThemeBadgeColors = darkThemeBadgeColors; return this; } public Builder setProfileParentRequired(boolean profileParentRequired) { mProfileParentRequired = profileParentRequired; return this; } public Builder setIconBadge(@DrawableRes int badgeIcon) { mIconBadge = badgeIcon; return this; Loading Loading @@ -541,9 +558,7 @@ public final class UserTypeDetails { return this; } /** * Sets the accessibility label associated with the user */ /** Sets the accessibility label associated with the user */ public Builder setAccessibilityString(@StringRes int accessibilityString) { mAccessibilityString = accessibilityString; return this; Loading Loading @@ -590,6 +605,8 @@ public final class UserTypeDetails { || mDefaultCrossProfileIntentFilters.isEmpty(), "UserTypeDetails %s has a non empty " + "defaultCrossProfileIntentFilters", mName); Preconditions.checkArgument(!mProfileParentRequired, "UserTypeDetails %s requires a parent but isn't a profile", mName); } return new UserTypeDetails( mName, Loading @@ -599,6 +616,7 @@ public final class UserTypeDetails { mDefaultUserInfoPropertyFlags, mLabels, mMaxAllowedPerParent, mProfileParentRequired, mIconBadge, mBadgePlain, mBadgeNoBackground, Loading
services/core/java/com/android/server/pm/UserTypeFactory.java +8 −0 Original line number Diff line number Diff line Loading @@ -128,6 +128,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_CLONE) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(1) .setProfileParentRequired(true) .setLabels(R.string.profile_label_clone) .setIconBadge(com.android.internal.R.drawable.ic_clone_icon_badge) .setBadgePlain(com.android.internal.R.drawable.ic_clone_badge) Loading Loading @@ -177,6 +178,7 @@ public final class UserTypeFactory { .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE) .setMaxAllowedPerParent(1) .setProfileParentRequired(true) .setLabels( R.string.profile_label_work, R.string.profile_label_work_2, Loading Loading @@ -226,6 +228,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_TEST) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(2) .setProfileParentRequired(true) .setLabels( R.string.profile_label_test, R.string.profile_label_test, Loading Loading @@ -259,6 +262,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_COMMUNAL) .setBaseType(FLAG_PROFILE) .setMaxAllowed(1) .setProfileParentRequired(false) .setEnabled(UserManager.isCommunalProfileEnabled() ? 1 : 0) .setLabels(R.string.profile_label_communal) .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment) Loading Loading @@ -295,6 +299,7 @@ public final class UserTypeFactory { return new UserTypeDetails.Builder() .setName(USER_TYPE_PROFILE_PRIVATE) .setBaseType(FLAG_PROFILE) .setProfileParentRequired(true) .setMaxAllowedPerParent(1) .setEnabled(UserManager.isPrivateProfileEnabled() ? 1 : 0) .setLabels(R.string.profile_label_private) Loading Loading @@ -387,6 +392,7 @@ public final class UserTypeFactory { .setBaseType(FLAG_FULL) .setDefaultUserInfoPropertyFlags(FLAG_RESTRICTED) .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS) .setProfileParentRequired(false) // they have a "parent", but not a profile parent // NB: UserManagerService.createRestrictedProfile() applies hardcoded restrictions. .setDefaultRestrictions(null); } Loading Loading @@ -541,6 +547,8 @@ public final class UserTypeFactory { builder = new UserTypeDetails.Builder(); builder.setName(typeName); builder.setBaseType(FLAG_PROFILE); // Custom parentless profiles are not yet supported. builder.setProfileParentRequired(true); builders.put(typeName, builder); } else { throw new IllegalArgumentException("Creation of non-profile user type " Loading
services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +6 −3 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ public class UserManagerServiceUserTypeTest { .setMaxAllowed(21) .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL) .setProfileParentRequired(true) .setBadgeLabels(23, 24, 25) .setBadgeColors(26, 27) .setIconBadge(28) Loading @@ -125,6 +126,7 @@ public class UserManagerServiceUserTypeTest { assertTrue(type.isEnabled()); assertEquals(21, type.getMaxAllowed()); assertEquals(FLAG_PROFILE | FLAG_EPHEMERAL, type.getDefaultUserInfoFlags()); assertTrue(type.isProfileParentRequired()); assertEquals(28, type.getIconBadge()); assertEquals(29, type.getBadgePlain()); assertEquals(30, type.getBadgeNoBackground()); Loading Loading @@ -452,9 +454,10 @@ public class UserManagerServiceUserTypeTest { assertTrue(aospType.getDefaultUserPropertiesReference().areItemsRestrictedOnHomeScreen()); // userTypeOem1 should be created. UserTypeDetails.Builder customType = builders.get(userTypeOem1); assertNotNull(customType); assertEquals(14, customType.createUserTypeDetails().getMaxAllowedPerParent()); assertNotNull(builders.get(userTypeOem1)); UserTypeDetails customType = builders.get(userTypeOem1).createUserTypeDetails(); assertEquals(14, customType.getMaxAllowedPerParent()); assertTrue(customType.isProfileParentRequired()); } /** Tests {@link UserTypeFactory#customizeBuilders} for customizing a FULL user. */ Loading