Loading core/java/android/os/IUserManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading core/java/android/os/UserManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -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. Loading services/core/java/com/android/server/pm/UserManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +33 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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; Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +9 −4 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading
core/java/android/os/IUserManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
core/java/android/os/UserManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
services/core/java/com/android/server/pm/UserManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +33 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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; Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +9 −4 Original line number Diff line number Diff line Loading @@ -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 { Loading