Merge cherrypicks of ['googleplex-android-review.googlesource.com/31576081'] into security-aosp-tm-release.
Change-Id: Id952bc9011ef10a2cb45ad0a0045e8a52898caa8
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
index f3addd1..d45e78f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
@@ -17,6 +17,7 @@
package com.android.permissioncontroller.permission.data
import android.Manifest
+import android.Manifest.permission_group.READ_MEDIA_VISUAL
import android.Manifest.permission_group.STORAGE
import android.app.AppOpsManager
import android.app.Application
@@ -63,9 +64,8 @@
private val isStorage = permGroupName == STORAGE
init {
- isSpecialLocation = LocationUtils.isLocationGroupAndProvider(app,
- permGroupName, packageName) ||
- LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)
+ isSpecialLocation = LightAppPermGroupLiveData
+ .isSpecialLocationGranted(app, packageName, permGroupName, user) != null
addSource(packageInfoLiveData) {
update()
@@ -246,9 +246,14 @@
allPermInfos: Map<String, LightPermInfo>,
pkg: LightPackageInfo
): PermGrantState {
- val specialLocationState = getIsSpecialLocationState()
+ val specialLocationState = LightAppPermGroupLiveData
+ .isSpecialLocationGranted(app, packageName, permGroupName, user)
+ val specialFixedStorage = LightAppPermGroupLiveData
+ .isSpecialFixedStorageGranted(app, packageName, permGroupName, pkg.uid)
if (isStorage && isFullFilesAccessGranted(pkg)) {
return PermGrantState.PERMS_ALLOWED
+ } else if (permGroupName == READ_MEDIA_VISUAL && specialFixedStorage) {
+ return PermGrantState.PERMS_ALLOWED
}
var hasPermWithBackground = false
@@ -304,24 +309,6 @@
return PermGrantState.PERMS_DENIED
}
- private fun getIsSpecialLocationState(): Boolean? {
- if (!isSpecialLocation) {
- return null
- }
-
- val userContext = Utils.getUserContext(app, user)
- if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)) {
- return LocationUtils.isLocationEnabled(userContext)
- }
- // The permission of the extra location controller package is determined by the
- // status of the controller package itself.
- if (LocationUtils.isLocationGroupAndControllerExtraPackage(userContext,
- permGroupName, packageName)) {
- return LocationUtils.isExtraLocationControllerPackageEnabled(userContext)
- }
- return null
- }
-
private fun isFullFilesAccessGranted(pkg: LightPackageInfo): Boolean {
val packageState = if (!FullStoragePermissionAppsLiveData.isStale) {
val fullStoragePackages = FullStoragePermissionAppsLiveData.value ?: return false
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt
index 3621319..3f0ff86 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt
@@ -16,7 +16,13 @@
package com.android.permissioncontroller.permission.data
+import android.Manifest.permission_group.READ_MEDIA_VISUAL
+import android.Manifest.permission_group.STORAGE
+import android.app.AppOpsManager
+import android.app.AppOpsManager.MODE_ALLOWED
+import android.app.AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES
import android.app.Application
+import android.app.role.RoleManager
import android.content.pm.PackageManager
import android.content.pm.PermissionInfo
import android.os.Build
@@ -114,22 +120,16 @@
foregroundPerms)
}
- // Determine if this app permission group is a special location package or provider
- var specialLocationGrant: Boolean? = null
- val userContext = Utils.getUserContext(app, user)
- if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)) {
- specialLocationGrant = LocationUtils.isLocationEnabled(userContext)
- } else if (LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName,
- packageName)) {
- // The permission of the extra location controller package is determined by the status
- // of the controller package itself.
- specialLocationGrant = LocationUtils.isExtraLocationControllerPackageEnabled(
- userContext)
- }
-
val hasInstallToRuntimeSplit = hasInstallToRuntimeSplit(packageInfo, permissionMap)
- value = LightAppPermGroup(packageInfo, permGroup.groupInfo, permissionMap,
- hasInstallToRuntimeSplit, specialLocationGrant)
+ value =
+ LightAppPermGroup(
+ packageInfo,
+ permGroup.groupInfo,
+ permissionMap,
+ hasInstallToRuntimeSplit,
+ isSpecialLocationGranted(app, packageName, permGroupName, user),
+ isSpecialFixedStorageGranted(app, packageName, permGroupName, packageInfo.uid)
+ )
}
/**
@@ -209,5 +209,56 @@
return LightAppPermGroupLiveData(PermissionControllerApplication.get(),
key.first, key.second, key.third)
}
+
+ private const val SYSTEM_GALLERY_ROLE_NAME = "android.app.role.SYSTEM_GALLERY"
+
+ // Returns true if this app is the location provider or location extra package, and location
+ // access is granted, false if it is the provider/extra, and location is not granted, and
+ // null if it is not a special package
+ fun isSpecialLocationGranted(
+ app: Application,
+ packageName: String,
+ permGroupName: String,
+ user: UserHandle
+ ): Boolean? {
+ val userContext = Utils.getUserContext(app, user)
+ return if (
+ LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)
+ ) {
+ LocationUtils.isLocationEnabled(userContext)
+ } else if (
+ LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)
+ ) {
+ // The permission of the extra location controller package is determined by the status
+ // of the controller package itself.
+ LocationUtils.isExtraLocationControllerPackageEnabled(userContext)
+ } else {
+ null
+ }
+ }
+
+ // Gallery role is static, so we only need to get the set gallery app once
+ private val systemGalleryApps: List<String> by lazy {
+ val roleManager = PermissionControllerApplication.get()
+ .getSystemService(RoleManager::class.java) ?: return@lazy emptyList()
+ roleManager.getRoleHolders(SYSTEM_GALLERY_ROLE_NAME)
+ }
+
+ fun isSpecialFixedStorageGranted(
+ app: Application,
+ packageName: String,
+ permGroupName: String,
+ uid: Int
+ ): Boolean {
+ if (permGroupName != READ_MEDIA_VISUAL && permGroupName != STORAGE) {
+ return false
+ }
+ if (packageName !in systemGalleryApps) {
+ return false
+ }
+ // This is the storage group, and the gallery app. Check the write media app op
+ val appOps = app.getSystemService(AppOpsManager::class.java)
+ return appOps.unsafeCheckOpNoThrow(OPSTR_WRITE_MEDIA_IMAGES, uid, packageName) == MODE_ALLOWED
+ }
}
}
\ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt
index 2e7d3b4..515825b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt
@@ -33,18 +33,26 @@
* @param hasInstallToRuntimeSplit If this group contains a permission that was previously an
* install permission, but is currently a runtime permission
* @param specialLocationGrant If this package is the location provider, or the extra location
- * package, then the grant state of the group is not determined by the grant state of individual
- * permissions, but by other system properties
+ * package, then the grant state of the group is not determined by the grant state of individual
+ * permissions, but by other system properties
+ * @param specialFixedStorageGrant If this package holds the SYSTEM_GALLERY role, and has the
+ * WRITE_MEDIA_IMAGES app op granted, then we should show the grant state of the storage
+ * permissions as system fixed and granted.
+ *
*/
data class LightAppPermGroup(
val packageInfo: LightPackageInfo,
val permGroupInfo: LightPermGroupInfo,
val allPermissions: Map<String, LightPermission>,
val hasInstallToRuntimeSplit: Boolean,
- val specialLocationGrant: Boolean?
+ val specialLocationGrant: Boolean?,
+ val specialFixedStorageGrant: Boolean,
) {
- constructor(pI: LightPackageInfo, pGI: LightPermGroupInfo, perms: Map<String, LightPermission>):
- this(pI, pGI, perms, false, null)
+ constructor(
+ pI: LightPackageInfo,
+ pGI: LightPermGroupInfo,
+ perms: Map<String, LightPermission>
+ ) : this(pI, pGI, perms, false, null, false)
/**
* All unrestricted permissions. Usually restricted permissions are ignored
@@ -82,11 +90,23 @@
val isPlatformPermissionGroup = permGroupInfo.packageName == Utils.OS_PKG
- val foreground = AppPermSubGroup(permissions.filter { it.key in foregroundPermNames },
- packageInfo, isPlatformPermissionGroup, specialLocationGrant)
+ val foreground =
+ AppPermSubGroup(
+ permissions.filter { it.key in foregroundPermNames },
+ packageInfo,
+ isPlatformPermissionGroup,
+ specialLocationGrant,
+ specialFixedStorageGrant
+ )
- val background = AppPermSubGroup(permissions.filter { it.key in backgroundPermNames },
- packageInfo, isPlatformPermissionGroup, specialLocationGrant)
+ val background =
+ AppPermSubGroup(
+ permissions.filter { it.key in backgroundPermNames },
+ packageInfo,
+ isPlatformPermissionGroup,
+ specialLocationGrant,
+ specialFixedStorageGrant
+ )
/**
* Whether or not this App Permission Group has a permission which has a background mode
@@ -181,17 +201,19 @@
* in the full group
* @param isPlatformPermissionGroup Whether this is a platform permission group
* @param specialLocationGrant Whether this is a special location package
+ * @param specialFixedStorageGrant Whether this is a special storage grant
*/
data class AppPermSubGroup internal constructor(
private val permissions: Map<String, LightPermission>,
private val packageInfo: LightPackageInfo,
private val isPlatformPermissionGroup: Boolean,
- private val specialLocationGrant: Boolean?
+ private val specialLocationGrant: Boolean?,
+ private val specialFixedStorageGrant: Boolean
) {
/** Whether any of this App Permission SubGroup's permissions are granted */
val isGranted =
specialLocationGrant
- ?: permissions.any {
+ ?: specialFixedStorageGrant || permissions.any {
val mayGrantByPlatformOrSystem =
!isPlatformPermissionGroup || it.value.isPlatformOrSystem
it.value.isGranted && mayGrantByPlatformOrSystem
@@ -231,10 +253,8 @@
*/
val isPolicyFixed = permissions.any { it.value.isPolicyFixed }
- /**
- * Whether any of this App Permission Subgroup's permissions are fixed by the system
- */
- val isSystemFixed = permissions.any { it.value.isSystemFixed }
+ /** Whether any of this App Permission Subgroup's permissions are fixed by the system */
+ val isSystemFixed = permissions.any { it.value.isSystemFixed } || specialFixedStorageGrant
/**
* Whether any of this App Permission Subgroup's permissions are fixed by the user
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
index 12d7d45..efcd059 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
@@ -393,9 +393,15 @@
perm.flags or FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
perm.foregroundPerms)
- bgAppsWithExemption[pkgName] = LightAppPermGroup(bgApp.packageInfo,
- bgApp.permGroupInfo, allPermissionsWithxemption,
- bgApp.hasInstallToRuntimeSplit, bgApp.specialLocationGrant)
+ bgAppsWithExemption[pkgName] =
+ LightAppPermGroup(
+ bgApp.packageInfo,
+ bgApp.permGroupInfo,
+ allPermissionsWithxemption,
+ bgApp.hasInstallToRuntimeSplit,
+ bgApp.specialLocationGrant,
+ bgApp.specialFixedStorageGrant,
+ )
}
exemptions.addAll(bgLocExemptions)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index e7f4874..c1f9e7a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -472,8 +472,14 @@
newPerms[permName] = LightPermission(group.packageInfo, perm.permInfo,
perm.isGranted, perm.flags or flagsToSet, perm.foregroundPerms)
}
- return LightAppPermGroup(group.packageInfo, group.permGroupInfo, newPerms,
- group.hasInstallToRuntimeSplit, group.specialLocationGrant)
+ return LightAppPermGroup(
+ group.packageInfo,
+ group.permGroupInfo,
+ newPerms,
+ group.hasInstallToRuntimeSplit,
+ group.specialLocationGrant,
+ group.specialFixedStorageGrant,
+ )
}
/**
@@ -557,8 +563,15 @@
(app.getSystemService(ActivityManager::class.java) as ActivityManager).killUid(
group.packageInfo.uid, KILL_REASON_APP_OP_CHANGE)
}
- val newGroup = LightAppPermGroup(group.packageInfo, group.permGroupInfo, newPerms,
- group.hasInstallToRuntimeSplit, group.specialLocationGrant)
+ val newGroup =
+ LightAppPermGroup(
+ group.packageInfo,
+ group.permGroupInfo,
+ newPerms,
+ group.hasInstallToRuntimeSplit,
+ group.specialLocationGrant,
+ group.specialFixedStorageGrant,
+ )
// If any permission in the group is one time granted, start one time permission session.
if (newGroup.permissions.any { it.value.isOneTime && it.value.isGranted }) {
if (SdkLevel.isAtLeastT()) {
@@ -756,8 +769,15 @@
group.packageInfo.uid, KILL_REASON_APP_OP_CHANGE)
}
- val newGroup = LightAppPermGroup(group.packageInfo, group.permGroupInfo, newPerms,
- group.hasInstallToRuntimeSplit, group.specialLocationGrant)
+ val newGroup =
+ LightAppPermGroup(
+ group.packageInfo,
+ group.permGroupInfo,
+ newPerms,
+ group.hasInstallToRuntimeSplit,
+ group.specialLocationGrant,
+ group.specialFixedStorageGrant,
+ )
if (wasOneTime && !anyPermsOfPackageOneTimeGranted(app, newGroup.packageInfo, newGroup)) {
app.getSystemService(PermissionManager::class.java)!!.stopOneTimePermissionSession(
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt
index 0d0edc8..836ff30 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt
@@ -200,7 +200,7 @@
perms: Map<String, LightPermission> = emptyMap()
): LightAppPermGroup {
val pGi = LightPermGroupInfo(PERM_GROUP_NAME, TEST_PACKAGE_NAME, 0, 0, 0, false)
- return LightAppPermGroup(pkgInfo, pGi, perms, false, false)
+ return LightAppPermGroup(pkgInfo, pGi, perms, false, false, false)
}
/**