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

Commit 6dc428f6 authored by Tony Mak's avatar Tony Mak
Browse files

Allow device owner to inflate managed profile

1. Modify DPM.isProvisioningAllowed to allow it to happen
2. Introduce hidden API createProfileForUserEvenWhenDisallowed for
   ManagedProvisioning app to create profile under DO.
   Apps with MANAGE_USERS permission can clear the
   DISALLOW_ADD_USER restriction anyway, so they do not gain extra power.

Test: runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
Test: cts-tradefed run cts --module DevicePolicyManager --test com.android.cts.devicepolicy.CustomDeviceOwnerTest#testIsProvisioningAllowed

Bug: 31895999

Change-Id: I10dc3043653130ae717a1d3d8256c9e73231bb21
parent 7e98d9e2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -83,4 +83,6 @@ interface IUserManager {
    boolean someUserHasSeedAccount(in String accountName, in String accountType);
    boolean isManagedProfile(int userId);
    boolean isDemoUser(int userId);
    UserInfo createProfileForUserEvenWhenDisallowed(in String name, int flags, int userHandle,
            in String[] disallowedPackages);
}
+18 −0
Original line number Diff line number Diff line
@@ -1373,6 +1373,24 @@ public class UserManager {
        }
    }

    /**
     * Similar to {@link #createProfileForUser(String, int, int, String[])}
     * except bypassing the checking of {@link UserManager#DISALLOW_ADD_USER}.
     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
     *
     * @see #createProfileForUser(String, int, int, String[])
     * @hide
     */
    public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags,
            @UserIdInt int userHandle, String[] disallowedPackages) {
        try {
            return mService.createProfileForUserEvenWhenDisallowed(name, flags, userHandle,
                    disallowedPackages);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a restricted profile with the specified name. This method also sets necessary
     * restrictions and adds shared accounts.
+13 −5
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.am.UserState;
import com.android.server.storage.DeviceStorageMonitorInternal;

import libcore.io.IoUtils;
import libcore.util.Objects;

@@ -2188,6 +2189,13 @@ public class UserManagerService extends IUserManager.Stub {
        return createUserInternal(name, flags, userId, disallowedPackages);
    }

    @Override
    public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags, int userId,
            String[] disallowedPackages) {
        checkManageOrCreateUsersPermission(flags);
        return createUserInternalUnchecked(name, flags, userId, disallowedPackages);
    }

    @Override
    public UserInfo createUser(String name, int flags) {
        checkManageOrCreateUsersPermission(flags);
@@ -2204,17 +2212,17 @@ public class UserManagerService extends IUserManager.Stub {
            Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
            return null;
        }
        return createUserInternalUnchecked(name, flags, parentId, disallowedPackages);
    }

    private UserInfo createUserInternalUnchecked(String name, int flags, int parentId,
            String[] disallowedPackages) {
        DeviceStorageMonitorInternal dsm = LocalServices
                .getService(DeviceStorageMonitorInternal.class);
        if (dsm.isMemoryLow()) {
            Log.w(LOG_TAG, "Cannot add user. Not enough space on disk.");
            return null;
        }
        return createUserInternalUnchecked(name, flags, parentId, disallowedPackages);
    }

    private UserInfo createUserInternalUnchecked(String name, int flags, int parentId,
            String[] disallowedPackages) {
        if (ActivityManager.isLowRamDeviceStatic()) {
            return null;
        }
+7 −13
Original line number Diff line number Diff line
@@ -8621,22 +8621,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            synchronized (this) {
                if (mOwners.hasDeviceOwner()) {
                    if (!mInjector.userManagerIsSplitSystemUser()) {
                        // Only split-system-user systems support managed-profiles in combination with
                        // device-owner.
                        return false;
                    }
                    if (mOwners.getDeviceOwnerUserId() != UserHandle.USER_SYSTEM) {
                        // Only system device-owner supports managed-profiles. Non-system device-owner
                        // doesn't.
                        return false;
                    }
                    // STOPSHIP Only allow creating a managed profile if allowed by the device
                    // owner. http://b/31952368
                    if (mInjector.userManagerIsSplitSystemUser()) {
                        if (callingUserId == UserHandle.USER_SYSTEM) {
                        // Managed-profiles cannot be setup on the system user, only regular users.
                            // Managed-profiles cannot be setup on the system user.
                            return false;
                        }
                    }
                }
            }
            if (getProfileOwner(callingUserId) != null) {
                // Managed user cannot have a managed profile.
                return false;
+42 −0
Original line number Diff line number Diff line
@@ -237,6 +237,38 @@ public class UserManagerTest extends AndroidTestCase {
        }
    }

    // Make sure createProfile would fail if we have DISALLOW_ADD_USER.
    @MediumTest
    public void testCreateProfileForUser_disallowAddUser() throws Exception {
        final int primaryUserId = mUserManager.getPrimaryUser().id;
        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
        try {
            UserInfo userInfo = createProfileForUser("Managed",
                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
            assertNull(userInfo);
        } finally {
            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
                    primaryUserHandle);
        }
    }

    // Make sure createProfileEvenWhenDisallowedForUser bypass DISALLOW_ADD_USER.
    @MediumTest
    public void testCreateProfileForUserEvenWhenDisallowed() throws Exception {
        final int primaryUserId = mUserManager.getPrimaryUser().id;
        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
        try {
            UserInfo userInfo = createProfileEvenWhenDisallowedForUser("Managed",
                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
            assertNotNull(userInfo);
        } finally {
            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
                    primaryUserHandle);
        }
    }

    @MediumTest
    public void testAddRestrictedProfile() throws Exception {
        UserInfo userInfo = createRestrictedProfile("Profile");
@@ -474,6 +506,16 @@ public class UserManagerTest extends AndroidTestCase {
        return profile;
    }

    private UserInfo createProfileEvenWhenDisallowedForUser(String name, int flags,
            int userHandle) {
        UserInfo profile = mUserManager.createProfileForUserEvenWhenDisallowed(
                name, flags, userHandle, null);
        if (profile != null) {
            usersToRemove.add(profile.id);
        }
        return profile;
    }

    private UserInfo createRestrictedProfile(String name) {
        UserInfo profile = mUserManager.createRestrictedProfile(name);
        if (profile != null) {