diff options
4 files changed, 41 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 8cbccf5feead..18992d01fcf1 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -5742,8 +5742,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; @@ -5783,7 +5783,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 diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java index 19410e50a3fb..c1f63f0cc361 100644 --- a/services/core/java/com/android/server/pm/UserTypeDetails.java +++ b/services/core/java/com/android/server/pm/UserTypeDetails.java @@ -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. @@ -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, @@ -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; @@ -249,6 +253,14 @@ public final class UserTypeDetails { } /** + * 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 * number of labels, returns the label for the highest index. @@ -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); @@ -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; @@ -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; @@ -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; @@ -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, @@ -599,6 +616,7 @@ public final class UserTypeDetails { mDefaultUserInfoPropertyFlags, mLabels, mMaxAllowedPerParent, + mProfileParentRequired, mIconBadge, mBadgePlain, mBadgeNoBackground, diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 2715025187db..58c5b1c90a66 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -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) @@ -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, @@ -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, @@ -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) @@ -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) @@ -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); } @@ -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 " diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java index 3047bcf4b146..78a7e31fb58f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java @@ -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) @@ -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()); @@ -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. */ |