Loading services/permission/java/com/android/server/permission/access/AccessPolicy.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -431,7 +431,7 @@ private constructor( companion object { companion object { private val LOG_TAG = AccessPolicy::class.java.simpleName private val LOG_TAG = AccessPolicy::class.java.simpleName internal const val VERSION_LATEST = 16 internal const val VERSION_LATEST = 17 private const val TAG_ACCESS = "access" private const val TAG_ACCESS = "access" private const val TAG_DEFAULT_PERMISSION_GRANT = "default-permission-grant" private const val TAG_DEFAULT_PERMISSION_GRANT = "default-permission-grant" Loading services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt +172 −2 Original line number Original line Diff line number Diff line Loading @@ -17,8 +17,10 @@ package com.android.server.permission.access.permission package com.android.server.permission.access.permission import android.Manifest import android.Manifest import android.health.connect.HealthPermissions import android.os.Build import android.os.Build import android.util.Slog import android.util.Slog import com.android.server.permission.access.GetStateScope import com.android.server.permission.access.MutateStateScope import com.android.server.permission.access.MutateStateScope import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.util.andInv import com.android.server.permission.access.util.andInv Loading Loading @@ -64,7 +66,7 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { ", version: $version, user: $userId", ", version: $version, user: $userId", ) ) upgradeAuralVisualMediaPermissions(packageState, userId) upgradeAuralVisualMediaPermissions(packageState, userId) upgradeBodySensorPermissions(packageState, userId) upgradeBodySensorBackgroundPermissions(packageState, userId) } } // TODO Enable isAtLeastU check, when moving subsystem to mainline. // TODO Enable isAtLeastU check, when moving subsystem to mainline. if (version <= 14 /*&& SdkLevel.isAtLeastU()*/) { if (version <= 14 /*&& SdkLevel.isAtLeastU()*/) { Loading @@ -75,6 +77,16 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { ) ) upgradeUserSelectedVisualMediaPermission(packageState, userId) upgradeUserSelectedVisualMediaPermission(packageState, userId) } } // TODO Enable isAtLeastB check, when moving subsystem to mainline. if (version <= 16 /*&& SdkLevel.isAtLeastB()*/) { Slog.v( LOG_TAG, "Upgrading body sensor / read heart rate permissions for package: $packageName" + ", version: $version, user: $userId", ) upgradeBodySensorReadHeartRatePermissions(packageState, userId) } // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... } // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... } // Also increase LATEST_VERSION // Also increase LATEST_VERSION } } Loading Loading @@ -182,7 +194,7 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { } } } } private fun MutateStateScope.upgradeBodySensorPermissions( private fun MutateStateScope.upgradeBodySensorBackgroundPermissions( packageState: PackageState, packageState: PackageState, userId: Int, userId: Int, ) { ) { Loading Loading @@ -256,6 +268,112 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { } } } } /** * Upgrade permissions based on the body sensors and health permissions status. * * Starting in BAKLAVA, the BODY_SENSORS and BODY_SENSORS_BACKGROUND permissions are being * replaced by the READ_HEART_RATE and READ_HEALTH_DATA_IN_BACKGROUND permissions respectively. * To ensure that older apps can continue using BODY_SENSORS without breaking we need to keep * their permission state in sync with the new health permissions. * * The approach we take is to be as conservative as possible. This means if either permission is * not granted, then we want to ensure that both end up not granted to force the user to * re-grant with the expanded scope. */ private fun MutateStateScope.upgradeBodySensorReadHeartRatePermissions( packageState: PackageState, userId: Int, ) { val androidPackage = packageState.androidPackage!! if (androidPackage.targetSdkVersion >= Build.VERSION_CODES.BAKLAVA) { return } // First sync BODY_SENSORS and READ_HEART_RATE, if required. val isBodySensorsRequested = Manifest.permission.BODY_SENSORS in androidPackage.requestedPermissions val isReadHeartRateRequested = HealthPermissions.READ_HEART_RATE in androidPackage.requestedPermissions var isBodySensorsGranted = isPermissionGranted(packageState, userId, Manifest.permission.BODY_SENSORS) if (isBodySensorsRequested && isReadHeartRateRequested) { val isReadHeartRateGranted = isPermissionGranted(packageState, userId, HealthPermissions.READ_HEART_RATE) if (isBodySensorsGranted != isReadHeartRateGranted) { if (isBodySensorsGranted) { if ( revokeRuntimePermission( packageState, userId, Manifest.permission.BODY_SENSORS, ) ) { isBodySensorsGranted = false } } if (isReadHeartRateGranted) { revokeRuntimePermission(packageState, userId, HealthPermissions.READ_HEART_RATE) } } } // Then check to ensure we haven't put the background/foreground permissions out of sync. var isBodySensorsBackgroundGranted = isPermissionGranted(packageState, userId, Manifest.permission.BODY_SENSORS_BACKGROUND) // Background permission should not be granted without the foreground permission. if (!isBodySensorsGranted && isBodySensorsBackgroundGranted) { if ( revokeRuntimePermission( packageState, userId, Manifest.permission.BODY_SENSORS_BACKGROUND, ) ) { isBodySensorsBackgroundGranted = false } } // Finally sync BODY_SENSORS_BACKGROUND and READ_HEALTH_DATA_IN_BACKGROUND, if required. val isBodySensorsBackgroundRequested = Manifest.permission.BODY_SENSORS_BACKGROUND in androidPackage.requestedPermissions val isReadHealthDataInBackgroundRequested = HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND in androidPackage.requestedPermissions if (isBodySensorsBackgroundRequested && isReadHealthDataInBackgroundRequested) { val isReadHealthDataInBackgroundGranted = isPermissionGranted( packageState, userId, HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, ) if (isBodySensorsBackgroundGranted != isReadHealthDataInBackgroundGranted) { if (isBodySensorsBackgroundGranted) { revokeRuntimePermission( packageState, userId, Manifest.permission.BODY_SENSORS_BACKGROUND, ) } if (isReadHealthDataInBackgroundGranted) { revokeRuntimePermission( packageState, userId, HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, ) } } } } private fun GetStateScope.isPermissionGranted( packageState: PackageState, userId: Int, permissionName: String, ): Boolean { val permissionFlags = with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } return PermissionFlags.isAppOpGranted(permissionFlags) } private fun MutateStateScope.grantRuntimePermission( private fun MutateStateScope.grantRuntimePermission( packageState: PackageState, packageState: PackageState, userId: Int, userId: Int, Loading Loading @@ -292,6 +410,47 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } } } /** * Revoke a runtime permission for a given user from a given package. * * @return true if the permission was revoked, false otherwise. */ private fun MutateStateScope.revokeRuntimePermission( packageState: PackageState, userId: Int, permissionName: String, ): Boolean { Slog.v( LOG_TAG, "Revoking runtime permission for package: ${packageState.packageName}, " + "permission: $permissionName, userId: $userId", ) val permission = newState.systemState.permissions[permissionName]!! if (packageState.getUserStateOrDefault(userId).isInstantApp && !permission.isInstant) { return false } val appId = packageState.appId var flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } if (flags.hasAnyBit(MASK_SYSTEM_OR_POLICY_FIXED)) { Slog.v( LOG_TAG, "Not allowed to revoke $permissionName to package ${packageState.packageName} " + "for user $userId", ) return false } val newFlags = flags andInv (PermissionFlags.RUNTIME_GRANTED or MASK_USER_SETTABLE or PermissionFlags.PREGRANT or PermissionFlags.ROLE) with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } return true } companion object { companion object { private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName Loading @@ -302,6 +461,17 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { PermissionFlags.POLICY_FIXED or PermissionFlags.POLICY_FIXED or PermissionFlags.SYSTEM_FIXED PermissionFlags.SYSTEM_FIXED private const val MASK_SYSTEM_OR_POLICY_FIXED = PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED private const val MASK_USER_SETTABLE = PermissionFlags.USER_SET or PermissionFlags.USER_FIXED or PermissionFlags.APP_OP_REVOKED or PermissionFlags.ONE_TIME or PermissionFlags.HIBERNATION or PermissionFlags.USER_SELECTED private val LEGACY_RESTRICTED_PERMISSIONS = private val LEGACY_RESTRICTED_PERMISSIONS = indexedSetOf( indexedSetOf( Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, Loading Loading
services/permission/java/com/android/server/permission/access/AccessPolicy.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -431,7 +431,7 @@ private constructor( companion object { companion object { private val LOG_TAG = AccessPolicy::class.java.simpleName private val LOG_TAG = AccessPolicy::class.java.simpleName internal const val VERSION_LATEST = 16 internal const val VERSION_LATEST = 17 private const val TAG_ACCESS = "access" private const val TAG_ACCESS = "access" private const val TAG_DEFAULT_PERMISSION_GRANT = "default-permission-grant" private const val TAG_DEFAULT_PERMISSION_GRANT = "default-permission-grant" Loading
services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt +172 −2 Original line number Original line Diff line number Diff line Loading @@ -17,8 +17,10 @@ package com.android.server.permission.access.permission package com.android.server.permission.access.permission import android.Manifest import android.Manifest import android.health.connect.HealthPermissions import android.os.Build import android.os.Build import android.util.Slog import android.util.Slog import com.android.server.permission.access.GetStateScope import com.android.server.permission.access.MutateStateScope import com.android.server.permission.access.MutateStateScope import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.util.andInv import com.android.server.permission.access.util.andInv Loading Loading @@ -64,7 +66,7 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { ", version: $version, user: $userId", ", version: $version, user: $userId", ) ) upgradeAuralVisualMediaPermissions(packageState, userId) upgradeAuralVisualMediaPermissions(packageState, userId) upgradeBodySensorPermissions(packageState, userId) upgradeBodySensorBackgroundPermissions(packageState, userId) } } // TODO Enable isAtLeastU check, when moving subsystem to mainline. // TODO Enable isAtLeastU check, when moving subsystem to mainline. if (version <= 14 /*&& SdkLevel.isAtLeastU()*/) { if (version <= 14 /*&& SdkLevel.isAtLeastU()*/) { Loading @@ -75,6 +77,16 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { ) ) upgradeUserSelectedVisualMediaPermission(packageState, userId) upgradeUserSelectedVisualMediaPermission(packageState, userId) } } // TODO Enable isAtLeastB check, when moving subsystem to mainline. if (version <= 16 /*&& SdkLevel.isAtLeastB()*/) { Slog.v( LOG_TAG, "Upgrading body sensor / read heart rate permissions for package: $packageName" + ", version: $version, user: $userId", ) upgradeBodySensorReadHeartRatePermissions(packageState, userId) } // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... } // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... } // Also increase LATEST_VERSION // Also increase LATEST_VERSION } } Loading Loading @@ -182,7 +194,7 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { } } } } private fun MutateStateScope.upgradeBodySensorPermissions( private fun MutateStateScope.upgradeBodySensorBackgroundPermissions( packageState: PackageState, packageState: PackageState, userId: Int, userId: Int, ) { ) { Loading Loading @@ -256,6 +268,112 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { } } } } /** * Upgrade permissions based on the body sensors and health permissions status. * * Starting in BAKLAVA, the BODY_SENSORS and BODY_SENSORS_BACKGROUND permissions are being * replaced by the READ_HEART_RATE and READ_HEALTH_DATA_IN_BACKGROUND permissions respectively. * To ensure that older apps can continue using BODY_SENSORS without breaking we need to keep * their permission state in sync with the new health permissions. * * The approach we take is to be as conservative as possible. This means if either permission is * not granted, then we want to ensure that both end up not granted to force the user to * re-grant with the expanded scope. */ private fun MutateStateScope.upgradeBodySensorReadHeartRatePermissions( packageState: PackageState, userId: Int, ) { val androidPackage = packageState.androidPackage!! if (androidPackage.targetSdkVersion >= Build.VERSION_CODES.BAKLAVA) { return } // First sync BODY_SENSORS and READ_HEART_RATE, if required. val isBodySensorsRequested = Manifest.permission.BODY_SENSORS in androidPackage.requestedPermissions val isReadHeartRateRequested = HealthPermissions.READ_HEART_RATE in androidPackage.requestedPermissions var isBodySensorsGranted = isPermissionGranted(packageState, userId, Manifest.permission.BODY_SENSORS) if (isBodySensorsRequested && isReadHeartRateRequested) { val isReadHeartRateGranted = isPermissionGranted(packageState, userId, HealthPermissions.READ_HEART_RATE) if (isBodySensorsGranted != isReadHeartRateGranted) { if (isBodySensorsGranted) { if ( revokeRuntimePermission( packageState, userId, Manifest.permission.BODY_SENSORS, ) ) { isBodySensorsGranted = false } } if (isReadHeartRateGranted) { revokeRuntimePermission(packageState, userId, HealthPermissions.READ_HEART_RATE) } } } // Then check to ensure we haven't put the background/foreground permissions out of sync. var isBodySensorsBackgroundGranted = isPermissionGranted(packageState, userId, Manifest.permission.BODY_SENSORS_BACKGROUND) // Background permission should not be granted without the foreground permission. if (!isBodySensorsGranted && isBodySensorsBackgroundGranted) { if ( revokeRuntimePermission( packageState, userId, Manifest.permission.BODY_SENSORS_BACKGROUND, ) ) { isBodySensorsBackgroundGranted = false } } // Finally sync BODY_SENSORS_BACKGROUND and READ_HEALTH_DATA_IN_BACKGROUND, if required. val isBodySensorsBackgroundRequested = Manifest.permission.BODY_SENSORS_BACKGROUND in androidPackage.requestedPermissions val isReadHealthDataInBackgroundRequested = HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND in androidPackage.requestedPermissions if (isBodySensorsBackgroundRequested && isReadHealthDataInBackgroundRequested) { val isReadHealthDataInBackgroundGranted = isPermissionGranted( packageState, userId, HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, ) if (isBodySensorsBackgroundGranted != isReadHealthDataInBackgroundGranted) { if (isBodySensorsBackgroundGranted) { revokeRuntimePermission( packageState, userId, Manifest.permission.BODY_SENSORS_BACKGROUND, ) } if (isReadHealthDataInBackgroundGranted) { revokeRuntimePermission( packageState, userId, HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, ) } } } } private fun GetStateScope.isPermissionGranted( packageState: PackageState, userId: Int, permissionName: String, ): Boolean { val permissionFlags = with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } return PermissionFlags.isAppOpGranted(permissionFlags) } private fun MutateStateScope.grantRuntimePermission( private fun MutateStateScope.grantRuntimePermission( packageState: PackageState, packageState: PackageState, userId: Int, userId: Int, Loading Loading @@ -292,6 +410,47 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } } } /** * Revoke a runtime permission for a given user from a given package. * * @return true if the permission was revoked, false otherwise. */ private fun MutateStateScope.revokeRuntimePermission( packageState: PackageState, userId: Int, permissionName: String, ): Boolean { Slog.v( LOG_TAG, "Revoking runtime permission for package: ${packageState.packageName}, " + "permission: $permissionName, userId: $userId", ) val permission = newState.systemState.permissions[permissionName]!! if (packageState.getUserStateOrDefault(userId).isInstantApp && !permission.isInstant) { return false } val appId = packageState.appId var flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } if (flags.hasAnyBit(MASK_SYSTEM_OR_POLICY_FIXED)) { Slog.v( LOG_TAG, "Not allowed to revoke $permissionName to package ${packageState.packageName} " + "for user $userId", ) return false } val newFlags = flags andInv (PermissionFlags.RUNTIME_GRANTED or MASK_USER_SETTABLE or PermissionFlags.PREGRANT or PermissionFlags.ROLE) with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } return true } companion object { companion object { private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName Loading @@ -302,6 +461,17 @@ class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { PermissionFlags.POLICY_FIXED or PermissionFlags.POLICY_FIXED or PermissionFlags.SYSTEM_FIXED PermissionFlags.SYSTEM_FIXED private const val MASK_SYSTEM_OR_POLICY_FIXED = PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED private const val MASK_USER_SETTABLE = PermissionFlags.USER_SET or PermissionFlags.USER_FIXED or PermissionFlags.APP_OP_REVOKED or PermissionFlags.ONE_TIME or PermissionFlags.HIBERNATION or PermissionFlags.USER_SELECTED private val LEGACY_RESTRICTED_PERMISSIONS = private val LEGACY_RESTRICTED_PERMISSIONS = indexedSetOf( indexedSetOf( Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, Loading