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
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 9146bec2..c0de214 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -97,6 +97,7 @@
 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;
 
@@ -2189,6 +2190,13 @@
     }
 
     @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);
         return createUserInternal(name, flags, UserHandle.USER_NULL);
@@ -2204,17 +2212,17 @@
             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;
         }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e7772f3..c30d30f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8621,19 +8621,13 @@
             }
             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;
-                    }
-                    if (callingUserId == UserHandle.USER_SYSTEM) {
-                        // Managed-profiles cannot be setup on the system user, only regular users.
-                        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.
+                            return false;
+                        }
                     }
                 }
             }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 0fb2c9f..1f0422b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -237,6 +237,38 @@
         }
     }
 
+    // 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 @@
         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) {