summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--api/system-current.txt3
-rw-r--r--api/test-current.txt3
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java98
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java135
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java82
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);