Loading core/api/test-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -463,6 +463,7 @@ package android.app.admin { method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceSecurityLogs(); method public void forceUpdateUserSetupComplete(int); method @NonNull public java.util.Set<java.lang.String> getDefaultCrossProfilePackages(); method public int getDeviceOwnerType(@NonNull android.content.ComponentName); method @NonNull public java.util.Set<java.lang.String> getDisallowedSystemApps(@NonNull android.content.ComponentName, int, @NonNull String); method public long getLastBugReportRequestTime(); method public long getLastNetworkLogRetrievalTime(); Loading @@ -478,6 +479,7 @@ package android.app.admin { method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int); method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int); method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, @Nullable String, int); method public void setDeviceOwnerType(@NonNull android.content.ComponentName, int); method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(int, int); field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED = "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED"; Loading core/java/android/app/admin/DevicePolicyManager.java +48 −0 Original line number Diff line number Diff line Loading @@ -454,6 +454,52 @@ public class DevicePolicyManager { * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li> * </ul> * * <p>Once the device admin app is set as the device owner, the following APIs are available for * managing polices on the device: * <ul> * <li>{@link #isDeviceManaged()}</li> * <li>{@link #isUninstallBlocked(ComponentName, String)}</li> * <li>{@link #setUninstallBlocked(ComponentName, String, boolean)}</li> * <li>{@link #setUserControlDisabledPackages(ComponentName, List)}</li> * <li>{@link #getUserControlDisabledPackages(ComponentName)}</li> * <li>{@link #setOrganizationName(ComponentName, CharSequence)}</li> * <li>{@link #setShortSupportMessage(ComponentName, CharSequence)}</li> * <li>{@link #isBackupServiceEnabled(ComponentName)}</li> * <li>{@link #setBackupServiceEnabled(ComponentName, boolean)}</li> * <li>{@link #isLockTaskPermitted(String)}</li> * <li>{@link #setLockTaskFeatures(ComponentName, int)}, where the following lock task features * can be set (otherwise a {@link SecurityException} will be thrown):</li> * <ul> * <li>{@link #LOCK_TASK_FEATURE_SYSTEM_INFO}</li> * <li>{@link #LOCK_TASK_FEATURE_KEYGUARD}</li> * <li>{@link #LOCK_TASK_FEATURE_HOME}</li> * <li>{@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS}</li> * <li>{@link #LOCK_TASK_FEATURE_NOTIFICATIONS}</li> * </ul> * <li>{@link #setLockTaskPackages(ComponentName, String[])}</li> * <li>{@link #addPersistentPreferredActivity(ComponentName, IntentFilter, ComponentName)}</li> * <li>{@link #clearPackagePersistentPreferredActivities(ComponentName, String)} </li> * <li>{@link #wipeData(int)}</li> * <li>{@link #isDeviceOwnerApp(String)}</li> * <li>{@link #clearDeviceOwnerApp(String)}</li> * <li>{@link #setPermissionGrantState(ComponentName, String, String, int)}, where * {@link permission#READ_PHONE_STATE} is the <b>only</b> permission that can be * {@link #PERMISSION_GRANT_STATE_GRANTED}, {@link #PERMISSION_GRANT_STATE_DENIED}, or * {@link #PERMISSION_GRANT_STATE_DEFAULT} and can <b>only</b> be applied to the device admin * app (otherwise a {@link SecurityException} will be thrown)</li> * <li>{@link #addUserRestriction(ComponentName, String)}, where the following user restrictions * are permitted (otherwise a {@link SecurityException} will be thrown):</li> * <ul> * <li>{@link UserManager#DISALLOW_ADD_USER}</li> * <li>{@link UserManager#DISALLOW_DEBUGGING_FEATURES}</li> * <li>{@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}</li> * <li>{@link UserManager#DISALLOW_SAFE_BOOT}</li> * <li>{@link UserManager#DISALLOW_CONFIG_DATE_TIME}</li> * <li>{@link UserManager#DISALLOW_OUTGOING_CALLS}</li> * </ul> * <li>{@link #clearUserRestriction(ComponentName, String)}</li> * </ul> * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) Loading Loading @@ -14577,6 +14623,7 @@ public class DevicePolicyManager { * * @hide */ @TestApi public void setDeviceOwnerType(@NonNull ComponentName admin, @DeviceOwnerType int deviceOwnerType) { throwIfParentInstance("setDeviceOwnerType"); Loading @@ -14600,6 +14647,7 @@ public class DevicePolicyManager { * * @hide */ @TestApi @DeviceOwnerType public int getDeviceOwnerType(@NonNull ComponentName admin) { throwIfParentInstance("getDeviceOwnerType"); services/core/java/com/android/server/pm/UserRestrictionsUtils.java +22 −0 Original line number Diff line number Diff line Loading @@ -284,6 +284,19 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY ); /** * User restrictions available to a device owner whose type is * {@link android.app.admin.DevicePolicyManager#DEVICE_OWNER_TYPE_FINANCED}. */ private static final Set<String> FINANCED_DEVICE_OWNER_RESTRICTIONS = Sets.newArraySet( UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_DEBUGGING_FEATURES, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserManager.DISALLOW_SAFE_BOOT, UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_OUTGOING_CALLS ); /** * Returns whether the given restriction name is valid (and logs it if it isn't). */ Loading Loading @@ -457,6 +470,15 @@ public class UserRestrictionsUtils { return DEFAULT_ENABLED_FOR_MANAGED_PROFILES; } /** * @return {@code true} only if the restriction is allowed for financed devices and can be set * by a device owner. Otherwise, {@code false} would be returned. */ public static boolean canFinancedDeviceOwnerChange(String restriction) { return FINANCED_DEVICE_OWNER_RESTRICTIONS.contains(restriction) && canDeviceOwnerChange(restriction); } /** * Whether given user restriction should be enforced globally. */ Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +337 −192 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +302 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,14 @@ import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO; import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI; import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID; import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM; Loading Loading @@ -101,6 +109,7 @@ import android.app.admin.WifiSsidPolicy; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading Loading @@ -138,6 +147,9 @@ import com.android.internal.widget.LockscreenCredential; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.devicepolicy.DevicePolicyManagerService.RestrictionsListener; import com.android.server.pm.RestrictionsSet; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserRestrictionsUtils; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; Loading Loading @@ -7763,6 +7775,296 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThrows(IllegalStateException.class, () -> dpm.getDeviceOwnerType(admin2)); } @Test public void testSetUserRestriction_financeDo_invalidRestrictions_restrictionNotSet() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); for (String restriction : UserRestrictionsUtils.USER_RESTRICTIONS) { if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(restriction)) { assertNoDeviceOwnerRestrictions(); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.addUserRestriction(admin1, restriction)); verify(getServices().userManagerInternal, never()) .setDevicePolicyUserRestrictions(anyInt(), any(), any(), anyBoolean()); } } } @Test public void testSetUserRestriction_financeDo_validRestrictions_setsRestriction() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); for (String restriction : UserRestrictionsUtils.USER_RESTRICTIONS) { if (UserRestrictionsUtils.canFinancedDeviceOwnerChange(restriction)) { assertNoDeviceOwnerRestrictions(); dpm.addUserRestriction(admin1, restriction); Bundle globalRestrictions = dpms.getDeviceOwnerAdminLocked().getGlobalUserRestrictions( UserManagerInternal.OWNER_TYPE_DEVICE_OWNER); RestrictionsSet localRestrictions = new RestrictionsSet(); localRestrictions.updateRestrictions( UserHandle.USER_SYSTEM, dpms.getDeviceOwnerAdminLocked().getLocalUserRestrictions( UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); verify(getServices().userManagerInternal) .setDevicePolicyUserRestrictions(eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(globalRestrictions), MockUtils.checkUserRestrictions( UserHandle.USER_SYSTEM, localRestrictions), eq(true)); reset(getServices().userManagerInternal); dpm.clearUserRestriction(admin1, restriction); reset(getServices().userManagerInternal); } } } @Test public void testSetLockTaskFeatures_financeDo_validLockTaskFeatures_lockTaskFeaturesSet() throws Exception { int validLockTaskFeatures = LOCK_TASK_FEATURE_SYSTEM_INFO | LOCK_TASK_FEATURE_KEYGUARD | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_GLOBAL_ACTIONS | LOCK_TASK_FEATURE_NOTIFICATIONS; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setLockTaskFeatures(admin1, validLockTaskFeatures); verify(getServices().iactivityTaskManager) .updateLockTaskFeatures(eq(UserHandle.USER_SYSTEM), eq(validLockTaskFeatures)); } @Test public void testSetLockTaskFeatures_financeDo_invalidLockTaskFeatures_throwsException() throws Exception { int invalidLockTaskFeatures = LOCK_TASK_FEATURE_NONE | LOCK_TASK_FEATURE_OVERVIEW | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); // Called during setup. verify(getServices().iactivityTaskManager).updateLockTaskFeatures(anyInt(), anyInt()); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.setLockTaskFeatures(admin1, invalidLockTaskFeatures)); verifyNoMoreInteractions(getServices().iactivityTaskManager); } @Test public void testIsUninstallBlocked_financeDo_success() throws Exception { String packageName = "com.android.foo.package"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); when(getServices().ipackageManager.getBlockUninstallForUser( eq(packageName), eq(UserHandle.USER_SYSTEM))) .thenReturn(true); assertThat(dpm.isUninstallBlocked(admin1, packageName)).isTrue(); } @Test public void testSetUninstallBlocked_financeDo_success() throws Exception { String packageName = "com.android.foo.package"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setUninstallBlocked(admin1, packageName, false); verify(getServices().ipackageManager) .setBlockUninstallForUser(eq(packageName), eq(false), eq(UserHandle.USER_SYSTEM)); } @Test public void testSetUserControlDisabledPackages_financeDo_success() throws Exception { List<String> packages = new ArrayList<>(); packages.add("com.android.foo.package"); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setUserControlDisabledPackages(admin1, packages); verify(getServices().packageManagerInternal) .setDeviceOwnerProtectedPackages(eq(admin1.getPackageName()), eq(packages)); } @Test public void testGetUserControlDisabledPackages_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertThat(dpm.getUserControlDisabledPackages(admin1)).isEmpty(); } @Test public void testSetOrganizationName_financeDo_success() throws Exception { String organizationName = "Test Organization"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setOrganizationName(admin1, organizationName); assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo(organizationName); } @Test public void testSetShortSupportMessage_financeDo_success() throws Exception { String supportMessage = "Test short support message"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setShortSupportMessage(admin1, supportMessage); assertThat(dpm.getShortSupportMessage(admin1)).isEqualTo(supportMessage); } @Test public void testIsBackupServiceEnabled_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); when(getServices().ibackupManager.isBackupServiceActive(eq(UserHandle.USER_SYSTEM))) .thenReturn(true); assertThat(dpm.isBackupServiceEnabled(admin1)).isTrue(); } @Test public void testSetBackupServiceEnabled_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setBackupServiceEnabled(admin1, true); verify(getServices().ibackupManager) .setBackupServiceActive(eq(UserHandle.USER_SYSTEM), eq(true)); } @Test public void testIsLockTaskPermitted_financeDo_success() throws Exception { String packageName = "com.android.foo.package"; mockPolicyExemptApps(packageName); mockVendorPolicyExemptApps(); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertThat(dpm.isLockTaskPermitted(packageName)).isTrue(); } @Test public void testSetLockTaskPackages_financeDo_success() throws Exception { String[] packages = {"com.android.foo.package"}; mockEmptyPolicyExemptApps(); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setLockTaskPackages(admin1, packages); verify(getServices().iactivityManager) .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(packages)); } @Test public void testAddPersistentPreferredActivity_financeDo_success() throws Exception { IntentFilter filter = new IntentFilter(); ComponentName target = new ComponentName(admin2.getPackageName(), "test.class"); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.addPersistentPreferredActivity(admin1, filter, target); verify(getServices().ipackageManager) .addPersistentPreferredActivity(eq(filter), eq(target), eq(UserHandle.USER_SYSTEM)); verify(getServices().ipackageManager) .flushPackageRestrictionsAsUser(eq(UserHandle.USER_SYSTEM)); } @Test public void testClearPackagePersistentPreferredActvities_financeDo_success() throws Exception { String packageName = admin2.getPackageName(); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.clearPackagePersistentPreferredActivities(admin1, packageName); verify(getServices().ipackageManager) .clearPackagePersistentPreferredActivities( eq(packageName), eq(UserHandle.USER_SYSTEM)); verify(getServices().ipackageManager) .flushPackageRestrictionsAsUser(eq(UserHandle.USER_SYSTEM)); } @Test public void testWipeData_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); when(getServices().userManager.getUserRestrictionSource( UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM)) .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER); when(mMockContext.getResources() .getString(R.string.work_profile_deleted_description_dpm_wipe)) .thenReturn("Test string"); dpm.wipeData(0); verifyRebootWipeUserData(/* wipeEuicc= */ false); } @Test public void testIsDeviceOwnerApp_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue(); } @Test public void testClearDeviceOwnerApp_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.clearDeviceOwnerApp(admin1.getPackageName()); assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isNull(); assertThat(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)).isFalse(); verify(mMockContext.spiedContext, times(2)) .sendBroadcastAsUser( MockUtils.checkIntentAction( DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED), eq(UserHandle.SYSTEM)); } @Test public void testSetPermissionGrantState_financeDo_notReadPhoneStatePermission_throwsException() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.setPermissionGrantState(admin1, admin1.getPackageName(), permission.READ_CALENDAR, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED)); } @Test public void testSetPermissionGrantState_financeDo_grantPermissionToNonDeviceOwnerPackage_throwsException() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.setPermissionGrantState(admin1, "com.android.foo.package", permission.READ_PHONE_STATE, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED)); } @Test public void testSetUsbDataSignalingEnabled_noDeviceOwnerOrPoOfOrgOwnedDevice() { assertThrows(SecurityException.class, Loading Loading
core/api/test-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -463,6 +463,7 @@ package android.app.admin { method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceSecurityLogs(); method public void forceUpdateUserSetupComplete(int); method @NonNull public java.util.Set<java.lang.String> getDefaultCrossProfilePackages(); method public int getDeviceOwnerType(@NonNull android.content.ComponentName); method @NonNull public java.util.Set<java.lang.String> getDisallowedSystemApps(@NonNull android.content.ComponentName, int, @NonNull String); method public long getLastBugReportRequestTime(); method public long getLastNetworkLogRetrievalTime(); Loading @@ -478,6 +479,7 @@ package android.app.admin { method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int); method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int); method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, @Nullable String, int); method public void setDeviceOwnerType(@NonNull android.content.ComponentName, int); method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(int, int); field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED = "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED"; Loading
core/java/android/app/admin/DevicePolicyManager.java +48 −0 Original line number Diff line number Diff line Loading @@ -454,6 +454,52 @@ public class DevicePolicyManager { * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li> * </ul> * * <p>Once the device admin app is set as the device owner, the following APIs are available for * managing polices on the device: * <ul> * <li>{@link #isDeviceManaged()}</li> * <li>{@link #isUninstallBlocked(ComponentName, String)}</li> * <li>{@link #setUninstallBlocked(ComponentName, String, boolean)}</li> * <li>{@link #setUserControlDisabledPackages(ComponentName, List)}</li> * <li>{@link #getUserControlDisabledPackages(ComponentName)}</li> * <li>{@link #setOrganizationName(ComponentName, CharSequence)}</li> * <li>{@link #setShortSupportMessage(ComponentName, CharSequence)}</li> * <li>{@link #isBackupServiceEnabled(ComponentName)}</li> * <li>{@link #setBackupServiceEnabled(ComponentName, boolean)}</li> * <li>{@link #isLockTaskPermitted(String)}</li> * <li>{@link #setLockTaskFeatures(ComponentName, int)}, where the following lock task features * can be set (otherwise a {@link SecurityException} will be thrown):</li> * <ul> * <li>{@link #LOCK_TASK_FEATURE_SYSTEM_INFO}</li> * <li>{@link #LOCK_TASK_FEATURE_KEYGUARD}</li> * <li>{@link #LOCK_TASK_FEATURE_HOME}</li> * <li>{@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS}</li> * <li>{@link #LOCK_TASK_FEATURE_NOTIFICATIONS}</li> * </ul> * <li>{@link #setLockTaskPackages(ComponentName, String[])}</li> * <li>{@link #addPersistentPreferredActivity(ComponentName, IntentFilter, ComponentName)}</li> * <li>{@link #clearPackagePersistentPreferredActivities(ComponentName, String)} </li> * <li>{@link #wipeData(int)}</li> * <li>{@link #isDeviceOwnerApp(String)}</li> * <li>{@link #clearDeviceOwnerApp(String)}</li> * <li>{@link #setPermissionGrantState(ComponentName, String, String, int)}, where * {@link permission#READ_PHONE_STATE} is the <b>only</b> permission that can be * {@link #PERMISSION_GRANT_STATE_GRANTED}, {@link #PERMISSION_GRANT_STATE_DENIED}, or * {@link #PERMISSION_GRANT_STATE_DEFAULT} and can <b>only</b> be applied to the device admin * app (otherwise a {@link SecurityException} will be thrown)</li> * <li>{@link #addUserRestriction(ComponentName, String)}, where the following user restrictions * are permitted (otherwise a {@link SecurityException} will be thrown):</li> * <ul> * <li>{@link UserManager#DISALLOW_ADD_USER}</li> * <li>{@link UserManager#DISALLOW_DEBUGGING_FEATURES}</li> * <li>{@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}</li> * <li>{@link UserManager#DISALLOW_SAFE_BOOT}</li> * <li>{@link UserManager#DISALLOW_CONFIG_DATE_TIME}</li> * <li>{@link UserManager#DISALLOW_OUTGOING_CALLS}</li> * </ul> * <li>{@link #clearUserRestriction(ComponentName, String)}</li> * </ul> * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) Loading Loading @@ -14577,6 +14623,7 @@ public class DevicePolicyManager { * * @hide */ @TestApi public void setDeviceOwnerType(@NonNull ComponentName admin, @DeviceOwnerType int deviceOwnerType) { throwIfParentInstance("setDeviceOwnerType"); Loading @@ -14600,6 +14647,7 @@ public class DevicePolicyManager { * * @hide */ @TestApi @DeviceOwnerType public int getDeviceOwnerType(@NonNull ComponentName admin) { throwIfParentInstance("getDeviceOwnerType");
services/core/java/com/android/server/pm/UserRestrictionsUtils.java +22 −0 Original line number Diff line number Diff line Loading @@ -284,6 +284,19 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY ); /** * User restrictions available to a device owner whose type is * {@link android.app.admin.DevicePolicyManager#DEVICE_OWNER_TYPE_FINANCED}. */ private static final Set<String> FINANCED_DEVICE_OWNER_RESTRICTIONS = Sets.newArraySet( UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_DEBUGGING_FEATURES, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserManager.DISALLOW_SAFE_BOOT, UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_OUTGOING_CALLS ); /** * Returns whether the given restriction name is valid (and logs it if it isn't). */ Loading Loading @@ -457,6 +470,15 @@ public class UserRestrictionsUtils { return DEFAULT_ENABLED_FOR_MANAGED_PROFILES; } /** * @return {@code true} only if the restriction is allowed for financed devices and can be set * by a device owner. Otherwise, {@code false} would be returned. */ public static boolean canFinancedDeviceOwnerChange(String restriction) { return FINANCED_DEVICE_OWNER_RESTRICTIONS.contains(restriction) && canDeviceOwnerChange(restriction); } /** * Whether given user restriction should be enforced globally. */ Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +337 −192 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +302 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,14 @@ import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO; import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI; import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID; import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM; Loading Loading @@ -101,6 +109,7 @@ import android.app.admin.WifiSsidPolicy; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading Loading @@ -138,6 +147,9 @@ import com.android.internal.widget.LockscreenCredential; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.devicepolicy.DevicePolicyManagerService.RestrictionsListener; import com.android.server.pm.RestrictionsSet; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserRestrictionsUtils; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; Loading Loading @@ -7763,6 +7775,296 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThrows(IllegalStateException.class, () -> dpm.getDeviceOwnerType(admin2)); } @Test public void testSetUserRestriction_financeDo_invalidRestrictions_restrictionNotSet() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); for (String restriction : UserRestrictionsUtils.USER_RESTRICTIONS) { if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(restriction)) { assertNoDeviceOwnerRestrictions(); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.addUserRestriction(admin1, restriction)); verify(getServices().userManagerInternal, never()) .setDevicePolicyUserRestrictions(anyInt(), any(), any(), anyBoolean()); } } } @Test public void testSetUserRestriction_financeDo_validRestrictions_setsRestriction() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); for (String restriction : UserRestrictionsUtils.USER_RESTRICTIONS) { if (UserRestrictionsUtils.canFinancedDeviceOwnerChange(restriction)) { assertNoDeviceOwnerRestrictions(); dpm.addUserRestriction(admin1, restriction); Bundle globalRestrictions = dpms.getDeviceOwnerAdminLocked().getGlobalUserRestrictions( UserManagerInternal.OWNER_TYPE_DEVICE_OWNER); RestrictionsSet localRestrictions = new RestrictionsSet(); localRestrictions.updateRestrictions( UserHandle.USER_SYSTEM, dpms.getDeviceOwnerAdminLocked().getLocalUserRestrictions( UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); verify(getServices().userManagerInternal) .setDevicePolicyUserRestrictions(eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(globalRestrictions), MockUtils.checkUserRestrictions( UserHandle.USER_SYSTEM, localRestrictions), eq(true)); reset(getServices().userManagerInternal); dpm.clearUserRestriction(admin1, restriction); reset(getServices().userManagerInternal); } } } @Test public void testSetLockTaskFeatures_financeDo_validLockTaskFeatures_lockTaskFeaturesSet() throws Exception { int validLockTaskFeatures = LOCK_TASK_FEATURE_SYSTEM_INFO | LOCK_TASK_FEATURE_KEYGUARD | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_GLOBAL_ACTIONS | LOCK_TASK_FEATURE_NOTIFICATIONS; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setLockTaskFeatures(admin1, validLockTaskFeatures); verify(getServices().iactivityTaskManager) .updateLockTaskFeatures(eq(UserHandle.USER_SYSTEM), eq(validLockTaskFeatures)); } @Test public void testSetLockTaskFeatures_financeDo_invalidLockTaskFeatures_throwsException() throws Exception { int invalidLockTaskFeatures = LOCK_TASK_FEATURE_NONE | LOCK_TASK_FEATURE_OVERVIEW | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); // Called during setup. verify(getServices().iactivityTaskManager).updateLockTaskFeatures(anyInt(), anyInt()); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.setLockTaskFeatures(admin1, invalidLockTaskFeatures)); verifyNoMoreInteractions(getServices().iactivityTaskManager); } @Test public void testIsUninstallBlocked_financeDo_success() throws Exception { String packageName = "com.android.foo.package"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); when(getServices().ipackageManager.getBlockUninstallForUser( eq(packageName), eq(UserHandle.USER_SYSTEM))) .thenReturn(true); assertThat(dpm.isUninstallBlocked(admin1, packageName)).isTrue(); } @Test public void testSetUninstallBlocked_financeDo_success() throws Exception { String packageName = "com.android.foo.package"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setUninstallBlocked(admin1, packageName, false); verify(getServices().ipackageManager) .setBlockUninstallForUser(eq(packageName), eq(false), eq(UserHandle.USER_SYSTEM)); } @Test public void testSetUserControlDisabledPackages_financeDo_success() throws Exception { List<String> packages = new ArrayList<>(); packages.add("com.android.foo.package"); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setUserControlDisabledPackages(admin1, packages); verify(getServices().packageManagerInternal) .setDeviceOwnerProtectedPackages(eq(admin1.getPackageName()), eq(packages)); } @Test public void testGetUserControlDisabledPackages_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertThat(dpm.getUserControlDisabledPackages(admin1)).isEmpty(); } @Test public void testSetOrganizationName_financeDo_success() throws Exception { String organizationName = "Test Organization"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setOrganizationName(admin1, organizationName); assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo(organizationName); } @Test public void testSetShortSupportMessage_financeDo_success() throws Exception { String supportMessage = "Test short support message"; setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setShortSupportMessage(admin1, supportMessage); assertThat(dpm.getShortSupportMessage(admin1)).isEqualTo(supportMessage); } @Test public void testIsBackupServiceEnabled_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); when(getServices().ibackupManager.isBackupServiceActive(eq(UserHandle.USER_SYSTEM))) .thenReturn(true); assertThat(dpm.isBackupServiceEnabled(admin1)).isTrue(); } @Test public void testSetBackupServiceEnabled_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setBackupServiceEnabled(admin1, true); verify(getServices().ibackupManager) .setBackupServiceActive(eq(UserHandle.USER_SYSTEM), eq(true)); } @Test public void testIsLockTaskPermitted_financeDo_success() throws Exception { String packageName = "com.android.foo.package"; mockPolicyExemptApps(packageName); mockVendorPolicyExemptApps(); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertThat(dpm.isLockTaskPermitted(packageName)).isTrue(); } @Test public void testSetLockTaskPackages_financeDo_success() throws Exception { String[] packages = {"com.android.foo.package"}; mockEmptyPolicyExemptApps(); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.setLockTaskPackages(admin1, packages); verify(getServices().iactivityManager) .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(packages)); } @Test public void testAddPersistentPreferredActivity_financeDo_success() throws Exception { IntentFilter filter = new IntentFilter(); ComponentName target = new ComponentName(admin2.getPackageName(), "test.class"); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.addPersistentPreferredActivity(admin1, filter, target); verify(getServices().ipackageManager) .addPersistentPreferredActivity(eq(filter), eq(target), eq(UserHandle.USER_SYSTEM)); verify(getServices().ipackageManager) .flushPackageRestrictionsAsUser(eq(UserHandle.USER_SYSTEM)); } @Test public void testClearPackagePersistentPreferredActvities_financeDo_success() throws Exception { String packageName = admin2.getPackageName(); setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.clearPackagePersistentPreferredActivities(admin1, packageName); verify(getServices().ipackageManager) .clearPackagePersistentPreferredActivities( eq(packageName), eq(UserHandle.USER_SYSTEM)); verify(getServices().ipackageManager) .flushPackageRestrictionsAsUser(eq(UserHandle.USER_SYSTEM)); } @Test public void testWipeData_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); when(getServices().userManager.getUserRestrictionSource( UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM)) .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER); when(mMockContext.getResources() .getString(R.string.work_profile_deleted_description_dpm_wipe)) .thenReturn("Test string"); dpm.wipeData(0); verifyRebootWipeUserData(/* wipeEuicc= */ false); } @Test public void testIsDeviceOwnerApp_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue(); } @Test public void testClearDeviceOwnerApp_financeDo_success() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); dpm.clearDeviceOwnerApp(admin1.getPackageName()); assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isNull(); assertThat(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)).isFalse(); verify(mMockContext.spiedContext, times(2)) .sendBroadcastAsUser( MockUtils.checkIntentAction( DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED), eq(UserHandle.SYSTEM)); } @Test public void testSetPermissionGrantState_financeDo_notReadPhoneStatePermission_throwsException() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.setPermissionGrantState(admin1, admin1.getPackageName(), permission.READ_CALENDAR, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED)); } @Test public void testSetPermissionGrantState_financeDo_grantPermissionToNonDeviceOwnerPackage_throwsException() throws Exception { setDeviceOwner(); dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED); assertExpectException(SecurityException.class, /* messageRegex= */ null, () -> dpm.setPermissionGrantState(admin1, "com.android.foo.package", permission.READ_PHONE_STATE, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED)); } @Test public void testSetUsbDataSignalingEnabled_noDeviceOwnerOrPoOfOrgOwnedDevice() { assertThrows(SecurityException.class, Loading