diff options
author | 2025-01-09 16:38:46 -0800 | |
---|---|---|
committer | 2025-03-11 11:04:20 -0700 | |
commit | 339a240bda351ecc05ff7d5125268809e93a306b (patch) | |
tree | 878e3830026d38837df3533f7f20dc42bb33f9c6 /PermissionController/src | |
parent | 7dacebe21abe2de0a37ed4068b0a31c656de3e34 (diff) |
RESTRICT AUTOMERGE Display the system gallery storage permission as system fixed
Due to the WRITE_MEDIA_IMAGES app op, photos access cannot actually be
denied. Since the role is fixed, the permission effectively is, too
Bug: 315320090
Test: atest MediaPermissionTest#testGalleryAppListedAsFixed
Flag: EXEMPT see bug
Relnote: none
Merged-In: If9ae5366fe80fcd9eaf9c45dcee13e163207fbbe
Change-Id: If9ae5366fe80fcd9eaf9c45dcee13e163207fbbe
(cherry picked from commit 17f747d7ea2e2bb9ac5bbb7654bd5354eb4632d0)
Diffstat (limited to 'PermissionController/src')
5 files changed, 149 insertions, 65 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt index f3addd112..d45e78fe8 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 @@ class AppPermGroupUiInfoLiveData private constructor( 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 @@ class AppPermGroupUiInfoLiveData private constructor( 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 @@ class AppPermGroupUiInfoLiveData private constructor( 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 3621319a6..64df3721d 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 @@ class LightAppPermGroupLiveData private constructor( 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 @@ class LightAppPermGroupLiveData private constructor( 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.checkOpNoThrow(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 64d63bd1a..867215925 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt @@ -32,18 +32,26 @@ import android.os.UserHandle * @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 @@ -79,11 +87,21 @@ data class LightAppPermGroup( if (name !in backgroundPermNames) name else null } - val foreground = AppPermSubGroup(permissions.filter { it.key in foregroundPermNames }, - packageInfo, specialLocationGrant) - - val background = AppPermSubGroup(permissions.filter { it.key in backgroundPermNames }, - packageInfo, specialLocationGrant) + val foreground = + AppPermSubGroup( + permissions.filter { it.key in foregroundPermNames }, + packageInfo, + specialLocationGrant, + specialFixedStorageGrant + ) + + val background = + AppPermSubGroup( + permissions.filter { it.key in backgroundPermNames }, + packageInfo, + specialLocationGrant, + specialFixedStorageGrant + ) /** * Whether or not this App Permission Group has a permission which has a background mode @@ -177,16 +195,20 @@ data class LightAppPermGroup( * @param permissions The permissions contained within this subgroup, a subset of those contained * in the full 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 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 { it.value.isGrantedIncludingAppOp } + /** Whether any of this App Permission SubGroup's permissions are granted */ + val isGranted = + specialLocationGrant + ?: specialFixedStorageGrant || permissions.any { + it.value.isGrantedIncludingAppOp + } /** * Whether this App Permission SubGroup should be treated as granted. This means either: @@ -216,10 +238,8 @@ data class LightAppPermGroup( */ 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 e105a69bc..1cc17243d 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 @@ internal object RuntimePermissionsUpgradeController { 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 2216802f3..b92c6237c 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 @@ object KotlinUtils { newPerms[permName] = LightPermission(group.packageInfo, perm.permInfo, perm.isGrantedIncludingAppOp, 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 @@ object KotlinUtils { (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.isGrantedIncludingAppOp }) { if (SdkLevel.isAtLeastT()) { @@ -756,8 +769,15 @@ object KotlinUtils { 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( |