diff options
| -rw-r--r-- | api/current.txt | 3 | ||||
| -rw-r--r-- | api/system-current.txt | 3 | ||||
| -rw-r--r-- | api/test-current.txt | 3 | ||||
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 98 | ||||
| -rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 3 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 135 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java | 82 |
7 files changed, 276 insertions, 51 deletions
diff --git a/api/current.txt b/api/current.txt index ec38436deb3d..d7493e9c0aea 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5740,6 +5740,7 @@ package android.app.admin { method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String); + method public java.lang.String getApplicationRestrictionsManagingPackage(android.content.ComponentName); method public boolean getAutoTimeRequired(); method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName); method public boolean getCameraDisabled(android.content.ComponentName); @@ -5783,6 +5784,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); + method public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceOwnerApp(java.lang.String); method public boolean isLockTaskPermitted(java.lang.String); method public boolean isMasterVolumeMuted(android.content.ComponentName); @@ -5798,6 +5800,7 @@ package android.app.admin { method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); + method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String); method public void setAutoTimeRequired(android.content.ComponentName, boolean); method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); diff --git a/api/system-current.txt b/api/system-current.txt index d89e2ca5aaf5..f6e427aeb6cf 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5865,6 +5865,7 @@ package android.app.admin { method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String); + method public java.lang.String getApplicationRestrictionsManagingPackage(android.content.ComponentName); method public boolean getAutoTimeRequired(); method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName); method public boolean getCameraDisabled(android.content.ComponentName); @@ -5915,6 +5916,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); + method public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceOwnerApp(java.lang.String); method public boolean isLockTaskPermitted(java.lang.String); method public boolean isMasterVolumeMuted(android.content.ComponentName); @@ -5932,6 +5934,7 @@ package android.app.admin { method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException; method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); + method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String); method public void setAutoTimeRequired(android.content.ComponentName, boolean); method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); diff --git a/api/test-current.txt b/api/test-current.txt index 7cc7cb6bb370..25bd3ad4f53f 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5740,6 +5740,7 @@ package android.app.admin { method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String); + method public java.lang.String getApplicationRestrictionsManagingPackage(android.content.ComponentName); method public boolean getAutoTimeRequired(); method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName); method public boolean getCameraDisabled(android.content.ComponentName); @@ -5783,6 +5784,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); + method public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceOwnerApp(java.lang.String); method public boolean isLockTaskPermitted(java.lang.String); method public boolean isMasterVolumeMuted(android.content.ComponentName); @@ -5798,6 +5800,7 @@ package android.app.admin { method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); + method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String); method public void setAutoTimeRequired(android.content.ComponentName, boolean); method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 660ce3bd0a44..d9cd3ccaa793 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3312,8 +3312,69 @@ public class DevicePolicyManager { } /** - * Called by a profile or device owner to set the application restrictions for a given target - * application running in the profile. + * Called by a profile owner or device owner to grant permission to a package to manage + * application restrictions for the calling user via {@link #setApplicationRestrictions} and + * {@link #getApplicationRestrictions}. + * <p> + * This permission is persistent until it is later cleared by calling this method with a + * {@code null} value or uninstalling the managing package. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package name which will be given access to application restrictions + * APIs. If {@code null} is given the current package will be cleared. + */ + public void setApplicationRestrictionsManagingPackage(@NonNull ComponentName admin, + @Nullable String packageName) { + if (mService != null) { + try { + mService.setApplicationRestrictionsManagingPackage(admin, packageName); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + } + + /** + * Called by a profile owner or device owner to retrieve the application restrictions managing + * package for the current user, or {@code null} if none is set. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return The package name allowed to manage application restrictions on the current user, or + * {@code null} if none is set. + */ + public String getApplicationRestrictionsManagingPackage(@NonNull ComponentName admin) { + if (mService != null) { + try { + return mService.getApplicationRestrictionsManagingPackage(admin); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return null; + } + + /** + * Returns {@code true} if the calling package has been granted permission via + * {@link #setApplicationRestrictionsManagingPackage} to manage application + * restrictions for the calling user. + */ + public boolean isCallerApplicationRestrictionsManagingPackage() { + if (mService != null) { + try { + return mService.isCallerApplicationRestrictionsManagingPackage(); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return false; + } + + /** + * Sets the application restrictions for a given target application running in the calling user. + * + * <p>The caller must be a profile or device owner on that user, or the package allowed to + * manage application restrictions via {@link #setApplicationRestrictionsManagingPackage}; + * otherwise a security exception will be thrown. * * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be: * <ul> @@ -3323,24 +3384,25 @@ public class DevicePolicyManager { * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]} * </ul> * - * <p>The application restrictions are only made visible to the target application and the - * profile or device owner. - * * <p>If the restrictions are not available yet, but may be applied in the near future, - * the admin can notify the target application of that by adding + * the caller can notify the target application of that by adding * {@link UserManager#KEY_RESTRICTIONS_PENDING} to the settings parameter. * - * <p>The calling device admin must be a profile or device owner; if it is not, a security - * exception will be thrown. + * <p>The application restrictions are only made visible to the target application via + * {@link UserManager#getApplicationRestrictions(String)}, in addition to the profile or + * device owner, and the application restrictions managing package via + * {@link #getApplicationRestrictions}. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if called by the application restrictions managing package. * @param packageName The name of the package to update restricted settings for. * @param settings A {@link Bundle} to be parsed by the receiving application, conveying a new * set of active restrictions. * + * @see #setApplicationRestrictionsManagingPackage * @see UserManager#KEY_RESTRICTIONS_PENDING */ - public void setApplicationRestrictions(@NonNull ComponentName admin, String packageName, + public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName, Bundle settings) { if (mService != null) { try { @@ -3896,19 +3958,23 @@ public class DevicePolicyManager { } /** - * Called by a profile or device owner to get the application restrictions for a given target - * application running in the profile. + * Retrieves the application restrictions for a given target application running in the calling + * user. * - * <p>The calling device admin must be a profile or device owner; if it is not, a security - * exception will be thrown. + * <p>The caller must be a profile or device owner on that user, or the package allowed to + * manage application restrictions via {@link #setApplicationRestrictionsManagingPackage}; + * otherwise a security exception will be thrown. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if called by the application restrictions managing package. * @param packageName The name of the package to fetch restricted settings of. * @return {@link Bundle} of settings corresponding to what was set last time * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle} * if no restrictions have been set. + * + * @see {@link #setApplicationRestrictionsManagingPackage} */ - public Bundle getApplicationRestrictions(@NonNull ComponentName admin, String packageName) { + public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) { if (mService != null) { try { return mService.getApplicationRestrictions(admin, packageName); diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index d8cc2eaf280d..ac5a3030ad21 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -149,6 +149,9 @@ interface IDevicePolicyManager { void setApplicationRestrictions(in ComponentName who, in String packageName, in Bundle settings); Bundle getApplicationRestrictions(in ComponentName who, in String packageName); + void setApplicationRestrictionsManagingPackage(in ComponentName admin, in String packageName); + String getApplicationRestrictionsManagingPackage(in ComponentName admin); + boolean isCallerApplicationRestrictionsManagingPackage(); void setRestrictionsProvider(in ComponentName who, in ComponentName provider); ComponentName getRestrictionsProvider(int userHandle); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 810ee6bcd598..c9810fc4496d 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -193,6 +193,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String ATTR_PERMISSION_POLICY = "permission-policy"; private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer"; + private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER + = "application-restrictions-manager"; private static final int STATUS_BAR_DISABLE_MASK = StatusBarManager.DISABLE_EXPAND | @@ -322,6 +324,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean doNotAskCredentialsOnBoot = false; + String mApplicationRestrictionsManagingPackage; + public DevicePolicyData(int userHandle) { mUserHandle = userHandle; } @@ -1035,19 +1039,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { saveSettingsLocked(policy.mUserHandle); } - if (policy.mDelegatedCertInstallerPackage != null && - (packageName == null - || packageName.equals(policy.mDelegatedCertInstallerPackage))) { - try { - // Check if delegated cert installer package is removed. - if (mIPackageManager.getPackageInfo( - policy.mDelegatedCertInstallerPackage, 0, userHandle) == null) { - policy.mDelegatedCertInstallerPackage = null; - saveSettingsLocked(policy.mUserHandle); - } - } catch (RemoteException e) { - // Shouldn't happen - } + // Check if delegated cert installer or app restrictions managing packages are removed. + if (isRemovedPackage(packageName, policy.mDelegatedCertInstallerPackage, userHandle)) { + policy.mDelegatedCertInstallerPackage = null; + saveSettingsLocked(policy.mUserHandle); + } + if (isRemovedPackage( + packageName, policy.mApplicationRestrictionsManagingPackage, userHandle)) { + policy.mApplicationRestrictionsManagingPackage = null; + saveSettingsLocked(policy.mUserHandle); } } if (removed) { @@ -1056,6 +1056,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private boolean isRemovedPackage(String changedPackage, String targetPackage, int userHandle) { + try { + return targetPackage != null + && (changedPackage == null || changedPackage.equals(targetPackage)) + && mIPackageManager.getPackageInfo(targetPackage, 0, userHandle) == null; + } catch (RemoteException e) { + // Shouldn't happen + } + + return false; + } + /** * Unit test will subclass it to inject mocks. */ @@ -1795,6 +1807,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, ATTR_DELEGATED_CERT_INSTALLER, policy.mDelegatedCertInstallerPackage); } + if (policy.mApplicationRestrictionsManagingPackage != null) { + out.attribute(null, ATTR_APPLICATION_RESTRICTIONS_MANAGER, + policy.mApplicationRestrictionsManagingPackage); + } final int N = policy.mAdminList.size(); for (int i=0; i<N; i++) { @@ -1920,6 +1936,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } policy.mDelegatedCertInstallerPackage = parser.getAttributeValue(null, ATTR_DELEGATED_CERT_INSTALLER); + policy.mApplicationRestrictionsManagingPackage = parser.getAttributeValue(null, + ATTR_APPLICATION_RESTRICTIONS_MANAGER); type = parser.next(); int outerDepth = parser.getDepth(); @@ -4815,6 +4833,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DevicePolicyData policy = getUserData(userId); policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT; policy.mDelegatedCertInstallerPackage = null; + policy.mApplicationRestrictionsManagingPackage = null; policy.mStatusBarDisabled = false; saveSettingsLocked(userId); @@ -5187,18 +5206,68 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) { - Preconditions.checkNotNull(who, "ComponentName is null"); - final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + public void setApplicationRestrictionsManagingPackage(ComponentName admin, String packageName) { + final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (this) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + DevicePolicyData policy = getUserData(userHandle); + policy.mApplicationRestrictionsManagingPackage = packageName; + saveSettingsLocked(userHandle); + } + } + + @Override + public String getApplicationRestrictionsManagingPackage(ComponentName admin) { + final int userHandle = mInjector.userHandleGetCallingUserId(); + synchronized (this) { + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + DevicePolicyData policy = getUserData(userHandle); + return policy.mApplicationRestrictionsManagingPackage; + } + } + + @Override + public boolean isCallerApplicationRestrictionsManagingPackage() { + final int callingUid = mInjector.binderGetCallingUid(); + final int userHandle = UserHandle.getUserId(callingUid); + synchronized (this) { + final DevicePolicyData policy = getUserData(userHandle); + if (policy.mApplicationRestrictionsManagingPackage == null) { + return false; + } - long id = mInjector.binderClearCallingIdentity(); try { - mUserManager.setApplicationRestrictions(packageName, settings, userHandle); - } finally { - mInjector.binderRestoreCallingIdentity(id); + int uid = mContext.getPackageManager().getPackageUid( + policy.mApplicationRestrictionsManagingPackage, userHandle); + return uid == callingUid; + } catch (NameNotFoundException e) { + return false; + } + } + } + + private void enforceCanManageApplicationRestrictions(ComponentName who) { + if (who != null) { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); } + } else if (!isCallerApplicationRestrictionsManagingPackage()) { + throw new SecurityException( + "No admin component given, and caller cannot manage application restrictions " + + "for other apps."); + } + } + + @Override + public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) { + enforceCanManageApplicationRestrictions(who); + + final UserHandle userHandle = mInjector.binderGetCallingUserHandle(); + final long id = mInjector.binderClearCallingIdentity(); + try { + mUserManager.setApplicationRestrictions(packageName, settings, userHandle); + } finally { + mInjector.binderRestoreCallingIdentity(id); } } @@ -5764,21 +5833,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public Bundle getApplicationRestrictions(ComponentName who, String packageName) { - Preconditions.checkNotNull(who, "ComponentName is null"); - final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); - - synchronized (this) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + enforceCanManageApplicationRestrictions(who); - long id = mInjector.binderClearCallingIdentity(); - try { - Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle); - // if no restrictions were saved, mUserManager.getApplicationRestrictions - // returns null, but DPM method should return an empty Bundle as per JavaDoc - return bundle != null ? bundle : Bundle.EMPTY; - } finally { - mInjector.binderRestoreCallingIdentity(id); - } + final UserHandle userHandle = mInjector.binderGetCallingUserHandle(); + final long id = mInjector.binderClearCallingIdentity(); + try { + Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle); + // if no restrictions were saved, mUserManager.getApplicationRestrictions + // returns null, but DPM method should return an empty Bundle as per JavaDoc + return bundle != null ? bundle : Bundle.EMPTY; + } finally { + mInjector.binderRestoreCallingIdentity(id); } } 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 565ef4b72058..7747fd9a1cb5 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -944,6 +944,88 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg2").size()); } + public void testApplicationRestrictionsManagingApp() throws Exception { + setAsProfileOwner(admin1); + + final String appRestrictionsManagerPackage = "com.google.app.restrictions.manager"; + final int appRestrictionsManagerAppId = 20987; + final int appRestrictionsManagerUid = UserHandle.getUid( + DpmMockContext.CALLER_USER_HANDLE, appRestrictionsManagerAppId); + doReturn(appRestrictionsManagerUid).when(mContext.packageManager).getPackageUid( + eq(appRestrictionsManagerPackage), + eq(DpmMockContext.CALLER_USER_HANDLE)); + mContext.binder.callingUid = appRestrictionsManagerUid; + + // appRestrictionsManager package shouldn't be able to manage restrictions as the PO hasn't + // delegated that permission yet. + assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage()); + Bundle rest = new Bundle(); + rest.putString("KEY_STRING", "Foo1"); + try { + dpm.setApplicationRestrictions(null, "pkg1", rest); + fail("Didn't throw expected SecurityException"); + } catch (SecurityException expected) { + MoreAsserts.assertContainsRegex( + "caller cannot manage application restrictions", expected.getMessage()); + } + try { + dpm.getApplicationRestrictions(null, "pkg1"); + fail("Didn't throw expected SecurityException"); + } catch (SecurityException expected) { + MoreAsserts.assertContainsRegex( + "caller cannot manage application restrictions", expected.getMessage()); + } + + // Check via the profile owner that no restrictions were set. + mContext.binder.callingUid = DpmMockContext.CALLER_UID; + assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg1").size()); + + // Let appRestrictionsManagerPackage manage app restrictions + dpm.setApplicationRestrictionsManagingPackage(admin1, appRestrictionsManagerPackage); + assertEquals(appRestrictionsManagerPackage, + dpm.getApplicationRestrictionsManagingPackage(admin1)); + + // Now that package should be able to set and retrieve app restrictions. + mContext.binder.callingUid = appRestrictionsManagerUid; + assertTrue(dpm.isCallerApplicationRestrictionsManagingPackage()); + dpm.setApplicationRestrictions(null, "pkg1", rest); + Bundle returned = dpm.getApplicationRestrictions(null, "pkg1"); + assertEquals(1, returned.size(), 1); + assertEquals("Foo1", returned.get("KEY_STRING")); + + // The same app running on a separate user shouldn't be able to manage app restrictions. + mContext.binder.callingUid = UserHandle.getUid( + UserHandle.USER_SYSTEM, appRestrictionsManagerAppId); + assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage()); + try { + dpm.setApplicationRestrictions(null, "pkg1", rest); + fail("Didn't throw expected SecurityException"); + } catch (SecurityException expected) { + MoreAsserts.assertContainsRegex( + "caller cannot manage application restrictions", expected.getMessage()); + } + + // The DPM is still able to manage app restrictions, even if it allowed another app to do it + // too. + mContext.binder.callingUid = DpmMockContext.CALLER_UID; + assertEquals(returned, dpm.getApplicationRestrictions(admin1, "pkg1")); + dpm.setApplicationRestrictions(admin1, "pkg1", null); + assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg1").size()); + + // Removing the ability for the package to manage app restrictions. + dpm.setApplicationRestrictionsManagingPackage(admin1, null); + assertNull(dpm.getApplicationRestrictionsManagingPackage(admin1)); + mContext.binder.callingUid = appRestrictionsManagerUid; + assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage()); + try { + dpm.setApplicationRestrictions(null, "pkg1", null); + fail("Didn't throw expected SecurityException"); + } catch (SecurityException expected) { + MoreAsserts.assertContainsRegex( + "caller cannot manage application restrictions", expected.getMessage()); + } + } + public void testSetUserRestriction_asDo() throws Exception { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_USERS); |