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

Commit 38c23950 authored by Nicolas Prévot's avatar Nicolas Prévot Committed by Android (Google) Code Review
Browse files

Merge "Allow DO to provision even if it has set disallow remove mp."

parents 7242ca51 d37c4a99
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ interface IUserManager {
    void setUserEnabled(int userHandle);
    void evictCredentialEncryptionKey(int userHandle);
    boolean removeUser(int userHandle);
    boolean removeUserEvenWhenDisallowed(int userHandle);
    void setUserName(int userHandle, String name);
    void setUserIcon(int userHandle, in Bitmap icon);
    ParcelFileDescriptor getUserIcon(int userHandle);
+16 −0
Original line number Diff line number Diff line
@@ -2081,6 +2081,22 @@ public class UserManager {
        }
    }

    /**
     * Similar to {@link #removeUser(int)} except bypassing the checking of
     * {@link UserManager#DISALLOW_REMOVE_USER}
     * or {@link UserManager#DISALLOW_REMOVE_MANAGED_PROFILE}.
     *
     * @see {@link #removeUser(int)}
     * @hide
     */
    public boolean removeUserEvenWhenDisallowed(@UserIdInt int userHandle) {
        try {
            return mService.removeUserEvenWhenDisallowed(userHandle);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Updates the user's name.
     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+6 −0
Original line number Diff line number Diff line
@@ -2344,6 +2344,12 @@ public class UserManagerService extends IUserManager.Stub {
        return createUserInternalUnchecked(name, flags, userId, disallowedPackages);
    }

    @Override
    public boolean removeUserEvenWhenDisallowed(@UserIdInt int userHandle) {
        checkManageOrCreateUsersPermission("Only the system can remove users");
        return removeUserUnchecked(userHandle);
    }

    @Override
    public UserInfo createUser(String name, int flags) {
        checkManageOrCreateUsersPermission(flags);
+33 −12
Original line number Diff line number Diff line
@@ -6146,6 +6146,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private boolean isProfileOwnerPackage(String packageName, int userId) {
        synchronized (this) {
            return mOwners.hasProfileOwner(userId)
                    && mOwners.getProfileOwnerPackage(userId).equals(packageName);
        }
    }

    public boolean isProfileOwner(ComponentName who, int userId) {
        final ComponentName profileOwner = getProfileOwner(userId);
        return who != null && who.equals(profileOwner);
@@ -9119,21 +9126,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        final long ident = mInjector.binderClearCallingIdentity();
        try {
            final UserHandle callingUserHandle = UserHandle.of(callingUserId);
            if (mUserManager.hasUserRestriction(
                    UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserHandle)) {
                // The DO can initiate provisioning if the restriction was set by the DO.
                if (!isDeviceOwnerPackage(packageName, callingUserId)
                        || isAdminAffectedByRestriction(mOwners.getDeviceOwnerComponent(),
            final ComponentName ownerAdmin = getOwnerComponent(packageName, callingUserId);
            if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE,
                    callingUserHandle)) {
                // An admin can initiate provisioning if it has set the restriction.
                if (ownerAdmin == null || isAdminAffectedByRestriction(ownerAdmin,
                        UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserId)) {
                    // Caller is not DO or the restriction was set by the system.
                    return CODE_ADD_MANAGED_PROFILE_DISALLOWED;
                }
            }

            // TODO: Allow it if the caller is the DO? DO could just call removeUser() before
            // provisioning, so not strictly required...
            boolean canRemoveProfile = !mUserManager.hasUserRestriction(
                        UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, callingUserHandle);
            boolean canRemoveProfile = true;
            if (mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
                    callingUserHandle)) {
                // We can remove a profile if the admin itself has set the restriction.
                if (ownerAdmin == null || isAdminAffectedByRestriction(ownerAdmin,
                        UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
                        callingUserId)) {
                    canRemoveProfile = false;
                }
            }
            if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
                return CODE_CANNOT_ADD_MANAGED_PROFILE;
            }
@@ -9143,6 +9154,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return CODE_OK;
    }

    private ComponentName getOwnerComponent(String packageName, int userId) {
        if (isDeviceOwnerPackage(packageName, userId)) {
            return mOwners.getDeviceOwnerComponent();
        }
        if (isProfileOwnerPackage(packageName, userId)) {
            return mOwners.getProfileOwnerComponent(userId);
        }
        return null;
    }

    private int checkManagedUserProvisioningPreCondition(int callingUserId) {
        if (!hasFeatureManagedUsers()) {
            return CODE_MANAGED_USERS_NOT_SUPPORTED;
+9 −4
Original line number Diff line number Diff line
@@ -2505,18 +2505,23 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE),
                eq(UserHandle.SYSTEM)))
                .thenReturn(true);
        when(mContext.userManager.getUserRestrictionSource(
                eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE),
                eq(UserHandle.SYSTEM)))
                .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);

        // We can't remove the profile to create a new one.
        assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
                DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);

        assertCheckProvisioningPreCondition(
                DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
                DpmMockContext.ANOTHER_PACKAGE_NAME,
                DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
                DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);

        // But the device owner can still do it because it has set the restriction itself.
        assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
                DevicePolicyManager.CODE_OK);
        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
    }

    private void setup_splitUser_firstBoot_systemUser() throws Exception {