UserTypeDetails - new enabled option
Adds an option for enabling/disabling a user type. enabled=0 means disabled (otherwise it is enabled). We use an int (rather than a boolean) to make it clear what String value does what (1 vs. 0). If we had used a boolean, we'd have to worry about true/True/TRUE/1/etc.; with an int, the device will fail to boot if a non-int is given. If a user type is diabled, pre-existing users of that type are unaffected. However, no new users of that type may be created. We do NOT simply use the maxAllowed option (setting it to 0 to simulate disalbing) for ease-of-use and to avoid any potential complications with pre-created users. Bug: 192577100 Bug: 142482943 Test: atest UserManagerServiceUserTypeTest Change-Id: I3db25f3a48f9ba18a5dd3e74f6ac9b7638980497
This commit is contained in:
@@ -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" />
|
||||
@@ -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
|
||||
@@ -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'.
|
||||
|
||||
@@ -2352,6 +2352,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.
|
||||
@@ -2392,7 +2395,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.
|
||||
@@ -3549,6 +3552,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;
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -405,7 +408,7 @@ public final class UserTypeDetails {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEnabled(boolean enabled) {
|
||||
public Builder setEnabled(int enabled) {
|
||||
mEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
@@ -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()));
|
||||
|
||||
Reference in New Issue
Block a user