Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80dc45dd authored by Adam Bookatz's avatar Adam Bookatz
Browse files

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
parent 567fe7b4
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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'.
+10 −1
Original line number Diff line number Diff line
@@ -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;
+25 −9
Original line number Diff line number Diff line
@@ -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() {
+2 −0
Original line number Diff line number Diff line
@@ -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)) {
+3 −1
Original line number Diff line number Diff line
@@ -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()));