Allow system to retrieve permission grant state
To inform the user which apps were granted permissions by the admin,
the Settings app needs to access this information without being a DO/PO.
Bug: 32692748
Test: FrameworksServicesTests unit test
Change-Id: I3770ec6343b85be9c6f7655675ed6db5cb50612c
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ec5491d..8d8934e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -6783,6 +6783,18 @@
enforceManageUsers();
}
+ private void enforceProfileOwnerOrSystemUser(ComponentName admin) {
+ synchronized (this) {
+ if (getActiveAdminWithPolicyForUidLocked(admin,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
+ != null) {
+ return;
+ }
+ }
+ Preconditions.checkState(isCallerWithSystemUid(),
+ "Only profile owner, device owner and system may call this method.");
+ }
+
private void ensureCallerPackage(@Nullable String packageName) {
if (packageName == null) {
Preconditions.checkState(isCallerWithSystemUid(),
@@ -8913,8 +8925,8 @@
PackageManager packageManager = mInjector.getPackageManager();
UserHandle user = mInjector.binderGetCallingUserHandle();
+ enforceProfileOwnerOrSystemUser(admin);
synchronized (this) {
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long ident = mInjector.binderClearCallingIdentity();
try {
int granted = mIPackageManager.checkPermission(permission,
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 c3eb09d..f1eaf9b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -3207,6 +3207,48 @@
}
}
+ public void testGetPermissionGrantState() throws Exception {
+ final String permission = "some.permission";
+ final String app1 = "com.example.app1";
+ final String app2 = "com.example.app2";
+
+ when(mContext.ipackageManager.checkPermission(eq(permission), eq(app1), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ doReturn(PackageManager.FLAG_PERMISSION_POLICY_FIXED).when(mContext.packageManager)
+ .getPermissionFlags(permission, app1, UserHandle.SYSTEM);
+ when(mContext.packageManager.getPermissionFlags(permission, app1,
+ UserHandle.of(DpmMockContext.CALLER_USER_HANDLE)))
+ .thenReturn(PackageManager.FLAG_PERMISSION_POLICY_FIXED);
+ when(mContext.ipackageManager.checkPermission(eq(permission), eq(app2), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ doReturn(0).when(mContext.packageManager).getPermissionFlags(permission, app2,
+ UserHandle.SYSTEM);
+ when(mContext.packageManager.getPermissionFlags(permission, app2,
+ UserHandle.of(DpmMockContext.CALLER_USER_HANDLE))).thenReturn(0);
+
+ // System can retrieve permission grant state.
+ mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+ assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
+ dpm.getPermissionGrantState(null, app1, permission));
+ assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
+ dpm.getPermissionGrantState(null, app2, permission));
+
+ // A regular app cannot retrieve permission grant state.
+ mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ try {
+ dpm.getPermissionGrantState(null, app1, permission);
+ fail("Didn't throw IllegalStateException");
+ } catch (IllegalStateException expected) {
+ }
+
+ // Profile owner can retrieve permission grant state.
+ setAsProfileOwner(admin1);
+ assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
+ dpm.getPermissionGrantState(admin1, app1, permission));
+ assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
+ dpm.getPermissionGrantState(admin1, app2, permission));
+ }
+
private void setUserSetupCompleteForUser(boolean isUserSetupComplete, int userhandle) {
when(mContext.settings.settingsSecureGetIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0,
userhandle)).thenReturn(isUserSetupComplete ? 1 : 0);