1 /* <lambda>null2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.permission.access.permission 18 19 import android.Manifest 20 import android.os.Build 21 import android.util.Slog 22 import com.android.server.permission.access.MutateStateScope 23 import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports 24 import com.android.server.permission.access.util.andInv 25 import com.android.server.permission.access.util.hasAnyBit 26 import com.android.server.permission.access.util.hasBits 27 import com.android.server.pm.pkg.PackageState 28 29 class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { 30 /** 31 * Upgrade the package permissions, if needed. 32 * 33 * @param version package version 34 * @see [com.android.server.permission.access.util.PackageVersionMigration.getVersion] 35 */ 36 fun MutateStateScope.upgradePackageState( 37 packageState: PackageState, 38 userId: Int, 39 version: Int 40 ) { 41 val packageName = packageState.packageName 42 if (version <= 3) { 43 Slog.v( 44 LOG_TAG, 45 "Allowlisting and upgrading background location permission for " + 46 "package: $packageName, version: $version, user:$userId" 47 ) 48 allowlistRestrictedPermissions(packageState, userId) 49 upgradeBackgroundLocationPermission(packageState, userId) 50 } 51 if (version <= 10) { 52 Slog.v( 53 LOG_TAG, 54 "Upgrading access media location permission for package: $packageName" + 55 ", version: $version, user: $userId" 56 ) 57 upgradeAccessMediaLocationPermission(packageState, userId) 58 } 59 // TODO Enable isAtLeastT check, when moving subsystem to mainline. 60 if (version <= 12 /*&& SdkLevel.isAtLeastT()*/) { 61 Slog.v( 62 LOG_TAG, 63 "Upgrading scoped media and body sensor permissions for package: $packageName" + 64 ", version: $version, user: $userId" 65 ) 66 upgradeAuralVisualMediaPermissions(packageState, userId) 67 upgradeBodySensorPermissions(packageState, userId) 68 } 69 // TODO Enable isAtLeastU check, when moving subsystem to mainline. 70 if (version <= 14 /*&& SdkLevel.isAtLeastU()*/) { 71 Slog.v( 72 LOG_TAG, 73 "Upgrading visual media permission for package: $packageName" + 74 ", version: $version, user: $userId" 75 ) 76 upgradeUserSelectedVisualMediaPermission(packageState, userId) 77 } 78 // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... } 79 // Also increase LATEST_VERSION 80 } 81 82 private fun MutateStateScope.allowlistRestrictedPermissions( 83 packageState: PackageState, 84 userId: Int 85 ) { 86 packageState.androidPackage!!.requestedPermissions.forEach { permissionName -> 87 if (permissionName in LEGACY_RESTRICTED_PERMISSIONS) { 88 with(policy) { 89 updatePermissionFlags( 90 packageState.appId, 91 userId, 92 permissionName, 93 PermissionFlags.UPGRADE_EXEMPT, 94 PermissionFlags.UPGRADE_EXEMPT 95 ) 96 } 97 } 98 } 99 } 100 101 private fun MutateStateScope.upgradeBackgroundLocationPermission( 102 packageState: PackageState, 103 userId: Int 104 ) { 105 if ( 106 Manifest.permission.ACCESS_BACKGROUND_LOCATION in 107 packageState.androidPackage!!.requestedPermissions 108 ) { 109 val appId = packageState.appId 110 val accessFineLocationFlags = 111 with(policy) { 112 getPermissionFlags(appId, userId, Manifest.permission.ACCESS_FINE_LOCATION) 113 } 114 val accessCoarseLocationFlags = 115 with(policy) { 116 getPermissionFlags(appId, userId, Manifest.permission.ACCESS_COARSE_LOCATION) 117 } 118 val isForegroundLocationGranted = 119 PermissionFlags.isAppOpGranted(accessFineLocationFlags) || 120 PermissionFlags.isAppOpGranted(accessCoarseLocationFlags) 121 if (isForegroundLocationGranted) { 122 grantRuntimePermission( 123 packageState, 124 userId, 125 Manifest.permission.ACCESS_BACKGROUND_LOCATION 126 ) 127 } 128 } 129 } 130 131 private fun MutateStateScope.upgradeAccessMediaLocationPermission( 132 packageState: PackageState, 133 userId: Int 134 ) { 135 if ( 136 Manifest.permission.ACCESS_MEDIA_LOCATION in 137 packageState.androidPackage!!.requestedPermissions 138 ) { 139 val flags = 140 with(policy) { 141 getPermissionFlags( 142 packageState.appId, 143 userId, 144 Manifest.permission.READ_EXTERNAL_STORAGE 145 ) 146 } 147 if (PermissionFlags.isAppOpGranted(flags)) { 148 grantRuntimePermission( 149 packageState, 150 userId, 151 Manifest.permission.ACCESS_MEDIA_LOCATION 152 ) 153 } 154 } 155 } 156 157 /** Upgrade permissions based on storage permissions grant */ 158 private fun MutateStateScope.upgradeAuralVisualMediaPermissions( 159 packageState: PackageState, 160 userId: Int 161 ) { 162 val androidPackage = packageState.androidPackage!! 163 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) { 164 return 165 } 166 val requestedPermissionNames = androidPackage.requestedPermissions 167 val isStorageUserGranted = 168 STORAGE_PERMISSIONS.anyIndexed { _, permissionName -> 169 if (permissionName !in requestedPermissionNames) { 170 return@anyIndexed false 171 } 172 val flags = 173 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } 174 PermissionFlags.isAppOpGranted(flags) && flags.hasBits(PermissionFlags.USER_SET) 175 } 176 if (isStorageUserGranted) { 177 AURAL_VISUAL_MEDIA_PERMISSIONS.forEachIndexed { _, permissionName -> 178 if (permissionName in requestedPermissionNames) { 179 grantRuntimePermission(packageState, userId, permissionName) 180 } 181 } 182 } 183 } 184 185 private fun MutateStateScope.upgradeBodySensorPermissions( 186 packageState: PackageState, 187 userId: Int 188 ) { 189 if ( 190 Manifest.permission.BODY_SENSORS_BACKGROUND !in 191 packageState.androidPackage!!.requestedPermissions 192 ) { 193 return 194 } 195 196 // Should have been granted when first getting exempt as if the perm was just split 197 val appId = packageState.appId 198 val backgroundBodySensorsFlags = 199 with(policy) { 200 getPermissionFlags(appId, userId, Manifest.permission.BODY_SENSORS_BACKGROUND) 201 } 202 if (backgroundBodySensorsFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)) { 203 return 204 } 205 206 // Add Upgrade Exemption - BODY_SENSORS_BACKGROUND is a restricted permission 207 with(policy) { 208 updatePermissionFlags( 209 appId, 210 userId, 211 Manifest.permission.BODY_SENSORS_BACKGROUND, 212 PermissionFlags.UPGRADE_EXEMPT, 213 PermissionFlags.UPGRADE_EXEMPT, 214 ) 215 } 216 217 val bodySensorsFlags = 218 with(policy) { getPermissionFlags(appId, userId, Manifest.permission.BODY_SENSORS) } 219 val isForegroundBodySensorsGranted = PermissionFlags.isAppOpGranted(bodySensorsFlags) 220 if (isForegroundBodySensorsGranted) { 221 grantRuntimePermission( 222 packageState, 223 userId, 224 Manifest.permission.BODY_SENSORS_BACKGROUND 225 ) 226 } 227 } 228 229 /** Upgrade permission based on the grant in [Manifest.permission_group.READ_MEDIA_VISUAL] */ 230 private fun MutateStateScope.upgradeUserSelectedVisualMediaPermission( 231 packageState: PackageState, 232 userId: Int 233 ) { 234 val androidPackage = packageState.androidPackage!! 235 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) { 236 return 237 } 238 val requestedPermissionNames = androidPackage.requestedPermissions 239 val isVisualMediaUserGranted = 240 VISUAL_MEDIA_PERMISSIONS.anyIndexed { _, permissionName -> 241 if (permissionName !in requestedPermissionNames) { 242 return@anyIndexed false 243 } 244 val flags = 245 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } 246 PermissionFlags.isAppOpGranted(flags) && flags.hasBits(PermissionFlags.USER_SET) 247 } 248 if (isVisualMediaUserGranted) { 249 if (Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED in requestedPermissionNames) { 250 grantRuntimePermission( 251 packageState, 252 userId, 253 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED 254 ) 255 } 256 } 257 } 258 259 private fun MutateStateScope.grantRuntimePermission( 260 packageState: PackageState, 261 userId: Int, 262 permissionName: String 263 ) { 264 Slog.v( 265 LOG_TAG, 266 "Granting runtime permission for package: ${packageState.packageName}, " + 267 "permission: $permissionName, userId: $userId" 268 ) 269 val permission = newState.systemState.permissions[permissionName]!! 270 if (packageState.getUserStateOrDefault(userId).isInstantApp && !permission.isInstant) { 271 return 272 } 273 274 val appId = packageState.appId 275 var flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 276 if (flags.hasAnyBit(MASK_ANY_FIXED)) { 277 Slog.v( 278 LOG_TAG, 279 "Not allowed to grant $permissionName to package ${packageState.packageName}" 280 ) 281 return 282 } 283 284 flags = flags or PermissionFlags.RUNTIME_GRANTED 285 flags = 286 flags andInv 287 (PermissionFlags.APP_OP_REVOKED or 288 PermissionFlags.IMPLICIT or 289 PermissionFlags.LEGACY_GRANTED or 290 PermissionFlags.HIBERNATION or 291 PermissionFlags.ONE_TIME) 292 with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } 293 } 294 295 companion object { 296 private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName 297 298 private const val MASK_ANY_FIXED = 299 PermissionFlags.USER_SET or 300 PermissionFlags.USER_FIXED or 301 PermissionFlags.POLICY_FIXED or 302 PermissionFlags.SYSTEM_FIXED 303 304 private val LEGACY_RESTRICTED_PERMISSIONS = 305 indexedSetOf( 306 Manifest.permission.ACCESS_BACKGROUND_LOCATION, 307 Manifest.permission.READ_EXTERNAL_STORAGE, 308 Manifest.permission.WRITE_EXTERNAL_STORAGE, 309 Manifest.permission.SEND_SMS, 310 Manifest.permission.RECEIVE_SMS, 311 Manifest.permission.RECEIVE_WAP_PUSH, 312 Manifest.permission.RECEIVE_MMS, 313 Manifest.permission.READ_CELL_BROADCASTS, 314 Manifest.permission.READ_CALL_LOG, 315 Manifest.permission.WRITE_CALL_LOG, 316 Manifest.permission.PROCESS_OUTGOING_CALLS 317 ) 318 319 private val STORAGE_PERMISSIONS = 320 indexedSetOf( 321 Manifest.permission.READ_EXTERNAL_STORAGE, 322 Manifest.permission.WRITE_EXTERNAL_STORAGE 323 ) 324 private val AURAL_VISUAL_MEDIA_PERMISSIONS = 325 indexedSetOf( 326 Manifest.permission.READ_MEDIA_AUDIO, 327 Manifest.permission.READ_MEDIA_IMAGES, 328 Manifest.permission.READ_MEDIA_VIDEO, 329 Manifest.permission.ACCESS_MEDIA_LOCATION, 330 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED 331 ) 332 // Visual media permissions in T 333 private val VISUAL_MEDIA_PERMISSIONS = 334 indexedSetOf( 335 Manifest.permission.READ_MEDIA_IMAGES, 336 Manifest.permission.READ_MEDIA_VIDEO, 337 Manifest.permission.ACCESS_MEDIA_LOCATION 338 ) 339 } 340 } 341