Loading core/res/res/xml/config_user_types.xml +8 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,10 @@ and the PROFILE user android.os.usertype.profile.MANAGED) and creates a new PROF <default-restrictions no_sms="true" no_outgoing_calls="true" /> </profile-type> <full-type name="android.os.usertype.full.RESTRICTED" enabled='0' /> <profile-type name="com.example.profilename" max-allowed-per-parent="2" /> Loading @@ -78,6 +82,7 @@ Mandatory attributes: Supported optional properties (to be used as shown in the example above) are as follows. For profile and full users: default-restrictions (with values defined in UserRestrictionUtils.USER_RESTRICTIONS) enabled For profile users only: max-allowed-per-parent icon-badge Loading @@ -98,6 +103,9 @@ If this file is updated, the properties of any pre-existing user types will be u Note, however, that default-restrictions refers to the restrictions applied at the time of user creation; therefore, the active restrictions of any pre-existing users will not be updated. If a user type is disabled, by setting enabled='0', then no further users of that type may be created; however, any pre-existing users of that type will remain. The 'change-user-type' tag should be used in conjunction with the 'version' property of 'user-types'. It defines a type change for all pre-existing users of 'from' type to the new 'to' type, if the former 'user-type's version of device is less than or equal to 'whenVersionLeq'. Loading services/core/java/com/android/server/pm/UserManagerService.java +10 −1 Original line number Diff line number Diff line Loading @@ -2357,6 +2357,9 @@ public class UserManagerService extends IUserManager.Stub { * {@link #canAddMoreProfilesToUser}. */ private boolean canAddMoreUsersOfType(UserTypeDetails userTypeDetails) { if (!userTypeDetails.isEnabled()) { return false; } final int max = userTypeDetails.getMaxAllowed(); if (max == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) { return true; // Indicates that there is no max. Loading Loading @@ -2397,7 +2400,7 @@ public class UserManagerService extends IUserManager.Stub { boolean allowedToRemoveOne) { checkManageUsersPermission("check if more profiles can be added."); final UserTypeDetails type = mUserTypes.get(userType); if (type == null) { if (type == null || !type.isEnabled()) { return false; } // Managed profiles have their own specific rules. Loading Loading @@ -3553,6 +3556,12 @@ public class UserManagerService extends IUserManager.Stub { + ") indicated SYSTEM user, which cannot be created."); return null; } if (!userTypeDetails.isEnabled()) { throwCheckedUserOperationException( "Cannot add a user of disabled type " + userType + ".", UserManager.USER_OPERATION_ERROR_MAX_USERS); } synchronized (mUsersLock) { if (mForceEphemeralUsers) { flags |= UserInfo.FLAG_EPHEMERAL; Loading services/core/java/com/android/server/pm/UserTypeDetails.java +25 −9 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ public final class UserTypeDetails { /** Name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}. */ private final @NonNull String mName; // TODO(b/142482943): Currently unused. Hook this up. /** Whether users of this type can be created. */ private final boolean mEnabled; // TODO(b/142482943): Currently unused and not set. Hook this up. Loading Loading @@ -195,7 +195,10 @@ public final class UserTypeDetails { return mName; } // TODO(b/142482943) Hook this up or delete it. /** * Returns whether this user type is enabled. * If it is not enabled, all future attempts to create users of this type will be rejected. */ public boolean isEnabled() { return mEnabled; } Loading Loading @@ -390,7 +393,7 @@ public final class UserTypeDetails { private @Nullable Bundle mDefaultSecureSettings = null; private @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters = null; private boolean mEnabled = true; private int mEnabled = 1; private int mLabel = Resources.ID_NULL; private @Nullable int[] mBadgeLabels = null; private @Nullable int[] mBadgeColors = null; Loading @@ -405,7 +408,7 @@ public final class UserTypeDetails { return this; } public Builder setEnabled(boolean enabled) { public Builder setEnabled(int enabled) { mEnabled = enabled; return this; } Loading Loading @@ -522,12 +525,25 @@ public final class UserTypeDetails { "UserTypeDetails %s has a non empty " + "defaultCrossProfileIntentFilters", mName); } return new UserTypeDetails(mName, mEnabled, mMaxAllowed, mBaseType, mDefaultUserInfoPropertyFlags, mLabel, mMaxAllowedPerParent, mIconBadge, mBadgePlain, mBadgeNoBackground, mBadgeLabels, mBadgeColors, return new UserTypeDetails( mName, mEnabled != 0, mMaxAllowed, mBaseType, mDefaultUserInfoPropertyFlags, mLabel, mMaxAllowedPerParent, mIconBadge, mBadgePlain, mBadgeNoBackground, mBadgeLabels, mBadgeColors, mDarkThemeBadgeColors == null ? mBadgeColors : mDarkThemeBadgeColors, mDefaultRestrictions, mDefaultSystemSettings, mDefaultSecureSettings, mDefaultCrossProfileIntentFilters, mIsMediaSharedWithParent); mDefaultRestrictions, mDefaultSystemSettings, mDefaultSecureSettings, mDefaultCrossProfileIntentFilters, mIsMediaSharedWithParent); } private boolean hasBadge() { Loading services/core/java/com/android/server/pm/UserTypeFactory.java +2 −0 Original line number Diff line number Diff line Loading @@ -376,6 +376,8 @@ public final class UserTypeFactory { setResAttribute(parser, "badge-no-background", builder::setBadgeNoBackground); } setIntAttribute(parser, "enabled", builder::setEnabled); // Process child elements. final int depth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, depth)) { Loading services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ public class UserManagerServiceUserTypeTest { /* letsPersonalDataIntoProfile= */false).build()); final UserTypeDetails type = new UserTypeDetails.Builder() .setName("a.name") .setEnabled(true) .setEnabled(1) .setMaxAllowed(21) .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL) Loading Loading @@ -316,6 +316,7 @@ public class UserManagerServiceUserTypeTest { builders.put(userTypeFull, new UserTypeDetails.Builder() .setName(userTypeFull) .setBaseType(FLAG_FULL) .setEnabled(0) .setDefaultRestrictions(restrictions)); final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full); Loading @@ -323,6 +324,7 @@ public class UserManagerServiceUserTypeTest { UserTypeDetails details = builders.get(userTypeFull).createUserTypeDetails(); assertEquals(UNLIMITED_NUMBER_OF_USERS, details.getMaxAllowedPerParent()); assertFalse(details.isEnabled()); assertTrue(UserRestrictionsUtils.areEqual( makeRestrictionsBundle("no_remove_user", "no_bluetooth"), details.getDefaultRestrictions())); Loading Loading
core/res/res/xml/config_user_types.xml +8 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,10 @@ and the PROFILE user android.os.usertype.profile.MANAGED) and creates a new PROF <default-restrictions no_sms="true" no_outgoing_calls="true" /> </profile-type> <full-type name="android.os.usertype.full.RESTRICTED" enabled='0' /> <profile-type name="com.example.profilename" max-allowed-per-parent="2" /> Loading @@ -78,6 +82,7 @@ Mandatory attributes: Supported optional properties (to be used as shown in the example above) are as follows. For profile and full users: default-restrictions (with values defined in UserRestrictionUtils.USER_RESTRICTIONS) enabled For profile users only: max-allowed-per-parent icon-badge Loading @@ -98,6 +103,9 @@ If this file is updated, the properties of any pre-existing user types will be u Note, however, that default-restrictions refers to the restrictions applied at the time of user creation; therefore, the active restrictions of any pre-existing users will not be updated. If a user type is disabled, by setting enabled='0', then no further users of that type may be created; however, any pre-existing users of that type will remain. The 'change-user-type' tag should be used in conjunction with the 'version' property of 'user-types'. It defines a type change for all pre-existing users of 'from' type to the new 'to' type, if the former 'user-type's version of device is less than or equal to 'whenVersionLeq'. Loading
services/core/java/com/android/server/pm/UserManagerService.java +10 −1 Original line number Diff line number Diff line Loading @@ -2357,6 +2357,9 @@ public class UserManagerService extends IUserManager.Stub { * {@link #canAddMoreProfilesToUser}. */ private boolean canAddMoreUsersOfType(UserTypeDetails userTypeDetails) { if (!userTypeDetails.isEnabled()) { return false; } final int max = userTypeDetails.getMaxAllowed(); if (max == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) { return true; // Indicates that there is no max. Loading Loading @@ -2397,7 +2400,7 @@ public class UserManagerService extends IUserManager.Stub { boolean allowedToRemoveOne) { checkManageUsersPermission("check if more profiles can be added."); final UserTypeDetails type = mUserTypes.get(userType); if (type == null) { if (type == null || !type.isEnabled()) { return false; } // Managed profiles have their own specific rules. Loading Loading @@ -3553,6 +3556,12 @@ public class UserManagerService extends IUserManager.Stub { + ") indicated SYSTEM user, which cannot be created."); return null; } if (!userTypeDetails.isEnabled()) { throwCheckedUserOperationException( "Cannot add a user of disabled type " + userType + ".", UserManager.USER_OPERATION_ERROR_MAX_USERS); } synchronized (mUsersLock) { if (mForceEphemeralUsers) { flags |= UserInfo.FLAG_EPHEMERAL; Loading
services/core/java/com/android/server/pm/UserTypeDetails.java +25 −9 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ public final class UserTypeDetails { /** Name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}. */ private final @NonNull String mName; // TODO(b/142482943): Currently unused. Hook this up. /** Whether users of this type can be created. */ private final boolean mEnabled; // TODO(b/142482943): Currently unused and not set. Hook this up. Loading Loading @@ -195,7 +195,10 @@ public final class UserTypeDetails { return mName; } // TODO(b/142482943) Hook this up or delete it. /** * Returns whether this user type is enabled. * If it is not enabled, all future attempts to create users of this type will be rejected. */ public boolean isEnabled() { return mEnabled; } Loading Loading @@ -390,7 +393,7 @@ public final class UserTypeDetails { private @Nullable Bundle mDefaultSecureSettings = null; private @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters = null; private boolean mEnabled = true; private int mEnabled = 1; private int mLabel = Resources.ID_NULL; private @Nullable int[] mBadgeLabels = null; private @Nullable int[] mBadgeColors = null; Loading @@ -405,7 +408,7 @@ public final class UserTypeDetails { return this; } public Builder setEnabled(boolean enabled) { public Builder setEnabled(int enabled) { mEnabled = enabled; return this; } Loading Loading @@ -522,12 +525,25 @@ public final class UserTypeDetails { "UserTypeDetails %s has a non empty " + "defaultCrossProfileIntentFilters", mName); } return new UserTypeDetails(mName, mEnabled, mMaxAllowed, mBaseType, mDefaultUserInfoPropertyFlags, mLabel, mMaxAllowedPerParent, mIconBadge, mBadgePlain, mBadgeNoBackground, mBadgeLabels, mBadgeColors, return new UserTypeDetails( mName, mEnabled != 0, mMaxAllowed, mBaseType, mDefaultUserInfoPropertyFlags, mLabel, mMaxAllowedPerParent, mIconBadge, mBadgePlain, mBadgeNoBackground, mBadgeLabels, mBadgeColors, mDarkThemeBadgeColors == null ? mBadgeColors : mDarkThemeBadgeColors, mDefaultRestrictions, mDefaultSystemSettings, mDefaultSecureSettings, mDefaultCrossProfileIntentFilters, mIsMediaSharedWithParent); mDefaultRestrictions, mDefaultSystemSettings, mDefaultSecureSettings, mDefaultCrossProfileIntentFilters, mIsMediaSharedWithParent); } private boolean hasBadge() { Loading
services/core/java/com/android/server/pm/UserTypeFactory.java +2 −0 Original line number Diff line number Diff line Loading @@ -376,6 +376,8 @@ public final class UserTypeFactory { setResAttribute(parser, "badge-no-background", builder::setBadgeNoBackground); } setIntAttribute(parser, "enabled", builder::setEnabled); // Process child elements. final int depth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, depth)) { Loading
services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ public class UserManagerServiceUserTypeTest { /* letsPersonalDataIntoProfile= */false).build()); final UserTypeDetails type = new UserTypeDetails.Builder() .setName("a.name") .setEnabled(true) .setEnabled(1) .setMaxAllowed(21) .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL) Loading Loading @@ -316,6 +316,7 @@ public class UserManagerServiceUserTypeTest { builders.put(userTypeFull, new UserTypeDetails.Builder() .setName(userTypeFull) .setBaseType(FLAG_FULL) .setEnabled(0) .setDefaultRestrictions(restrictions)); final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full); Loading @@ -323,6 +324,7 @@ public class UserManagerServiceUserTypeTest { UserTypeDetails details = builders.get(userTypeFull).createUserTypeDetails(); assertEquals(UNLIMITED_NUMBER_OF_USERS, details.getMaxAllowedPerParent()); assertFalse(details.isEnabled()); assertTrue(UserRestrictionsUtils.areEqual( makeRestrictionsBundle("no_remove_user", "no_bluetooth"), details.getDefaultRestrictions())); Loading