From 849fd6f58e92476af3e3eeb802e71fddf372d6f2 Mon Sep 17 00:00:00 2001 From: Mahaver Chopra Date: Thu, 3 Nov 2016 20:28:10 +0000 Subject: [PATCH] Return error code from isProvisioningAllowed Added hidden pre condition codes for PO and DO provsioning. Added hidden api checkProvisioningPreCondition, which returns codes instead of boolean. Managed provisioning can use this to show useful debug information and user facing error dialogs. Test: All DevicePolicyManagerTest pass Bug: 27467633 Change-Id: I7d2a79921bc3ac2e12d506629a35563fc7ff62bf --- .../app/admin/DevicePolicyManager.java | 184 ++++++++++++++ .../app/admin/IDevicePolicyManager.aidl | 1 + .../DevicePolicyManagerService.java | 187 ++++++++------- .../devicepolicy/DevicePolicyManagerTest.java | 227 ++++++++++++++++-- 4 files changed, 504 insertions(+), 95 deletions(-) diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 866a551a561c8..d1cb00aee3326 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1089,6 +1089,172 @@ public class DevicePolicyManager { @Retention(RetentionPolicy.SOURCE) public @interface UserProvisioningState {} + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when provisioning is allowed. + * + * @hide + */ + public static final int CODE_OK = 0; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the device already has a device + * owner. + * + * @hide + */ + public static final int CODE_HAS_DEVICE_OWNER = 1; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user has a profile owner and for + * {@link #ACTION_PROVISION_MANAGED_PROFILE} when the profile owner is already set. + * + * @hide + */ + public static final int CODE_USER_HAS_PROFILE_OWNER = 2; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user isn't running. + * + * @hide + */ + public static final int CODE_USER_NOT_RUNNING = 3; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the device has already been setup and + * for {@link #ACTION_PROVISION_MANAGED_USER} if the user has already been setup. + * + * @hide + */ + public static final int CODE_USER_SETUP_COMPLETED = 4; + + /** + * Code used to indicate that the device also has a user other than the system user. + * + * @hide + */ + public static final int CODE_NONSYSTEM_USER_EXISTS = 5; + + /** + * Code used to indicate that device has an account that prevents provisioning. + * + * @hide + */ + public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the user is not a system user. + * + * @hide + */ + public static final int CODE_NOT_SYSTEM_USER = 7; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} and {@link #ACTION_PROVISION_MANAGED_USER} + * when the device is a watch and is already paired. + * + * @hide + */ + public static final int CODE_HAS_PAIRED = 8; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} and + * {@link #ACTION_PROVISION_MANAGED_USER} on devices which do not support managed users. + * + * @see {@link PackageManager#FEATURE_MANAGED_USERS} + * @hide + */ + public static final int CODE_MANAGED_USERS_NOT_SUPPORTED = 9; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user. + * + * @hide + */ + public static final int CODE_SYSTEM_USER = 10; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the user cannot have more + * managed profiles. + * + * @hide + */ + public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_USER} and + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices not running with split system + * user. + * + * @hide + */ + public static final int CODE_NOT_SYSTEM_USER_SPLIT = 12; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices which do no support device + * admins. + * + * @hide + */ + public static final int CODE_DEVICE_ADMIN_NOT_SUPPORTED = 13; + + /** + * Result code for {@link checkProvisioningPreCondition}. + * + *

Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the device has a device owner + * and the user is a system user on a split system user device. + * + * @hide + */ + public static final int CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER = 14; + + /** + * Result codes for {@link checkProvisioningPreCondition} indicating all the provisioning pre + * conditions. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING, + CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER, CODE_HAS_PAIRED, + CODE_MANAGED_USERS_NOT_SUPPORTED, CODE_SYSTEM_USER, CODE_CANNOT_ADD_MANAGED_PROFILE, + CODE_NOT_SYSTEM_USER_SPLIT, CODE_DEVICE_ADMIN_NOT_SUPPORTED, + CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER}) + public @interface ProvisioningPreCondition {} + /** * Return true if the given administrator component is currently active (enabled) in the system. * @@ -5950,6 +6116,24 @@ public class DevicePolicyManager { } } + /** + * Checks if provisioning a managed profile or device is possible and returns one of the + * {@link ProvisioningPreCondition}. + * + * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_PROFILE}, + * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE}, + * {@link #ACTION_PROVISION_MANAGED_USER} + * @hide + */ + public @ProvisioningPreCondition int checkProvisioningPreCondition(String action) { + try { + return mService.checkProvisioningPreCondition(action); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + /** * Return if this user is a managed profile of another user. An admin can become the profile * owner of a managed profile with {@link #ACTION_PROVISION_MANAGED_PROFILE} and of a managed diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 3bc8cd015e702..f14a313c88e3b 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -269,6 +269,7 @@ interface IDevicePolicyManager { String permission, int grantState); int getPermissionGrantState(in ComponentName admin, String packageName, String permission); boolean isProvisioningAllowed(String action); + int checkProvisioningPreCondition(String action); void setKeepUninstalledPackages(in ComponentName admin,in List packageList); List getKeepUninstalledPackages(in ComponentName admin); boolean isManagedProfile(in ComponentName admin); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index e6b1fac675720..1f39faaf3f441 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -17,6 +17,21 @@ package com.android.server.devicepolicy; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; +import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY; +import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE; +import static android.app.admin.DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED; +import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER; +import static android.app.admin.DevicePolicyManager.CODE_HAS_PAIRED; +import static android.app.admin.DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED; +import static android.app.admin.DevicePolicyManager.CODE_NONSYSTEM_USER_EXISTS; +import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER; +import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT; +import static android.app.admin.DevicePolicyManager.CODE_OK; +import static android.app.admin.DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER; +import static android.app.admin.DevicePolicyManager.CODE_SYSTEM_USER; +import static android.app.admin.DevicePolicyManager.CODE_USER_HAS_PROFILE_OWNER; +import static android.app.admin.DevicePolicyManager.CODE_USER_NOT_RUNNING; +import static android.app.admin.DevicePolicyManager.CODE_USER_SETUP_COMPLETED; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE; import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA; @@ -310,21 +325,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final int PROFILE_KEYGUARD_FEATURES = PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER | PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY; - private static final int CODE_OK = 0; - private static final int CODE_HAS_DEVICE_OWNER = 1; - private static final int CODE_USER_HAS_PROFILE_OWNER = 2; - private static final int CODE_USER_NOT_RUNNING = 3; - private static final int CODE_USER_SETUP_COMPLETED = 4; - private static final int CODE_NONSYSTEM_USER_EXISTS = 5; - private static final int CODE_ACCOUNTS_NOT_EMPTY = 6; - private static final int CODE_NOT_SYSTEM_USER = 7; - private static final int CODE_HAS_PAIRED = 8; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING, - CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER }) - private @interface DeviceOwnerPreConditionCode {} - private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000; /** @@ -6520,7 +6520,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanManageProfileAndDeviceOwners(); } - final int code = checkSetDeviceOwnerPreConditionLocked(owner, userId, isAdb()); + final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner, userId, isAdb()); switch (code) { case CODE_OK: return; @@ -6547,7 +6547,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new IllegalStateException("Not allowed to set the device owner because this " + "device has already paired"); default: - throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code); + throw new IllegalStateException("Unexpected @ProvisioningPreCondition " + code); } } @@ -8754,79 +8754,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean isProvisioningAllowed(String action) { + return checkProvisioningPreConditionSkipPermission(action) == CODE_OK; + } + + @Override + public int checkProvisioningPreCondition(String action) { + enforceCanManageProfileAndDeviceOwners(); + return checkProvisioningPreConditionSkipPermission(action); + } + + private int checkProvisioningPreConditionSkipPermission(String action) { if (!mHasFeature) { - return false; + return CODE_DEVICE_ADMIN_NOT_SUPPORTED; } final int callingUserId = mInjector.userHandleGetCallingUserId(); - if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) { - if (!hasFeatureManagedUsers()) { - return false; + if (action != null) { + switch (action) { + case DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE: + return checkManagedProfileProvisioningPreCondition(callingUserId); + case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE: + return checkDeviceOwnerProvisioningPreCondition(callingUserId); + case DevicePolicyManager.ACTION_PROVISION_MANAGED_USER: + return checkManagedUserProvisioningPreCondition(callingUserId); + case DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE: + return checkManagedShareableDeviceProvisioningPreCondition(callingUserId); } - synchronized (this) { - if (mOwners.hasDeviceOwner()) { - // 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; - } - } - } - } - if (getProfileOwner(callingUserId) != null) { - // Managed user cannot have a managed profile. - return false; - } - boolean canRemoveProfile - = !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER); - final long ident = mInjector.binderClearCallingIdentity(); - try { - if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) { - return false; - } - } finally { - mInjector.binderRestoreCallingIdentity(ident); - } - return true; - } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE.equals(action)) { - return isDeviceOwnerProvisioningAllowed(callingUserId); - } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_USER.equals(action)) { - if (!hasFeatureManagedUsers()) { - return false; - } - if (!mInjector.userManagerIsSplitSystemUser()) { - // ACTION_PROVISION_MANAGED_USER only supported on split-user systems. - return false; - } - if (callingUserId == UserHandle.USER_SYSTEM) { - // System user cannot be a managed user. - return false; - } - if (hasUserSetupCompleted(callingUserId)) { - return false; - } - if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) { - return false; - } - return true; - } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE.equals(action)) { - if (!mInjector.userManagerIsSplitSystemUser()) { - // ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE only supported on split-user systems. - return false; - } - return isDeviceOwnerProvisioningAllowed(callingUserId); } throw new IllegalArgumentException("Unknown provisioning action " + action); } - /* + /** * The device owner can only be set before the setup phase of the primary user has completed, * except for adb command if no accounts or additional users are present on the device. */ - private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreConditionLocked( - @Nullable ComponentName owner, int deviceOwnerUserId, boolean isAdb) { + private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner, + int deviceOwnerUserId, boolean isAdb) { if (mOwners.hasDeviceOwner()) { return CODE_HAS_DEVICE_OWNER; } @@ -8871,13 +8834,75 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) { + private int checkDeviceOwnerProvisioningPreCondition(int deviceOwnerUserId) { synchronized (this) { - return CODE_OK == checkSetDeviceOwnerPreConditionLocked( - /* owner unknown */ null, deviceOwnerUserId, /* isAdb */ false); + return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null, + deviceOwnerUserId, /* isAdb= */ false); } } + private int checkManagedProfileProvisioningPreCondition(int callingUserId) { + if (!hasFeatureManagedUsers()) { + return CODE_MANAGED_USERS_NOT_SUPPORTED; + } + synchronized (this) { + if (mOwners.hasDeviceOwner()) { + // 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 CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER; + } + } + } + } + if (getProfileOwner(callingUserId) != null) { + // Managed user cannot have a managed profile. + return CODE_USER_HAS_PROFILE_OWNER; + } + boolean canRemoveProfile = + !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER); + final long ident = mInjector.binderClearCallingIdentity(); + try { + if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) { + return CODE_CANNOT_ADD_MANAGED_PROFILE; + } + } finally { + mInjector.binderRestoreCallingIdentity(ident); + } + return CODE_OK; + } + + private int checkManagedUserProvisioningPreCondition(int callingUserId) { + if (!hasFeatureManagedUsers()) { + return CODE_MANAGED_USERS_NOT_SUPPORTED; + } + if (!mInjector.userManagerIsSplitSystemUser()) { + // ACTION_PROVISION_MANAGED_USER only supported on split-user systems. + return CODE_NOT_SYSTEM_USER_SPLIT; + } + if (callingUserId == UserHandle.USER_SYSTEM) { + // System user cannot be a managed user. + return CODE_SYSTEM_USER; + } + if (hasUserSetupCompleted(callingUserId)) { + return CODE_USER_SETUP_COMPLETED; + } + if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) { + return CODE_HAS_PAIRED; + } + return CODE_OK; + } + + private int checkManagedShareableDeviceProvisioningPreCondition(int callingUserId) { + if (!mInjector.userManagerIsSplitSystemUser()) { + // ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE only supported on split-user systems. + return CODE_NOT_SYSTEM_USER_SPLIT; + } + return checkDeviceOwnerProvisioningPreCondition(callingUserId); + } + private boolean hasFeatureManagedUsers() { try { return mIPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 350be51210f91..387af17357c52 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -1993,7 +1993,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { // UnfinishedVerificationException. } - public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception { + public void setup_DeviceAdminFeatureOff() throws Exception { when(mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) .thenReturn(false); when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) @@ -2005,7 +2005,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception { + setup_DeviceAdminFeatureOff(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, false); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, @@ -2013,7 +2016,21 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false); } - public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception { + public void testCheckProvisioningPreCondition_DeviceAdminFeatureOff() throws Exception { + setup_DeviceAdminFeatureOff(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED); + } + + public void setup_ManagedProfileFeatureOff() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(false); initializeDpms(); @@ -2023,7 +2040,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception { + setup_ManagedProfileFeatureOff(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, @@ -2039,7 +2059,33 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false); } - public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception { + public void testCheckProvisioningPreCondition_ManagedProfileFeatureOff() throws Exception { + setup_ManagedProfileFeatureOff(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED); + + // Test again when split user is on + when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED); + } + + public void setup_nonSplitUser_firstBoot_primaryUser() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(true); when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(false); @@ -2048,7 +2094,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception { + setup_nonSplitUser_firstBoot_primaryUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, @@ -2057,8 +2106,22 @@ public class DevicePolicyManagerTest extends DpmTestBase { false /* because of non-split user */); } - public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser() + public void testCheckProvisioningPreCondition_nonSplitUser_firstBoot_primaryUser() throws Exception { + setup_nonSplitUser_firstBoot_primaryUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT); + } + + public void setup_nonSplitUser_afterDeviceSetup_primaryUser() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(true); when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(false); @@ -2067,7 +2130,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser() + throws Exception { + setup_nonSplitUser_afterDeviceSetup_primaryUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, false/* because of completed device setup */); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true); @@ -2077,7 +2144,22 @@ public class DevicePolicyManagerTest extends DpmTestBase { false/* because of non-split user */); } - public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception { + public void testCheckProvisioningPreCondition_nonSplitUser_afterDeviceSetup_primaryUser() + throws Exception { + setup_nonSplitUser_afterDeviceSetup_primaryUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_USER_SETUP_COMPLETED); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT); + } + + public void setup_splitUser_firstBoot_systemUser() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(true); when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true); @@ -2086,7 +2168,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception { + setup_splitUser_firstBoot_systemUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false /* because canAddMoreManagedProfiles returns false */); @@ -2094,10 +2179,24 @@ public class DevicePolicyManagerTest extends DpmTestBase { true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false/* because calling uid is system user */); - } - public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception { + public void testCheckProvisioningPreCondition_splitUser_firstBoot_systemUser() + throws Exception { + setup_splitUser_firstBoot_systemUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_SYSTEM_USER); + } + + public void setup_splitUser_afterDeviceSetup_systemUser() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(true); when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true); @@ -2106,7 +2205,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception { + setup_splitUser_afterDeviceSetup_systemUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true/* it's undefined behavior. Can be changed into false in the future */); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, @@ -2117,7 +2219,22 @@ public class DevicePolicyManagerTest extends DpmTestBase { false/* because calling uid is system user */); } - public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception { + public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_systemUser() + throws Exception { + setup_splitUser_afterDeviceSetup_systemUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_SYSTEM_USER); + } + + public void setup_splitUser_firstBoot_primaryUser() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(true); when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true); @@ -2126,17 +2243,33 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE); mContext.binder.callingUid = DpmMockContext.CALLER_UID; + } + public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception { + setup_splitUser_firstBoot_primaryUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, true); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, true); - } - public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser() + public void testCheckProvisioningPreCondition_splitUser_firstBoot_primaryUser() throws Exception { + setup_splitUser_firstBoot_primaryUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_OK); + } + + public void setup_splitUser_afterDeviceSetup_primaryUser() throws Exception { when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) .thenReturn(true); when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true); @@ -2145,7 +2278,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(true, DpmMockContext.CALLER_USER_HANDLE); mContext.binder.callingUid = DpmMockContext.CALLER_UID; + } + public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser() + throws Exception { + setup_splitUser_afterDeviceSetup_primaryUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true/* it's undefined behavior. Can be changed into false in the future */); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true); @@ -2155,8 +2292,22 @@ public class DevicePolicyManagerTest extends DpmTestBase { false/* because user setup completed */); } - public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser() + public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_primaryUser() throws Exception { + setup_splitUser_afterDeviceSetup_primaryUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition( + DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE, + DevicePolicyManager.CODE_OK); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, + DevicePolicyManager.CODE_USER_SETUP_COMPLETED); + } + + public void setup_provisionManagedProfileWithDeviceOwner_systemUser() throws Exception { setDeviceOwner(); when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) @@ -2167,13 +2318,24 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + } + public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser() + throws Exception { + setup_provisionManagedProfileWithDeviceOwner_systemUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false /* can't provision managed profile on system user */); } - public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser() + public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_systemUser() throws Exception { + setup_provisionManagedProfileWithDeviceOwner_systemUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER); + } + + private void setup_provisionManagedProfileWithDeviceOwner_primaryUser() throws Exception { setDeviceOwner(); when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) @@ -2184,12 +2346,23 @@ public class DevicePolicyManagerTest extends DpmTestBase { setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE); mContext.binder.callingUid = DpmMockContext.CALLER_UID; + } + public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser() + throws Exception { + setup_provisionManagedProfileWithDeviceOwner_primaryUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true); } - public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser() + public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser() throws Exception { + setup_provisionManagedProfileWithDeviceOwner_primaryUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_OK); + } + + private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception { setDeviceOwner(); when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)) @@ -2198,16 +2371,37 @@ public class DevicePolicyManagerTest extends DpmTestBase { when(mContext.userManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)) .thenReturn(true); when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE, - false /* we can't remove a managed profile*/)).thenReturn(false); + false /* we can't remove a managed profile */)).thenReturn(false); when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE, true)).thenReturn(true); setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE); mContext.binder.callingUid = DpmMockContext.CALLER_UID; + } + public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser() + throws Exception { + setup_provisionManagedProfileCantRemoveUser_primaryUser(); assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false); } + public void testCheckProvisioningPreCondition_provisionManagedProfileCantRemoveUser_primaryUser() + throws Exception { + setup_provisionManagedProfileCantRemoveUser_primaryUser(); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, + DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE); + } + + public void testCheckProvisioningPreCondition_permission() { + // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted + try { + dpm.checkProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE); + fail("Didn't throw SecurityException"); + } catch (SecurityException expected) { + } + } + public void testForceUpdateUserSetupComplete_permission() { // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted try { @@ -2518,6 +2712,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.isProvisioningAllowed(action)); } + private void assertCheckProvisioningPreCondition(String action, int provisioningCondition) { + assertEquals("checkProvisioningPreCondition(" + action + ") returning unexpected result", + provisioningCondition, dpm.checkProvisioningPreCondition(action)); + } + /** * Setup a managed profile with the specified admin and its uid. * @param admin ComponentName that's visible to the test code, which doesn't have to exist.