1 /* <lambda>null2 * Copyright (C) 2021 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.content.pm.PackageManager 21 import android.content.pm.PermissionGroupInfo 22 import android.content.pm.PermissionInfo 23 import android.content.pm.SigningDetails 24 import android.health.connect.HealthPermissions 25 import android.os.Build 26 import android.permission.flags.Flags 27 import android.util.Slog 28 import com.android.internal.os.RoSystemProperties 29 import com.android.internal.pm.permission.CompatibilityPermissionInfo 30 import com.android.modules.utils.BinaryXmlPullParser 31 import com.android.modules.utils.BinaryXmlSerializer 32 import com.android.server.permission.access.AccessState 33 import com.android.server.permission.access.GetStateScope 34 import com.android.server.permission.access.MutableAccessState 35 import com.android.server.permission.access.MutateStateScope 36 import com.android.server.permission.access.PermissionUri 37 import com.android.server.permission.access.SchemePolicy 38 import com.android.server.permission.access.UidUri 39 import com.android.server.permission.access.WriteMode 40 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports 41 import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports 42 import com.android.server.permission.access.util.andInv 43 import com.android.server.permission.access.util.hasAnyBit 44 import com.android.server.permission.access.util.hasBits 45 import com.android.server.permission.access.util.isInternal 46 import com.android.server.pm.KnownPackages 47 import com.android.server.pm.parsing.PackageInfoUtils 48 import com.android.server.pm.pkg.AndroidPackage 49 import com.android.server.pm.pkg.PackageState 50 import libcore.util.EmptyArray 51 52 class AppIdPermissionPolicy : SchemePolicy() { 53 private val persistence = AppIdPermissionPersistence() 54 55 private val migration = AppIdPermissionMigration() 56 57 private val upgrade = AppIdPermissionUpgrade(this) 58 59 @Volatile 60 private var onPermissionFlagsChangedListeners: 61 IndexedListSet<OnPermissionFlagsChangedListener> = 62 MutableIndexedListSet() 63 private val onPermissionFlagsChangedListenersLock = Any() 64 65 private val privilegedPermissionAllowlistViolations = MutableIndexedSet<String>() 66 67 /** Test-only switch to enforce signature permission allowlist even on debuggable builds. */ 68 @Volatile var isSignaturePermissionAllowlistForceEnforced = false 69 70 override val subjectScheme: String 71 get() = UidUri.SCHEME 72 73 override val objectScheme: String 74 get() = PermissionUri.SCHEME 75 76 override fun GetStateScope.onStateMutated() { 77 onPermissionFlagsChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } 78 } 79 80 override fun MutateStateScope.onUserAdded(userId: Int) { 81 newState.externalState.packageStates.forEach { (_, packageState) -> 82 if (packageState.isApex) { 83 return@forEach 84 } 85 evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null) 86 } 87 newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> 88 inheritImplicitPermissionStates(appId, userId) 89 } 90 } 91 92 override fun MutateStateScope.onAppIdRemoved(appId: Int) { 93 newState.userStates.forEachIndexed { userStateIndex, _, userState -> 94 if (appId in userState.appIdPermissionFlags) { 95 newState.mutateUserStateAt(userStateIndex).mutateAppIdPermissionFlags() -= appId 96 // Skip notifying the change listeners since the app ID no longer exists. 97 } 98 } 99 } 100 101 override fun MutateStateScope.onStorageVolumeMounted( 102 volumeUuid: String?, 103 packageNames: List<String>, 104 isSystemUpdated: Boolean, 105 ) { 106 val changedPermissionNames = MutableIndexedSet<String>() 107 packageNames.forEachIndexed { _, packageName -> 108 // The package may still be removed even if it was once notified as installed. 109 val packageState = 110 newState.externalState.packageStates[packageName] ?: return@forEachIndexed 111 adoptPermissions(packageState, changedPermissionNames) 112 addPermissionGroups(packageState) 113 addPermissions(packageState, changedPermissionNames) 114 trimPermissions(packageState.packageName, changedPermissionNames) 115 trimPermissionStates(packageState.appId) 116 } 117 changedPermissionNames.forEachIndexed { _, permissionName -> 118 evaluatePermissionStateForAllPackages(permissionName, null) 119 } 120 121 packageNames.forEachIndexed { _, packageName -> 122 val packageState = 123 newState.externalState.packageStates[packageName] ?: return@forEachIndexed 124 val installedPackageState = if (isSystemUpdated) packageState else null 125 evaluateAllPermissionStatesForPackage(packageState, installedPackageState) 126 } 127 packageNames.forEachIndexed { _, packageName -> 128 val packageState = 129 newState.externalState.packageStates[packageName] ?: return@forEachIndexed 130 newState.externalState.userIds.forEachIndexed { _, userId -> 131 inheritImplicitPermissionStates(packageState.appId, userId) 132 } 133 revokePermissionsOnPackageUpdate(packageState.appId) 134 } 135 } 136 137 override fun MutateStateScope.onPackageAdded(packageState: PackageState) { 138 val changedPermissionNames = MutableIndexedSet<String>() 139 adoptPermissions(packageState, changedPermissionNames) 140 addPermissionGroups(packageState) 141 addPermissions(packageState, changedPermissionNames) 142 trimPermissions(packageState.packageName, changedPermissionNames) 143 trimPermissionStates(packageState.appId) 144 changedPermissionNames.forEachIndexed { _, permissionName -> 145 evaluatePermissionStateForAllPackages(permissionName, null) 146 } 147 evaluateAllPermissionStatesForPackage(packageState, packageState) 148 newState.externalState.userIds.forEachIndexed { _, userId -> 149 inheritImplicitPermissionStates(packageState.appId, userId) 150 } 151 revokePermissionsOnPackageUpdate(packageState.appId) 152 } 153 154 override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) { 155 check(packageName !in newState.externalState.disabledSystemPackageStates) { 156 "Package $packageName reported as removed before disabled system package is enabled" 157 } 158 159 val changedPermissionNames = MutableIndexedSet<String>() 160 trimPermissions(packageName, changedPermissionNames) 161 if (appId in newState.externalState.appIdPackageNames) { 162 trimPermissionStates(appId) 163 } 164 changedPermissionNames.forEachIndexed { _, permissionName -> 165 evaluatePermissionStateForAllPackages(permissionName, null) 166 } 167 } 168 169 override fun MutateStateScope.onPackageInstalled(packageState: PackageState, userId: Int) { 170 // Clear UPGRADE_EXEMPT for all permissions requested by this package since there's 171 // an installer and the installer has made a decision. 172 clearRestrictedPermissionImplicitExemption(packageState, userId) 173 } 174 175 private fun MutateStateScope.clearRestrictedPermissionImplicitExemption( 176 packageState: PackageState, 177 userId: Int, 178 ) { 179 // System apps can always retain their UPGRADE_EXEMPT. 180 if (packageState.isSystem) { 181 return 182 } 183 val androidPackage = packageState.androidPackage ?: return 184 val appId = packageState.appId 185 androidPackage.requestedPermissions.forEach { permissionName -> 186 val permission = newState.systemState.permissions[permissionName] ?: return@forEach 187 if (!permission.isHardOrSoftRestricted) { 188 return@forEach 189 } 190 val isRequestedBySystemPackage = 191 anyPackageInAppId(appId) { 192 it.isSystem && permissionName in it.androidPackage!!.requestedPermissions 193 } 194 if (isRequestedBySystemPackage) { 195 return@forEach 196 } 197 updatePermissionExemptFlags( 198 appId, 199 userId, 200 permission, 201 PermissionFlags.UPGRADE_EXEMPT, 202 0, 203 ) 204 } 205 } 206 207 fun MutateStateScope.updatePermissionExemptFlags( 208 appId: Int, 209 userId: Int, 210 permission: Permission, 211 exemptFlagMask: Int, 212 exemptFlagValues: Int, 213 ) { 214 val permissionName = permission.name 215 val oldFlags = getPermissionFlags(appId, userId, permissionName) 216 var newFlags = (oldFlags andInv exemptFlagMask) or (exemptFlagValues and exemptFlagMask) 217 if (oldFlags == newFlags) { 218 return 219 } 220 val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT) 221 if (permission.isHardRestricted && !isExempt) { 222 newFlags = newFlags or PermissionFlags.RESTRICTION_REVOKED 223 // If the permission was policy fixed as granted but it is no longer on any of the 224 // allowlists we need to clear the policy fixed flag as allowlisting trumps policy i.e. 225 // policy cannot grant a non grantable permission. 226 if (PermissionFlags.isPermissionGranted(oldFlags)) { 227 newFlags = newFlags andInv PermissionFlags.POLICY_FIXED 228 } 229 } else { 230 newFlags = newFlags andInv PermissionFlags.RESTRICTION_REVOKED 231 } 232 val isSoftRestricted = 233 if (permission.isSoftRestricted && !isExempt) { 234 val targetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName) 235 !anyPackageInAppId(appId) { 236 permissionName in it.androidPackage!!.requestedPermissions && 237 isSoftRestrictedPermissionExemptForPackage( 238 it, 239 targetSdkVersion, 240 permissionName, 241 ) 242 } 243 } else { 244 false 245 } 246 newFlags = 247 if (isSoftRestricted) { 248 newFlags or PermissionFlags.SOFT_RESTRICTED 249 } else { 250 newFlags andInv PermissionFlags.SOFT_RESTRICTED 251 } 252 if (oldFlags == newFlags) { 253 return 254 } 255 setPermissionFlags(appId, userId, permissionName, newFlags) 256 } 257 258 override fun MutateStateScope.onPackageUninstalled( 259 packageName: String, 260 appId: Int, 261 userId: Int, 262 ) { 263 resetRuntimePermissions(packageName, userId) 264 } 265 266 fun MutateStateScope.resetRuntimePermissions(packageName: String, userId: Int) { 267 // It's okay to skip resetting permissions for packages that are removed, 268 // because their states will be trimmed in onPackageRemoved()/onAppIdRemoved() 269 val packageState = newState.externalState.packageStates[packageName] ?: return 270 val androidPackage = packageState.androidPackage ?: return 271 val appId = packageState.appId 272 androidPackage.requestedPermissions.forEach { permissionName -> 273 val permission = newState.systemState.permissions[permissionName] ?: return@forEach 274 if (!permission.isRuntime || permission.isRemoved) { 275 return@forEach 276 } 277 val isRequestedByOtherPackages = 278 anyPackageInAppId(appId) { 279 it.packageName != packageName && 280 permissionName in it.androidPackage!!.requestedPermissions 281 } 282 if (isRequestedByOtherPackages) { 283 return@forEach 284 } 285 val oldFlags = getPermissionFlags(appId, userId, permissionName) 286 if (oldFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)) { 287 return@forEach 288 } 289 var newFlags = oldFlags 290 val isSystemOrInstalled = 291 packageState.isSystem || packageState.getUserStateOrDefault(userId).isInstalled 292 newFlags = 293 if ( 294 isSystemOrInstalled && 295 (newFlags.hasBits(PermissionFlags.ROLE) || 296 newFlags.hasBits(PermissionFlags.PREGRANT)) 297 ) { 298 newFlags or PermissionFlags.RUNTIME_GRANTED 299 } else { 300 newFlags andInv 301 (PermissionFlags.RUNTIME_GRANTED or 302 PermissionFlags.ROLE or 303 PermissionFlags.PREGRANT) 304 } 305 newFlags = newFlags andInv USER_SETTABLE_MASK 306 if (newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)) { 307 newFlags = newFlags or PermissionFlags.IMPLICIT 308 } 309 setPermissionFlags(appId, userId, permissionName, newFlags) 310 } 311 } 312 313 private fun MutateStateScope.adoptPermissions( 314 packageState: PackageState, 315 changedPermissionNames: MutableIndexedSet<String>, 316 ) { 317 val `package` = packageState.androidPackage!! 318 `package`.adoptPermissions.forEachIndexed { _, originalPackageName -> 319 val packageName = `package`.packageName 320 if (!canAdoptPermissions(packageName, originalPackageName)) { 321 return@forEachIndexed 322 } 323 newState.systemState.permissions.forEachIndexed permissions@{ 324 permissionIndex, 325 permissionName, 326 oldPermission -> 327 if (oldPermission.packageName != originalPackageName) { 328 return@permissions 329 } 330 @Suppress("DEPRECATION") 331 val newPermissionInfo = 332 PermissionInfo().apply { 333 name = oldPermission.permissionInfo.name 334 this.packageName = packageName 335 protectionLevel = oldPermission.permissionInfo.protectionLevel 336 } 337 // Different from the old implementation, which removes the GIDs upon permission 338 // adoption, but adds them back on the next boot, we now just consistently keep the 339 // GIDs. 340 val newPermission = 341 oldPermission.copy( 342 permissionInfo = newPermissionInfo, 343 isReconciled = false, 344 appId = 0, 345 ) 346 newState 347 .mutateSystemState() 348 .mutatePermissions() 349 .putAt(permissionIndex, newPermission) 350 changedPermissionNames += permissionName 351 } 352 } 353 } 354 355 private fun MutateStateScope.canAdoptPermissions( 356 packageName: String, 357 originalPackageName: String, 358 ): Boolean { 359 val originalPackageState = 360 newState.externalState.packageStates[originalPackageName] ?: return false 361 if (!originalPackageState.isSystem) { 362 Slog.w( 363 LOG_TAG, 364 "Unable to adopt permissions from $originalPackageName to $packageName:" + 365 " original package not in system partition", 366 ) 367 return false 368 } 369 if (originalPackageState.androidPackage != null) { 370 Slog.w( 371 LOG_TAG, 372 "Unable to adopt permissions from $originalPackageName to $packageName:" + 373 " original package still exists", 374 ) 375 return false 376 } 377 return true 378 } 379 380 private fun MutateStateScope.addPermissionGroups(packageState: PackageState) { 381 // Different from the old implementation, which decides whether the app is an instant app by 382 // the install flags, now for consistent behavior we allow adding permission groups if the 383 // app is non-instant in at least one user. 384 val isInstantApp = packageState.userStates.allIndexed { _, _, it -> it.isInstantApp } 385 if (isInstantApp) { 386 Slog.w( 387 LOG_TAG, 388 "Ignoring permission groups declared in package" + 389 " ${packageState.packageName}: instant apps cannot declare permission groups", 390 ) 391 return 392 } 393 packageState.androidPackage!!.permissionGroups.forEachIndexed { _, parsedPermissionGroup -> 394 val newPermissionGroup = 395 PackageInfoUtils.generatePermissionGroupInfo( 396 parsedPermissionGroup, 397 PackageManager.GET_META_DATA.toLong(), 398 )!! 399 // TODO: Clear permission state on group take-over? 400 val permissionGroupName = newPermissionGroup.name 401 val oldPermissionGroup = newState.systemState.permissionGroups[permissionGroupName] 402 if ( 403 oldPermissionGroup != null && 404 newPermissionGroup.packageName != oldPermissionGroup.packageName 405 ) { 406 val newPackageName = newPermissionGroup.packageName 407 val oldPackageName = oldPermissionGroup.packageName 408 // Different from the old implementation, which defines permission group on 409 // a first-come-first-serve basis, and relies on system apps being scanned before 410 // non-system apps, we now allow system apps to override permission groups similar 411 // to permissions so that we no longer need to rely on the scan order. 412 if (!packageState.isSystem) { 413 Slog.w( 414 LOG_TAG, 415 "Ignoring permission group $permissionGroupName declared in" + 416 " package $newPackageName: already declared in another" + 417 " package $oldPackageName", 418 ) 419 return@forEachIndexed 420 } 421 if (newState.externalState.packageStates[oldPackageName]?.isSystem == true) { 422 Slog.w( 423 LOG_TAG, 424 "Ignoring permission group $permissionGroupName declared in" + 425 " system package $newPackageName: already declared in another" + 426 " system package $oldPackageName", 427 ) 428 return@forEachIndexed 429 } 430 Slog.w( 431 LOG_TAG, 432 "Overriding permission group $permissionGroupName with" + 433 " new declaration in system package $newPackageName: originally" + 434 " declared in another package $oldPackageName", 435 ) 436 } 437 newState.mutateSystemState().mutatePermissionGroups()[permissionGroupName] = 438 newPermissionGroup 439 } 440 } 441 442 private fun MutateStateScope.addPermissions( 443 packageState: PackageState, 444 changedPermissionNames: MutableIndexedSet<String>, 445 ) { 446 val androidPackage = packageState.androidPackage!! 447 // This may not be the same package as the old permission because the old permission owner 448 // can be different, hence using this somewhat strange name to prevent misuse. 449 val oldNewPackage = 450 oldState.externalState.packageStates[packageState.packageName]?.androidPackage 451 val isPackageSigningChanged = 452 oldNewPackage != null && androidPackage.signingDetails != oldNewPackage.signingDetails 453 androidPackage.permissions.forEachIndexed { _, parsedPermission -> 454 val newPermissionInfo = 455 PackageInfoUtils.generatePermissionInfo( 456 parsedPermission, 457 PackageManager.GET_META_DATA.toLong(), 458 )!! 459 val permissionName = newPermissionInfo.name 460 val oldPermission = 461 if (parsedPermission.isTree) { 462 newState.systemState.permissionTrees[permissionName] 463 } else { 464 newState.systemState.permissions[permissionName] 465 } 466 467 // Different from the old implementation, which may add an (incomplete) signature 468 // permission inside another package's permission tree, we now consistently ignore such 469 // permissions. 470 val permissionTree = findPermissionTree(permissionName) 471 val newPackageName = newPermissionInfo.packageName 472 if (permissionTree != null && newPackageName != permissionTree.packageName) { 473 Slog.w( 474 LOG_TAG, 475 "Ignoring permission $permissionName declared in package" + 476 " $newPackageName: base permission tree ${permissionTree.name} is" + 477 " declared in another package ${permissionTree.packageName}", 478 ) 479 return@forEachIndexed 480 } 481 482 if (oldPermission != null) { 483 if (newPackageName != oldPermission.packageName) { 484 val oldPackageName = oldPermission.packageName 485 // Only allow system apps to redefine non-system permissions. 486 if (!packageState.isSystem) { 487 Slog.w( 488 LOG_TAG, 489 "Ignoring permission $permissionName declared in package" + 490 " $newPackageName: already declared in another package" + 491 " $oldPackageName", 492 ) 493 return@forEachIndexed 494 } 495 if (newState.externalState.packageStates[oldPackageName]?.isSystem == true) { 496 Slog.w( 497 LOG_TAG, 498 "Ignoring permission $permissionName declared in system package" + 499 " $newPackageName: already declared in another system package" + 500 " $oldPackageName", 501 ) 502 return@forEachIndexed 503 } 504 Slog.w( 505 LOG_TAG, 506 "Overriding permission $permissionName with new declaration in" + 507 " system package $newPackageName: originally declared in another" + 508 " package $oldPackageName", 509 ) 510 // Remove permission state on owner change. 511 newState.externalState.userIds.forEachIndexed { _, userId -> 512 newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> 513 setPermissionFlags(appId, userId, permissionName, 0) 514 } 515 } 516 } else if (oldPermission.isReconciled) { 517 val isPermissionGroupChanged = 518 newPermissionInfo.isRuntime && 519 newPermissionInfo.group != null && 520 newPermissionInfo.group != oldPermission.groupName 521 val isPermissionProtectionChanged = 522 (newPermissionInfo.isRuntime && !oldPermission.isRuntime) || 523 (newPermissionInfo.isInternal && !oldPermission.isInternal) 524 if (isPermissionGroupChanged || isPermissionProtectionChanged) { 525 newState.externalState.userIds.forEachIndexed { _, userId -> 526 newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> 527 if (isPermissionGroupChanged) { 528 // We might auto-grant permissions if any permission of 529 // the group is already granted. Hence if the group of 530 // a granted permission changes we need to revoke it to 531 // avoid having permissions of the new group auto-granted. 532 Slog.w( 533 LOG_TAG, 534 "Revoking runtime permission $permissionName for" + 535 " appId $appId and userId $userId as the permission" + 536 " group changed from ${oldPermission.groupName}" + 537 " to ${newPermissionInfo.group}", 538 ) 539 } 540 if (isPermissionProtectionChanged) { 541 Slog.w( 542 LOG_TAG, 543 "Revoking permission $permissionName for" + 544 " appId $appId and userId $userId as the permission" + 545 " protection changed.", 546 ) 547 } 548 setPermissionFlags(appId, userId, permissionName, 0) 549 } 550 } 551 } 552 } 553 } 554 555 var gids = EmptyArray.INT 556 var areGidsPerUser = false 557 if (!parsedPermission.isTree && packageState.isSystem) { 558 newState.externalState.configPermissions[permissionName]?.let { 559 // PermissionEntry.gids may return null when parsing legacy config trying 560 // to work around an issue about upgrading from L platfrm. We can just 561 // ignore such entries now. 562 if (it.gids != null) { 563 gids = it.gids 564 areGidsPerUser = it.perUser 565 } 566 } 567 } 568 val newPermission = 569 Permission( 570 newPermissionInfo, 571 true, 572 Permission.TYPE_MANIFEST, 573 packageState.appId, 574 gids, 575 areGidsPerUser, 576 ) 577 578 if (parsedPermission.isTree) { 579 newState.mutateSystemState().mutatePermissionTrees()[permissionName] = newPermission 580 } else { 581 newState.mutateSystemState().mutatePermissions()[permissionName] = newPermission 582 val isPermissionChanged = 583 oldPermission == null || 584 newPackageName != oldPermission.packageName || 585 newPermission.protectionLevel != oldPermission.protectionLevel || 586 (oldPermission.isReconciled && 587 ((newPermission.isSignature && isPackageSigningChanged) || 588 (newPermission.isKnownSigner && 589 newPermission.knownCerts != oldPermission.knownCerts) || 590 (newPermission.isRuntime && 591 newPermission.groupName != null && 592 newPermission.groupName != oldPermission.groupName))) 593 if (isPermissionChanged) { 594 changedPermissionNames += permissionName 595 } 596 } 597 } 598 } 599 600 private fun MutateStateScope.trimPermissions( 601 packageName: String, 602 changedPermissionNames: MutableIndexedSet<String>, 603 ) { 604 val packageState = newState.externalState.packageStates[packageName] 605 val androidPackage = packageState?.androidPackage 606 if (packageState != null && androidPackage == null) { 607 return 608 } 609 val disabledSystemPackage = 610 newState.externalState.disabledSystemPackageStates[packageName]?.androidPackage 611 // Unlike in the previous implementation, we now also retain permission trees defined by 612 // disabled system packages for consistency with permissions. 613 newState.systemState.permissionTrees.forEachReversedIndexed { 614 permissionTreeIndex, 615 permissionTreeName, 616 permissionTree -> 617 if ( 618 permissionTree.packageName == packageName && 619 (packageState == null || 620 androidPackage!!.permissions.noneIndexed { _, it -> 621 it.isTree && it.name == permissionTreeName 622 }) && 623 (disabledSystemPackage?.permissions?.anyIndexed { _, it -> 624 it.isTree && it.name == permissionTreeName 625 } != true) 626 ) { 627 newState.mutateSystemState().mutatePermissionTrees().removeAt(permissionTreeIndex) 628 } 629 } 630 631 newState.systemState.permissions.forEachReversedIndexed { 632 permissionIndex, 633 permissionName, 634 permission -> 635 val updatedPermission = updatePermissionIfDynamic(permission) 636 newState 637 .mutateSystemState() 638 .mutatePermissions() 639 .putAt(permissionIndex, updatedPermission) 640 if ( 641 updatedPermission.packageName == packageName && 642 (packageState == null || 643 androidPackage!!.permissions.noneIndexed { _, it -> 644 !it.isTree && it.name == permissionName 645 }) && 646 (disabledSystemPackage?.permissions?.anyIndexed { _, it -> 647 !it.isTree && it.name == permissionName 648 } != true) 649 ) { 650 // Different from the old implementation where we keep the permission state if the 651 // permission is declared by a disabled system package (ag/15189282), we now 652 // shouldn't be notified when the updated system package is removed but the disabled 653 // system package isn't re-enabled yet, so we don't need to maintain that brittle 654 // special case either. 655 newState.externalState.userIds.forEachIndexed { _, userId -> 656 newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> 657 setPermissionFlags(appId, userId, permissionName, 0) 658 } 659 } 660 newState.mutateSystemState().mutatePermissions().removeAt(permissionIndex) 661 changedPermissionNames += permissionName 662 } 663 } 664 } 665 666 private fun MutateStateScope.updatePermissionIfDynamic(permission: Permission): Permission { 667 if (!permission.isDynamic) { 668 return permission 669 } 670 val permissionTree = findPermissionTree(permission.name) ?: return permission 671 @Suppress("DEPRECATION") 672 return permission.copy( 673 permissionInfo = 674 PermissionInfo(permission.permissionInfo).apply { 675 packageName = permissionTree.packageName 676 }, 677 appId = permissionTree.appId, 678 isReconciled = true, 679 ) 680 } 681 682 private fun MutateStateScope.trimPermissionStates(appId: Int) { 683 val requestedPermissions = MutableIndexedSet<String>() 684 forEachPackageInAppId(appId) { 685 // Note that we still trim the permission states requested by disabled system packages. 686 // Because in the previous implementation: 687 // despite revokeSharedUserPermissionsForLeavingPackageInternal() retains permissions 688 // requested by disabled system packages, revokeUnusedSharedUserPermissionsLocked(), 689 // which is call upon app update installation, didn't do such preservation. 690 // Hence, permissions only requested by disabled system packages were still trimmed in 691 // the previous implementation. 692 requestedPermissions += it.androidPackage!!.requestedPermissions 693 } 694 newState.userStates.forEachIndexed { _, userId, userState -> 695 userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ -> 696 if (permissionName !in requestedPermissions) { 697 setPermissionFlags(appId, userId, permissionName, 0) 698 } 699 } 700 } 701 } 702 703 private fun MutateStateScope.revokePermissionsOnPackageUpdate(appId: Int) { 704 revokeStorageAndMediaPermissionsOnPackageUpdate(appId) 705 revokeHeartRatePermissionsOnPackageUpdate(appId) 706 } 707 708 private fun MutateStateScope.revokeStorageAndMediaPermissionsOnPackageUpdate(appId: Int) { 709 val hasOldPackage = 710 appId in oldState.externalState.appIdPackageNames && 711 anyPackageInAppId(appId, oldState) { true } 712 if (!hasOldPackage) { 713 // Don't revoke anything if this isn't a package update, i.e. if information about the 714 // old package isn't available. Notably, this also means skipping packages changed via 715 // OTA, but the revocation here is also mostly for normal apps and there's no way to get 716 // information about the package before OTA anyway. 717 return 718 } 719 720 // If the app is updated, and has scoped storage permissions, then it is possible that the 721 // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions. 722 val oldTargetSdkVersion = getAppIdTargetSdkVersion(appId, null, oldState) 723 val newTargetSdkVersion = getAppIdTargetSdkVersion(appId, null, newState) 724 @Suppress("ConvertTwoComparisonsToRangeCheck") 725 val isTargetSdkVersionDowngraded = 726 oldTargetSdkVersion >= Build.VERSION_CODES.Q && 727 newTargetSdkVersion < Build.VERSION_CODES.Q 728 @Suppress("ConvertTwoComparisonsToRangeCheck") 729 val isTargetSdkVersionUpgraded = 730 oldTargetSdkVersion < Build.VERSION_CODES.Q && 731 newTargetSdkVersion >= Build.VERSION_CODES.Q 732 val oldIsRequestLegacyExternalStorage = 733 anyPackageInAppId(appId, oldState) { 734 it.androidPackage!!.isRequestLegacyExternalStorage 735 } 736 val newIsRequestLegacyExternalStorage = 737 anyPackageInAppId(appId, newState) { 738 it.androidPackage!!.isRequestLegacyExternalStorage 739 } 740 val isNewlyRequestingLegacyExternalStorage = 741 !isTargetSdkVersionUpgraded && 742 !oldIsRequestLegacyExternalStorage && 743 newIsRequestLegacyExternalStorage 744 val shouldRevokeStorageAndMediaPermissions = 745 isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded 746 if (shouldRevokeStorageAndMediaPermissions) { 747 newState.userStates.forEachIndexed { _, userId, userState -> 748 userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { 749 _, 750 permissionName, 751 oldFlags -> 752 // Do not revoke the permission during an upgrade if it's POLICY_FIXED or 753 // SYSTEM_FIXED. Otherwise the user cannot grant back the permission. 754 if ( 755 permissionName in STORAGE_AND_MEDIA_PERMISSIONS && 756 oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED) 757 ) { 758 revokeRuntimePermission(appId, userId, permissionName) 759 } 760 } 761 } 762 } 763 } 764 765 /** 766 * If the app is updated, the legacy BODY_SENSOR and READ_HEART_RATE permissions may go out of 767 * sync (for example, when the app eventually requests the implicit new permission). If this 768 * occurs, revoke both permissions to force a re-prompt. 769 */ 770 private fun MutateStateScope.revokeHeartRatePermissionsOnPackageUpdate(appId: Int) { 771 val targetSdkVersion = getAppIdTargetSdkVersion(appId, null) 772 // Apps targeting BAKLAVA and above shouldn't be using BODY_SENSORS. 773 if (targetSdkVersion >= Build.VERSION_CODES.BAKLAVA) { 774 return 775 } 776 777 val isBodySensorsRequested = 778 anyPackageInAppId(appId, newState) { 779 Manifest.permission.BODY_SENSORS in it.androidPackage!!.requestedPermissions 780 } 781 val isReadHeartRateRequested = 782 anyPackageInAppId(appId, newState) { 783 HealthPermissions.READ_HEART_RATE in it.androidPackage!!.requestedPermissions 784 } 785 val isBodySensorsBackgroundRequested = 786 anyPackageInAppId(appId, newState) { 787 Manifest.permission.BODY_SENSORS_BACKGROUND in 788 it.androidPackage!!.requestedPermissions 789 } 790 val isReadHealthDataInBackgroundRequested = 791 anyPackageInAppId(appId, newState) { 792 HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND in 793 it.androidPackage!!.requestedPermissions 794 } 795 796 // Walk the list of user IDs and revoke states as needed. 797 newState.userStates.forEachIndexed { _, userId, _ -> 798 // First sync BODY_SENSORS and READ_HEART_RATE, if required. 799 var isBodySensorsGranted = 800 isRuntimePermissionGranted(appId, userId, Manifest.permission.BODY_SENSORS) 801 if (isBodySensorsRequested && isReadHeartRateRequested) { 802 val isReadHeartRateGranted = 803 isRuntimePermissionGranted(appId, userId, HealthPermissions.READ_HEART_RATE) 804 if (isBodySensorsGranted != isReadHeartRateGranted) { 805 if (isBodySensorsGranted) { 806 if ( 807 revokeRuntimePermission(appId, userId, Manifest.permission.BODY_SENSORS) 808 ) { 809 isBodySensorsGranted = false 810 } 811 } 812 if (isReadHeartRateGranted) { 813 revokeRuntimePermission(appId, userId, HealthPermissions.READ_HEART_RATE) 814 } 815 } 816 } 817 818 // Then check to ensure we haven't put the background/foreground permissions out of 819 // sync. 820 var isBodySensorsBackgroundGranted = 821 isRuntimePermissionGranted( 822 appId, 823 userId, 824 Manifest.permission.BODY_SENSORS_BACKGROUND, 825 ) 826 if (isBodySensorsBackgroundGranted && !isBodySensorsGranted) { 827 if ( 828 revokeRuntimePermission( 829 appId, 830 userId, 831 Manifest.permission.BODY_SENSORS_BACKGROUND, 832 ) 833 ) { 834 isBodySensorsBackgroundGranted = false 835 } 836 } 837 838 // Finally sync BODY_SENSORS_BACKGROUND and READ_HEALTH_DATA_IN_BACKGROUND, if required. 839 if (isBodySensorsBackgroundRequested && isReadHealthDataInBackgroundRequested) { 840 val isReadHealthDataInBackgroundGranted = 841 isRuntimePermissionGranted( 842 appId, 843 userId, 844 HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, 845 ) 846 if (isBodySensorsBackgroundGranted != isReadHealthDataInBackgroundGranted) { 847 if (isBodySensorsBackgroundGranted) { 848 revokeRuntimePermission( 849 appId, 850 userId, 851 Manifest.permission.BODY_SENSORS_BACKGROUND, 852 ) 853 } 854 if (isReadHealthDataInBackgroundGranted) { 855 revokeRuntimePermission( 856 appId, 857 userId, 858 HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, 859 ) 860 } 861 } 862 } 863 } 864 } 865 866 private fun GetStateScope.isRuntimePermissionGranted( 867 appId: Int, 868 userId: Int, 869 permissionName: String, 870 ): Boolean { 871 val flags = getPermissionFlags(appId, userId, permissionName) 872 return PermissionFlags.isAppOpGranted(flags) 873 } 874 875 fun MutateStateScope.revokeRuntimePermission( 876 appId: Int, 877 userId: Int, 878 permissionName: String, 879 ): Boolean { 880 Slog.v( 881 LOG_TAG, 882 "Revoking runtime permission for appId: $appId, " + 883 "permission: $permissionName, userId: $userId", 884 ) 885 var flags = getPermissionFlags(appId, userId, permissionName) 886 if (flags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)) { 887 Slog.v( 888 LOG_TAG, 889 "Not allowed to revoke $permissionName for appId: $appId, userId: $userId", 890 ) 891 return false 892 } 893 894 flags = 895 flags andInv 896 (PermissionFlags.RUNTIME_GRANTED or 897 USER_SETTABLE_MASK or 898 PermissionFlags.PREGRANT or 899 PermissionFlags.ROLE) 900 setPermissionFlags(appId, userId, permissionName, flags) 901 return true 902 } 903 904 private fun MutateStateScope.evaluatePermissionStateForAllPackages( 905 permissionName: String, 906 installedPackageState: PackageState?, 907 ) { 908 val externalState = newState.externalState 909 externalState.userIds.forEachIndexed { _, userId -> 910 externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> 911 val isPermissionRequested = 912 anyPackageInAppId(appId) { 913 permissionName in it.androidPackage!!.requestedPermissions 914 } 915 if (isPermissionRequested) { 916 evaluatePermissionState(appId, userId, permissionName, installedPackageState) 917 } 918 } 919 } 920 } 921 922 private fun MutateStateScope.evaluateAllPermissionStatesForPackage( 923 packageState: PackageState, 924 installedPackageState: PackageState?, 925 ) { 926 newState.externalState.userIds.forEachIndexed { _, userId -> 927 evaluateAllPermissionStatesForPackageAndUser( 928 packageState, 929 userId, 930 installedPackageState, 931 ) 932 } 933 } 934 935 private fun MutateStateScope.evaluateAllPermissionStatesForPackageAndUser( 936 packageState: PackageState, 937 userId: Int, 938 installedPackageState: PackageState?, 939 ) { 940 packageState.androidPackage?.requestedPermissions?.forEach { permissionName -> 941 evaluatePermissionState( 942 packageState.appId, 943 userId, 944 permissionName, 945 installedPackageState, 946 ) 947 } 948 } 949 950 private fun MutateStateScope.evaluatePermissionState( 951 appId: Int, 952 userId: Int, 953 permissionName: String, 954 installedPackageState: PackageState?, 955 ) { 956 val packageNames = newState.externalState.appIdPackageNames[appId]!! 957 // Repeatedly checking whether a permission is requested can actually be costly, so we cache 958 // the result for this method which is frequently called during boot, instead of calling 959 // anyPackageInAppId() and checking requested permissions multiple times. 960 val requestingPackageStates = MutableIndexedList<PackageState>() 961 var hasMissingPackage = false 962 packageNames.forEachIndexed { _, packageName -> 963 val packageState = newState.externalState.packageStates[packageName]!! 964 val androidPackage = packageState.androidPackage 965 if (androidPackage != null) { 966 if (permissionName in androidPackage.requestedPermissions) { 967 requestingPackageStates += packageState 968 } 969 } else { 970 hasMissingPackage = true 971 } 972 } 973 if (packageNames.size == 1 && hasMissingPackage) { 974 // For non-shared-user packages with missing androidPackage, skip evaluation. 975 return 976 } 977 val permission = newState.systemState.permissions[permissionName] 978 val oldFlags = getPermissionFlags(appId, userId, permissionName) 979 if (permission == null) { 980 if (oldFlags == 0) { 981 // If the permission definition is missing and we don't have any permission states 982 // for this permission, add the INSTALL_REVOKED flag to ensure that we don't 983 // automatically grant the permission when it's defined 984 setPermissionFlags(appId, userId, permissionName, PermissionFlags.INSTALL_REVOKED) 985 } 986 return 987 } 988 if (permission.isNormal) { 989 val wasGranted = oldFlags.hasBits(PermissionFlags.INSTALL_GRANTED) 990 if (!wasGranted) { 991 val wasRevoked = oldFlags.hasBits(PermissionFlags.INSTALL_REVOKED) 992 val isRequestedByInstalledPackage = 993 installedPackageState != null && 994 permissionName in 995 installedPackageState.androidPackage!!.requestedPermissions 996 val isRequestedBySystemPackage = 997 requestingPackageStates.anyIndexed { _, it -> it.isSystem } 998 val isCompatibilityPermission = 999 requestingPackageStates.anyIndexed { _, it -> 1000 isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName) 1001 } 1002 // If this is an existing, non-system package, 1003 // then we can't add any new permissions to it. 1004 // Except if this is a permission that was added to the platform 1005 var newFlags = 1006 if ( 1007 !wasRevoked || 1008 isRequestedByInstalledPackage || 1009 isRequestedBySystemPackage || 1010 isCompatibilityPermission 1011 ) { 1012 PermissionFlags.INSTALL_GRANTED 1013 } else { 1014 PermissionFlags.INSTALL_REVOKED 1015 } 1016 if (permission.isAppOp) { 1017 newFlags = 1018 newFlags or 1019 (oldFlags and (PermissionFlags.ROLE or PermissionFlags.USER_SET)) 1020 } 1021 setPermissionFlags(appId, userId, permissionName, newFlags) 1022 } 1023 } else if (permission.isSignature || permission.isInternal) { 1024 val wasProtectionGranted = oldFlags.hasBits(PermissionFlags.PROTECTION_GRANTED) 1025 var newFlags = 1026 if (hasMissingPackage && wasProtectionGranted) { 1027 // Keep the non-runtime permission grants for shared UID with missing 1028 // androidPackage 1029 PermissionFlags.PROTECTION_GRANTED 1030 } else { 1031 val mayGrantByPrivileged = 1032 !permission.isPrivileged || 1033 requestingPackageStates.anyIndexed { _, it -> 1034 checkPrivilegedPermissionAllowlistIfNeeded(it, permission) 1035 } 1036 val shouldGrantBySignature = 1037 permission.isSignature && 1038 requestingPackageStates.anyIndexed { _, it -> 1039 shouldGrantPermissionBySignature(it, permission) 1040 } 1041 val shouldGrantByProtectionFlags = 1042 requestingPackageStates.anyIndexed { _, it -> 1043 shouldGrantPermissionByProtectionFlags(it, permission) 1044 } 1045 if ( 1046 mayGrantByPrivileged && 1047 (shouldGrantBySignature || shouldGrantByProtectionFlags) 1048 ) { 1049 PermissionFlags.PROTECTION_GRANTED 1050 } else { 1051 0 1052 } 1053 } 1054 if (permission.isAppOp) { 1055 newFlags = 1056 newFlags or (oldFlags and (PermissionFlags.ROLE or PermissionFlags.USER_SET)) 1057 } 1058 // Different from the old implementation, which seemingly allows granting an 1059 // unallowlisted privileged permission via development or role but revokes it upon next 1060 // reconciliation, we now properly allows that because the privileged protection flag 1061 // should only affect the other static flags, but not dynamic flags like development or 1062 // role. This may be useful in the case of an updated system app. 1063 if (permission.isDevelopment) { 1064 newFlags = newFlags or (oldFlags and PermissionFlags.RUNTIME_GRANTED) 1065 } 1066 if (permission.isRole) { 1067 newFlags = 1068 newFlags or 1069 (oldFlags and (PermissionFlags.ROLE or PermissionFlags.RUNTIME_GRANTED)) 1070 } 1071 setPermissionFlags(appId, userId, permissionName, newFlags) 1072 } else if (permission.isRuntime) { 1073 var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME 1074 val wasRevoked = newFlags != 0 && !PermissionFlags.isPermissionGranted(newFlags) 1075 val targetSdkVersion = 1076 requestingPackageStates.reduceIndexed(Build.VERSION_CODES.CUR_DEVELOPMENT) { 1077 targetSdkVersion, 1078 _, 1079 packageState -> 1080 targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) 1081 } 1082 if (targetSdkVersion < Build.VERSION_CODES.M) { 1083 if (permission.isRuntimeOnly) { 1084 // Different from the old implementation, which simply skips a runtime-only 1085 // permission, we now only allow holding on to the restriction related flags, 1086 // since such flags may only be set one-time in some cases, and disallow all 1087 // other flags thus keeping it revoked. 1088 newFlags = newFlags and PermissionFlags.MASK_EXEMPT 1089 } else { 1090 newFlags = newFlags or PermissionFlags.LEGACY_GRANTED 1091 if (wasRevoked) { 1092 newFlags = newFlags or PermissionFlags.APP_OP_REVOKED 1093 } 1094 // Explicitly check against the old state to determine if this permission is 1095 // new. 1096 val isNewPermission = 1097 getOldStatePermissionFlags(appId, userId, permissionName) == 0 1098 if (isNewPermission) { 1099 newFlags = newFlags or PermissionFlags.IMPLICIT 1100 } 1101 } 1102 } else { 1103 val wasGrantedByLegacy = newFlags.hasBits(PermissionFlags.LEGACY_GRANTED) 1104 val hasImplicitFlag = newFlags.hasBits(PermissionFlags.IMPLICIT) 1105 if (wasGrantedByLegacy) { 1106 newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED 1107 if (!hasImplicitFlag) { 1108 newFlags = newFlags or PermissionFlags.RUNTIME_GRANTED 1109 } 1110 } 1111 val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED) 1112 val isLeanbackNotificationsPermission = 1113 newState.externalState.isLeanback && permissionName in NOTIFICATIONS_PERMISSIONS 1114 val isImplicitPermission = 1115 requestingPackageStates.anyIndexed { _, it -> 1116 permissionName in it.androidPackage!!.implicitPermissions 1117 } 1118 val sourcePermissions = 1119 newState.externalState.implicitToSourcePermissions[permissionName] 1120 val isAnySourcePermissionNonRuntime = 1121 sourcePermissions?.anyIndexed { _, sourcePermissionName -> 1122 val sourcePermission = 1123 newState.systemState.permissions[sourcePermissionName] 1124 checkNotNull(sourcePermission) { 1125 "Unknown source permission $sourcePermissionName in split permissions" 1126 } 1127 !sourcePermission.isRuntime 1128 } ?: false 1129 val shouldGrantByImplicit = 1130 isLeanbackNotificationsPermission || 1131 (isImplicitPermission && isAnySourcePermissionNonRuntime) 1132 if (shouldGrantByImplicit) { 1133 newFlags = newFlags or PermissionFlags.IMPLICIT_GRANTED 1134 if (wasRevoked) { 1135 newFlags = newFlags or PermissionFlags.APP_OP_REVOKED 1136 } 1137 } else { 1138 newFlags = newFlags andInv PermissionFlags.IMPLICIT_GRANTED 1139 if ( 1140 (wasGrantedByLegacy || wasGrantedByImplicit) && 1141 newFlags.hasBits(PermissionFlags.APP_OP_REVOKED) 1142 ) { 1143 // The permission was granted from a compatibility grant or an implicit 1144 // grant, however this flag might still be set if the user denied this 1145 // permission in the settings. Hence upon app upgrade and when this 1146 // permission is no longer LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke 1147 // the permission, we want to remove this flag so that the app can request 1148 // the permission again. 1149 newFlags = 1150 newFlags andInv 1151 (PermissionFlags.RUNTIME_GRANTED or PermissionFlags.APP_OP_REVOKED) 1152 } 1153 } 1154 if (!isImplicitPermission && hasImplicitFlag) { 1155 newFlags = newFlags andInv PermissionFlags.IMPLICIT 1156 var shouldRetainAsNearbyDevices = false 1157 if (permissionName in NEARBY_DEVICES_PERMISSIONS) { 1158 val accessBackgroundLocationFlags = 1159 getPermissionFlags( 1160 appId, 1161 userId, 1162 Manifest.permission.ACCESS_BACKGROUND_LOCATION, 1163 ) 1164 shouldRetainAsNearbyDevices = 1165 PermissionFlags.isAppOpGranted(accessBackgroundLocationFlags) && 1166 !accessBackgroundLocationFlags.hasBits(PermissionFlags.IMPLICIT) 1167 } 1168 val shouldRetainByMask = newFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK) 1169 if (shouldRetainAsNearbyDevices || shouldRetainByMask) { 1170 if (wasGrantedByImplicit) { 1171 newFlags = newFlags or PermissionFlags.RUNTIME_GRANTED 1172 } 1173 } else { 1174 newFlags = 1175 newFlags andInv 1176 (PermissionFlags.RUNTIME_GRANTED or 1177 PermissionFlags.USER_SET or 1178 PermissionFlags.USER_FIXED) 1179 } 1180 } 1181 } 1182 1183 val wasExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT) 1184 val wasRestricted = newFlags.hasAnyBit(PermissionFlags.MASK_RESTRICTED) 1185 val isExempt = 1186 if (permission.isHardOrSoftRestricted && !wasExempt && !wasRestricted) { 1187 // All restricted permissions start as exempt. If there's an installer for the 1188 // package, we will drop this UPGRADE_EXEMPT flag when we receive the 1189 // onPackageInstalled() callback and set up the INSTALLER_EXEMPT flags. 1190 // UPGRADE_EXEMPT is chosen instead of other flags because it is the same flag 1191 // that 1192 // was assigned to pre-installed apps in RuntimePermissionsUpgradeController, 1193 // and to 1194 // apps with missing permission state. 1195 // This way we make sure both pre-installed apps, and apps updated/installed 1196 // after 1197 // a rollback snapshot is taken, can get the allowlist for permissions that 1198 // won't be 1199 // allowlisted otherwise. 1200 newFlags = newFlags or PermissionFlags.UPGRADE_EXEMPT 1201 true 1202 } else { 1203 wasExempt 1204 } 1205 newFlags = 1206 if (permission.isHardRestricted && !isExempt) { 1207 newFlags or PermissionFlags.RESTRICTION_REVOKED 1208 } else { 1209 newFlags andInv PermissionFlags.RESTRICTION_REVOKED 1210 } 1211 newFlags = 1212 if ( 1213 permission.isSoftRestricted && 1214 !isExempt && 1215 !requestingPackageStates.anyIndexed { _, it -> 1216 isSoftRestrictedPermissionExemptForPackage( 1217 it, 1218 targetSdkVersion, 1219 permissionName, 1220 ) 1221 } 1222 ) { 1223 newFlags or PermissionFlags.SOFT_RESTRICTED 1224 } else { 1225 newFlags andInv PermissionFlags.SOFT_RESTRICTED 1226 } 1227 setPermissionFlags(appId, userId, permissionName, newFlags) 1228 } else { 1229 Slog.e( 1230 LOG_TAG, 1231 "Unknown protection level ${permission.protectionLevel}" + 1232 "for permission ${permission.name} while evaluating permission state" + 1233 "for appId $appId and userId $userId", 1234 ) 1235 } 1236 } 1237 1238 private fun MutateStateScope.inheritImplicitPermissionStates(appId: Int, userId: Int) { 1239 val targetSdkVersion = getAppIdTargetSdkVersion(appId, null) 1240 val implicitPermissions = MutableIndexedSet<String>() 1241 forEachPackageInAppId(appId) { 1242 implicitPermissions += it.androidPackage!!.implicitPermissions 1243 } 1244 implicitPermissions.forEachIndexed implicitPermissions@{ _, implicitPermissionName -> 1245 val implicitPermission = newState.systemState.permissions[implicitPermissionName] 1246 checkNotNull(implicitPermission) { 1247 "Unknown implicit permission $implicitPermissionName in split permissions" 1248 } 1249 if (!implicitPermission.isRuntime) { 1250 return@implicitPermissions 1251 } 1252 // Explicitly check against the old state to determine if this permission is new. 1253 val isNewPermission = 1254 getOldStatePermissionFlags(appId, userId, implicitPermissionName) == 0 1255 if (!isNewPermission) { 1256 return@implicitPermissions 1257 } 1258 val sourcePermissions = 1259 newState.externalState.implicitToSourcePermissions[implicitPermissionName] 1260 ?: return@implicitPermissions 1261 var newFlags = getPermissionFlags(appId, userId, implicitPermissionName) 1262 sourcePermissions.forEachIndexed sourcePermissions@{ _, sourcePermissionName -> 1263 val sourcePermission = newState.systemState.permissions[sourcePermissionName] 1264 checkNotNull(sourcePermission) { 1265 "Unknown source permission $sourcePermissionName in split permissions" 1266 } 1267 val sourceFlags = getPermissionFlags(appId, userId, sourcePermissionName) 1268 val isSourceGranted = PermissionFlags.isPermissionGranted(sourceFlags) 1269 val isNewGranted = PermissionFlags.isPermissionGranted(newFlags) 1270 val isGrantingNewFromRevoke = isSourceGranted && !isNewGranted 1271 if (isSourceGranted == isNewGranted || isGrantingNewFromRevoke) { 1272 if (isGrantingNewFromRevoke) { 1273 newFlags = 0 1274 } 1275 newFlags = newFlags or (sourceFlags and PermissionFlags.MASK_RUNTIME) 1276 } 1277 } 1278 if ( 1279 targetSdkVersion >= Build.VERSION_CODES.M && 1280 implicitPermissionName in NO_IMPLICIT_FLAG_PERMISSIONS 1281 ) { 1282 newFlags = newFlags andInv PermissionFlags.IMPLICIT 1283 } else { 1284 newFlags = newFlags or PermissionFlags.IMPLICIT 1285 } 1286 setPermissionFlags(appId, userId, implicitPermissionName, newFlags) 1287 } 1288 } 1289 1290 private fun isCompatibilityPermissionForPackage( 1291 androidPackage: AndroidPackage, 1292 permissionName: String, 1293 ): Boolean { 1294 for (compatibilityPermission in CompatibilityPermissionInfo.COMPAT_PERMS) { 1295 if ( 1296 compatibilityPermission.name == permissionName && 1297 androidPackage.targetSdkVersion < compatibilityPermission.sdkVersion 1298 ) { 1299 Slog.i( 1300 LOG_TAG, 1301 "Auto-granting $permissionName to old package" + 1302 " ${androidPackage.packageName}", 1303 ) 1304 return true 1305 } 1306 } 1307 return false 1308 } 1309 1310 private fun MutateStateScope.shouldGrantPermissionBySignature( 1311 packageState: PackageState, 1312 permission: Permission, 1313 ): Boolean { 1314 // Check if the package is allowed to use this signature permission. A package is allowed 1315 // to use a signature permission if: 1316 // - it has the same set of signing certificates as the source package 1317 // - or its signing certificate was rotated from the source package's certificate 1318 // - or its signing certificate is a previous signing certificate of the defining 1319 // package, and the defining package still trusts the old certificate for permissions 1320 // - or it shares a common signing certificate in its lineage with the defining package, 1321 // and the defining package still trusts the old certificate for permissions 1322 // - or it shares the above relationships with the system package 1323 val packageSigningDetails = packageState.androidPackage!!.signingDetails 1324 val sourceSigningDetails = 1325 newState.externalState.packageStates[permission.packageName] 1326 ?.androidPackage 1327 ?.signingDetails 1328 val platformSigningDetails = 1329 newState.externalState.packageStates[PLATFORM_PACKAGE_NAME]!! 1330 .androidPackage!! 1331 .signingDetails 1332 val hasCommonSigner = 1333 sourceSigningDetails?.hasCommonSignerWithCapability( 1334 packageSigningDetails, 1335 SigningDetails.CertCapabilities.PERMISSION, 1336 ) == true || 1337 packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) || 1338 platformSigningDetails.checkCapability( 1339 packageSigningDetails, 1340 SigningDetails.CertCapabilities.PERMISSION, 1341 ) 1342 if (!Flags.signaturePermissionAllowlistEnabled()) { 1343 return hasCommonSigner 1344 } 1345 if (!hasCommonSigner) { 1346 return false 1347 } 1348 // A platform signature permission also needs to be allowlisted on non-debuggable builds. 1349 if (permission.packageName == PLATFORM_PACKAGE_NAME) { 1350 val isRequestedByFactoryApp = 1351 if (packageState.isSystem) { 1352 // For updated system applications, a signature permission still needs to be 1353 // allowlisted if it wasn't requested by the original application. 1354 if (packageState.isUpdatedSystemApp) { 1355 val disabledSystemPackage = 1356 newState.externalState.disabledSystemPackageStates[ 1357 packageState.packageName] 1358 ?.androidPackage 1359 disabledSystemPackage != null && 1360 permission.name in disabledSystemPackage.requestedPermissions 1361 } else { 1362 true 1363 } 1364 } else { 1365 false 1366 } 1367 if ( 1368 !(isRequestedByFactoryApp || 1369 getSignaturePermissionAllowlistState(packageState, permission.name) == true) 1370 ) { 1371 Slog.w( 1372 LOG_TAG, 1373 "Signature permission ${permission.name} for package" + 1374 " ${packageState.packageName} (${packageState.path}) not in" + 1375 " signature permission allowlist", 1376 ) 1377 if (!Build.isDebuggable() || isSignaturePermissionAllowlistForceEnforced) { 1378 return false 1379 } 1380 } 1381 } 1382 return true 1383 } 1384 1385 private fun MutateStateScope.getSignaturePermissionAllowlistState( 1386 packageState: PackageState, 1387 permissionName: String, 1388 ): Boolean? { 1389 val permissionAllowlist = newState.externalState.permissionAllowlist 1390 val packageName = packageState.packageName 1391 return when { 1392 packageState.isVendor || packageState.isOdm -> 1393 permissionAllowlist.getVendorSignatureAppAllowlistState(packageName, permissionName) 1394 packageState.isProduct -> 1395 permissionAllowlist.getProductSignatureAppAllowlistState( 1396 packageName, 1397 permissionName, 1398 ) 1399 packageState.isSystemExt -> 1400 permissionAllowlist.getSystemExtSignatureAppAllowlistState( 1401 packageName, 1402 permissionName, 1403 ) 1404 else -> 1405 permissionAllowlist.getApexSignatureAppAllowlistState(packageName, permissionName) 1406 ?: permissionAllowlist.getProductSignatureAppAllowlistState( 1407 packageName, 1408 permissionName, 1409 ) 1410 ?: permissionAllowlist.getVendorSignatureAppAllowlistState( 1411 packageName, 1412 permissionName, 1413 ) 1414 ?: permissionAllowlist.getSystemExtSignatureAppAllowlistState( 1415 packageName, 1416 permissionName, 1417 ) 1418 ?: permissionAllowlist.getSignatureAppAllowlistState( 1419 packageName, 1420 permissionName, 1421 ) 1422 } 1423 } 1424 1425 /** 1426 * We only check privileged permission allowlist for system privileged apps. Hence, for platform 1427 * or for normal apps, we return true to indicate that we don't need to check the allowlist and 1428 * will let follow-up checks to decide whether we should grant the permission. 1429 * 1430 * @return `true`, if the permission is allowlisted for system privileged apps, or if we don't 1431 * need to check the allowlist (for platform or for normal apps). `false`, if the permission 1432 * is not allowlisted for system privileged apps. 1433 */ 1434 private fun MutateStateScope.checkPrivilegedPermissionAllowlistIfNeeded( 1435 packageState: PackageState, 1436 permission: Permission, 1437 ): Boolean { 1438 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) { 1439 return true 1440 } 1441 if (packageState.packageName == PLATFORM_PACKAGE_NAME) { 1442 return true 1443 } 1444 if (!(packageState.isSystem && packageState.isPrivileged)) { 1445 return true 1446 } 1447 if ( 1448 permission.packageName !in newState.externalState.privilegedPermissionAllowlistPackages 1449 ) { 1450 return true 1451 } 1452 val allowlistState = getPrivilegedPermissionAllowlistState(packageState, permission.name) 1453 if (allowlistState != null) { 1454 return allowlistState 1455 } 1456 // Updated system apps do not need to be allowlisted 1457 if (packageState.isUpdatedSystemApp) { 1458 return true 1459 } 1460 // Only enforce the privileged permission allowlist on boot 1461 if (!newState.externalState.isSystemReady) { 1462 // Apps that are in updated apex's do not need to be allowlisted 1463 if (!packageState.isApkInUpdatedApex) { 1464 Slog.w( 1465 LOG_TAG, 1466 "Privileged permission ${permission.name} for package" + 1467 " ${packageState.packageName} (${packageState.path}) not in" + 1468 " privileged permission allowlist", 1469 ) 1470 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { 1471 privilegedPermissionAllowlistViolations += 1472 "${packageState.packageName}" + 1473 " (${packageState.path}): ${permission.name}" 1474 } 1475 } 1476 } 1477 return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE 1478 } 1479 1480 /** 1481 * Get the whether a privileged permission is explicitly allowed or denied for a package in the 1482 * allowlist, or `null` if it's not in the allowlist. 1483 */ 1484 private fun MutateStateScope.getPrivilegedPermissionAllowlistState( 1485 packageState: PackageState, 1486 permissionName: String, 1487 ): Boolean? { 1488 val permissionAllowlist = newState.externalState.permissionAllowlist 1489 val apexModuleName = packageState.apexModuleName 1490 val packageName = packageState.packageName 1491 return when { 1492 packageState.isVendor || packageState.isOdm -> 1493 permissionAllowlist.getVendorPrivilegedAppAllowlistState( 1494 packageName, 1495 permissionName, 1496 ) 1497 packageState.isProduct -> 1498 permissionAllowlist.getProductPrivilegedAppAllowlistState( 1499 packageName, 1500 permissionName, 1501 ) 1502 packageState.isSystemExt -> 1503 permissionAllowlist.getSystemExtPrivilegedAppAllowlistState( 1504 packageName, 1505 permissionName, 1506 ) 1507 apexModuleName != null -> { 1508 val nonApexAllowlistState = 1509 permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName) 1510 if (nonApexAllowlistState != null) { 1511 // TODO(andreionea): Remove check as soon as all apk-in-apex 1512 // permission allowlists are migrated. 1513 Slog.w( 1514 LOG_TAG, 1515 "Package $packageName is an APK in APEX but has permission" + 1516 " allowlist on the system image, please bundle the allowlist in the" + 1517 " $apexModuleName APEX instead", 1518 ) 1519 } 1520 val apexAllowlistState = 1521 permissionAllowlist.getApexPrivilegedAppAllowlistState( 1522 apexModuleName, 1523 packageName, 1524 permissionName, 1525 ) 1526 apexAllowlistState ?: nonApexAllowlistState 1527 } 1528 else -> permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName) 1529 } 1530 } 1531 1532 // See also SoftRestrictedPermissionPolicy.mayGrantPermission() 1533 // Note: we need the appIdTargetSdkVersion parameter here because we are OR-ing the exempt 1534 // status for all packages in a shared UID, but the storage soft restriction logic needs to NOT 1535 // exempt when the target SDK version is low, which is the opposite of what most of our code do, 1536 // and thus can't check the individual package's target SDK version and rely on the OR among 1537 // them. 1538 private fun isSoftRestrictedPermissionExemptForPackage( 1539 packageState: PackageState, 1540 appIdTargetSdkVersion: Int, 1541 permissionName: String, 1542 ): Boolean = 1543 when (permissionName) { 1544 Manifest.permission.READ_EXTERNAL_STORAGE, 1545 Manifest.permission.WRITE_EXTERNAL_STORAGE -> 1546 appIdTargetSdkVersion >= Build.VERSION_CODES.Q 1547 else -> false 1548 } 1549 1550 private fun MutateStateScope.getAppIdTargetSdkVersion( 1551 appId: Int, 1552 permissionName: String?, 1553 state: AccessState = newState, 1554 ): Int = 1555 reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, state) { 1556 targetSdkVersion, 1557 packageState -> 1558 val androidPackage = packageState.androidPackage!! 1559 if (permissionName == null || permissionName in androidPackage.requestedPermissions) { 1560 targetSdkVersion.coerceAtMost(androidPackage.targetSdkVersion) 1561 } else { 1562 targetSdkVersion 1563 } 1564 } 1565 1566 private inline fun MutateStateScope.anyPackageInAppId( 1567 appId: Int, 1568 state: AccessState = newState, 1569 predicate: (PackageState) -> Boolean, 1570 ): Boolean { 1571 val packageNames = state.externalState.appIdPackageNames[appId]!! 1572 return packageNames.anyIndexed { _, packageName -> 1573 val packageState = state.externalState.packageStates[packageName]!! 1574 packageState.androidPackage != null && predicate(packageState) 1575 } 1576 } 1577 1578 private inline fun MutateStateScope.forEachPackageInAppId( 1579 appId: Int, 1580 state: AccessState = newState, 1581 action: (PackageState) -> Unit, 1582 ) { 1583 val packageNames = state.externalState.appIdPackageNames[appId]!! 1584 packageNames.forEachIndexed { _, packageName -> 1585 val packageState = state.externalState.packageStates[packageName]!! 1586 if (packageState.androidPackage != null) { 1587 action(packageState) 1588 } 1589 } 1590 } 1591 1592 // Using Int instead of <T> to avoid autoboxing, since we only have the use case for Int. 1593 private inline fun MutateStateScope.reducePackageInAppId( 1594 appId: Int, 1595 initialValue: Int, 1596 state: AccessState = newState, 1597 accumulator: (Int, PackageState) -> Int, 1598 ): Int { 1599 val packageNames = state.externalState.appIdPackageNames[appId]!! 1600 return packageNames.reduceIndexed(initialValue) { value, _, packageName -> 1601 val packageState = state.externalState.packageStates[packageName]!! 1602 if (packageState.androidPackage != null) { 1603 accumulator(value, packageState) 1604 } else { 1605 value 1606 } 1607 } 1608 } 1609 1610 private fun MutateStateScope.shouldGrantPermissionByProtectionFlags( 1611 packageState: PackageState, 1612 permission: Permission, 1613 ): Boolean { 1614 val androidPackage = packageState.androidPackage!! 1615 val knownPackages = newState.externalState.knownPackages 1616 val packageName = packageState.packageName 1617 if ((permission.isPrivileged || permission.isOem) && packageState.isSystem) { 1618 val shouldGrant = 1619 if (packageState.isUpdatedSystemApp) { 1620 // For updated system applications, a privileged/oem permission 1621 // is granted only if it had been defined by the original application. 1622 val disabledSystemPackageState = 1623 newState.externalState.disabledSystemPackageStates[packageState.packageName] 1624 val disabledSystemPackage = disabledSystemPackageState?.androidPackage 1625 disabledSystemPackage != null && 1626 permission.name in disabledSystemPackage.requestedPermissions && 1627 shouldGrantPrivilegedOrOemPermission(disabledSystemPackageState, permission) 1628 } else { 1629 shouldGrantPrivilegedOrOemPermission(packageState, permission) 1630 } 1631 if (shouldGrant) { 1632 return true 1633 } 1634 } 1635 if (permission.isPre23 && androidPackage.targetSdkVersion < Build.VERSION_CODES.M) { 1636 // If this was a previously normal/dangerous permission that got moved 1637 // to a system permission as part of the runtime permission redesign, then 1638 // we still want to blindly grant it to old apps. 1639 return true 1640 } 1641 if ( 1642 permission.isInstaller && 1643 (packageName in knownPackages[KnownPackages.PACKAGE_INSTALLER]!! || 1644 packageName in knownPackages[KnownPackages.PACKAGE_PERMISSION_CONTROLLER]!!) 1645 ) { 1646 // If this permission is to be granted to the system installer and 1647 // this app is an installer or permission controller, then it gets the permission. 1648 return true 1649 } 1650 if ( 1651 permission.isVerifier && packageName in knownPackages[KnownPackages.PACKAGE_VERIFIER]!! 1652 ) { 1653 // If this permission is to be granted to the system verifier and 1654 // this app is a verifier, then it gets the permission. 1655 return true 1656 } 1657 if (permission.isPreInstalled && packageState.isSystem) { 1658 // Any pre-installed system app is allowed to get this permission. 1659 return true 1660 } 1661 if ( 1662 permission.isKnownSigner && 1663 androidPackage.signingDetails.hasAncestorOrSelfWithDigest(permission.knownCerts) 1664 ) { 1665 // If the permission is to be granted to a known signer then check if any of this 1666 // app's signing certificates are in the trusted certificate digest Set. 1667 return true 1668 } 1669 if ( 1670 permission.isSetup && packageName in knownPackages[KnownPackages.PACKAGE_SETUP_WIZARD]!! 1671 ) { 1672 // If this permission is to be granted to the system setup wizard and 1673 // this app is a setup wizard, then it gets the permission. 1674 return true 1675 } 1676 if ( 1677 permission.isSystemTextClassifier && 1678 packageName in knownPackages[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER]!! 1679 ) { 1680 // Special permissions for the system default text classifier. 1681 return true 1682 } 1683 if ( 1684 permission.isConfigurator && 1685 packageName in knownPackages[KnownPackages.PACKAGE_CONFIGURATOR]!! 1686 ) { 1687 // Special permissions for the device configurator. 1688 return true 1689 } 1690 if ( 1691 permission.isIncidentReportApprover && 1692 packageName in knownPackages[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER]!! 1693 ) { 1694 // If this permission is to be granted to the incident report approver and 1695 // this app is the incident report approver, then it gets the permission. 1696 return true 1697 } 1698 if ( 1699 permission.isAppPredictor && 1700 packageName in knownPackages[KnownPackages.PACKAGE_APP_PREDICTOR]!! 1701 ) { 1702 // Special permissions for the system app predictor. 1703 return true 1704 } 1705 if ( 1706 permission.isCompanion && 1707 packageName in knownPackages[KnownPackages.PACKAGE_COMPANION]!! 1708 ) { 1709 // Special permissions for the system companion device manager. 1710 return true 1711 } 1712 if (permission.isRecents && packageName in knownPackages[KnownPackages.PACKAGE_RECENTS]!!) { 1713 // Special permission for the recents app. 1714 return true 1715 } 1716 if (permission.isModule && packageState.apexModuleName != null) { 1717 // Special permission granted for APKs inside APEX modules. 1718 return true 1719 } 1720 return false 1721 } 1722 1723 private fun MutateStateScope.shouldGrantPrivilegedOrOemPermission( 1724 packageState: PackageState, 1725 permission: Permission, 1726 ): Boolean { 1727 val permissionName = permission.name 1728 val packageName = packageState.packageName 1729 when { 1730 permission.isPrivileged -> { 1731 if (packageState.isPrivileged) { 1732 // In any case, don't grant a privileged permission to privileged vendor apps, 1733 // if the permission's protectionLevel does not have the extra vendorPrivileged 1734 // flag. 1735 if ( 1736 (packageState.isVendor || packageState.isOdm) && 1737 !permission.isVendorPrivileged 1738 ) { 1739 Slog.w( 1740 LOG_TAG, 1741 "Permission $permissionName cannot be granted to privileged" + 1742 " vendor (or odm) app $packageName because it isn't a" + 1743 " vendorPrivileged permission", 1744 ) 1745 return false 1746 } 1747 return true 1748 } 1749 } 1750 permission.isOem -> { 1751 if (packageState.isOem) { 1752 val allowlistState = 1753 newState.externalState.permissionAllowlist.getOemAppAllowlistState( 1754 packageName, 1755 permissionName, 1756 ) 1757 checkNotNull(allowlistState) { 1758 "OEM permission $permissionName requested by package" + 1759 " $packageName must be explicitly declared granted or not" 1760 } 1761 return allowlistState 1762 } 1763 } 1764 } 1765 return false 1766 } 1767 1768 override fun MutateStateScope.onSystemReady() { 1769 if (!privilegedPermissionAllowlistViolations.isEmpty()) { 1770 throw IllegalStateException( 1771 "Signature|privileged permissions not in privileged" + 1772 " permission allowlist: $privilegedPermissionAllowlistViolations" 1773 ) 1774 } 1775 } 1776 1777 override fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) { 1778 with(persistence) { this@parseSystemState.parseSystemState(state) } 1779 } 1780 1781 override fun BinaryXmlSerializer.serializeSystemState(state: AccessState) { 1782 with(persistence) { this@serializeSystemState.serializeSystemState(state) } 1783 } 1784 1785 override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) { 1786 with(persistence) { this@parseUserState.parseUserState(state, userId) } 1787 } 1788 1789 override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) { 1790 with(persistence) { this@serializeUserState.serializeUserState(state, userId) } 1791 } 1792 1793 fun GetStateScope.getPermissionTrees(): IndexedMap<String, Permission> = 1794 state.systemState.permissionTrees 1795 1796 fun GetStateScope.findPermissionTree(permissionName: String): Permission? = 1797 state.systemState.permissionTrees.firstNotNullOfOrNullIndexed { 1798 _, 1799 permissionTreeName, 1800 permissionTree -> 1801 if ( 1802 permissionName.startsWith(permissionTreeName) && 1803 permissionName.length > permissionTreeName.length && 1804 permissionName[permissionTreeName.length] == '.' 1805 ) { 1806 permissionTree 1807 } else { 1808 null 1809 } 1810 } 1811 1812 fun MutateStateScope.addPermissionTree(permission: Permission) { 1813 newState.mutateSystemState().mutatePermissionTrees()[permission.name] = permission 1814 } 1815 1816 /** returns all permission group definitions available in the system */ 1817 fun GetStateScope.getPermissionGroups(): IndexedMap<String, PermissionGroupInfo> = 1818 state.systemState.permissionGroups 1819 1820 /** returns all permission definitions available in the system */ 1821 fun GetStateScope.getPermissions(): IndexedMap<String, Permission> = 1822 state.systemState.permissions 1823 1824 fun MutateStateScope.addPermission( 1825 permission: Permission, 1826 isSynchronousWrite: Boolean = false, 1827 ) { 1828 val writeMode = if (isSynchronousWrite) WriteMode.SYNCHRONOUS else WriteMode.ASYNCHRONOUS 1829 newState.mutateSystemState(writeMode).mutatePermissions()[permission.name] = permission 1830 } 1831 1832 fun MutateStateScope.removePermission(permission: Permission) { 1833 newState.mutateSystemState().mutatePermissions() -= permission.name 1834 } 1835 1836 fun GetStateScope.getUidPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? = 1837 state.userStates[userId]?.appIdPermissionFlags?.get(appId) 1838 1839 fun GetStateScope.getPermissionFlags(appId: Int, userId: Int, permissionName: String): Int = 1840 getPermissionFlags(state, appId, userId, permissionName) 1841 1842 private fun MutateStateScope.getOldStatePermissionFlags( 1843 appId: Int, 1844 userId: Int, 1845 permissionName: String, 1846 ): Int = getPermissionFlags(oldState, appId, userId, permissionName) 1847 1848 private fun getPermissionFlags( 1849 state: AccessState, 1850 appId: Int, 1851 userId: Int, 1852 permissionName: String, 1853 ): Int = 1854 state.userStates[userId]?.appIdPermissionFlags?.get(appId).getWithDefault(permissionName, 0) 1855 1856 fun GetStateScope.getAllPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? = 1857 state.userStates[userId]?.appIdPermissionFlags?.get(appId) 1858 1859 fun MutateStateScope.setPermissionFlags( 1860 appId: Int, 1861 userId: Int, 1862 permissionName: String, 1863 flags: Int, 1864 ): Boolean = 1865 updatePermissionFlags(appId, userId, permissionName, PermissionFlags.MASK_ALL, flags) 1866 1867 fun MutateStateScope.updatePermissionFlags( 1868 appId: Int, 1869 userId: Int, 1870 permissionName: String, 1871 flagMask: Int, 1872 flagValues: Int, 1873 ): Boolean { 1874 if (userId !in newState.userStates) { 1875 // Despite that we check UserManagerInternal.exists() in PermissionService, we may still 1876 // sometimes get race conditions between that check and the actual mutateState() call. 1877 // This should rarely happen but at least we should not crash. 1878 Slog.e(LOG_TAG, "Unable to update permission flags for missing user $userId") 1879 return false 1880 } 1881 val oldFlags = 1882 newState.userStates[userId]!! 1883 .appIdPermissionFlags[appId] 1884 .getWithDefault(permissionName, 0) 1885 val newFlags = (oldFlags andInv flagMask) or (flagValues and flagMask) 1886 if (oldFlags == newFlags) { 1887 return false 1888 } 1889 val appIdPermissionFlags = newState.mutateUserState(userId)!!.mutateAppIdPermissionFlags() 1890 val permissionFlags = appIdPermissionFlags.mutateOrPut(appId) { MutableIndexedMap() } 1891 permissionFlags.putWithDefault(permissionName, newFlags, 0) 1892 if (permissionFlags.isEmpty()) { 1893 appIdPermissionFlags -= appId 1894 } 1895 onPermissionFlagsChangedListeners.forEachIndexed { _, it -> 1896 it.onPermissionFlagsChanged(appId, userId, permissionName, oldFlags, newFlags) 1897 } 1898 return true 1899 } 1900 1901 fun addOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) { 1902 synchronized(onPermissionFlagsChangedListenersLock) { 1903 onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners + listener 1904 } 1905 } 1906 1907 fun removeOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) { 1908 synchronized(onPermissionFlagsChangedListenersLock) { 1909 onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners - listener 1910 } 1911 } 1912 1913 override fun migrateSystemState(state: MutableAccessState) { 1914 migration.migrateSystemState(state) 1915 } 1916 1917 override fun migrateUserState(state: MutableAccessState, userId: Int) { 1918 migration.migrateUserState(state, userId) 1919 } 1920 1921 override fun MutateStateScope.upgradePackageState( 1922 packageState: PackageState, 1923 userId: Int, 1924 version: Int, 1925 ) { 1926 with(upgrade) { upgradePackageState(packageState, userId, version) } 1927 } 1928 1929 companion object { 1930 private val LOG_TAG = AppIdPermissionPolicy::class.java.simpleName 1931 1932 private const val PLATFORM_PACKAGE_NAME = "android" 1933 1934 // A set of permissions that we don't want to revoke when they are no longer implicit. 1935 private val NO_IMPLICIT_FLAG_PERMISSIONS = 1936 indexedSetOf( 1937 Manifest.permission.ACCESS_MEDIA_LOCATION, 1938 Manifest.permission.ACTIVITY_RECOGNITION, 1939 Manifest.permission.READ_MEDIA_AUDIO, 1940 Manifest.permission.READ_MEDIA_IMAGES, 1941 Manifest.permission.READ_MEDIA_VIDEO, 1942 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED, 1943 ) 1944 1945 private val NEARBY_DEVICES_PERMISSIONS = 1946 indexedSetOf( 1947 Manifest.permission.BLUETOOTH_ADVERTISE, 1948 Manifest.permission.BLUETOOTH_CONNECT, 1949 Manifest.permission.BLUETOOTH_SCAN, 1950 Manifest.permission.NEARBY_WIFI_DEVICES, 1951 ) 1952 1953 private val NOTIFICATIONS_PERMISSIONS = indexedSetOf(Manifest.permission.POST_NOTIFICATIONS) 1954 1955 private val STORAGE_AND_MEDIA_PERMISSIONS = 1956 indexedSetOf( 1957 Manifest.permission.READ_EXTERNAL_STORAGE, 1958 Manifest.permission.WRITE_EXTERNAL_STORAGE, 1959 Manifest.permission.READ_MEDIA_AUDIO, 1960 Manifest.permission.READ_MEDIA_VIDEO, 1961 Manifest.permission.READ_MEDIA_IMAGES, 1962 Manifest.permission.ACCESS_MEDIA_LOCATION, 1963 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED, 1964 ) 1965 1966 /** Mask for all permission flags that can be set by the user */ 1967 private const val USER_SETTABLE_MASK = 1968 PermissionFlags.USER_SET or 1969 PermissionFlags.USER_FIXED or 1970 PermissionFlags.APP_OP_REVOKED or 1971 PermissionFlags.ONE_TIME or 1972 PermissionFlags.HIBERNATION or 1973 PermissionFlags.USER_SELECTED 1974 1975 /** 1976 * Mask for all permission flags that imply we shouldn't automatically modify the permission 1977 * grant state. 1978 */ 1979 private const val SYSTEM_OR_POLICY_FIXED_MASK = 1980 PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED 1981 } 1982 1983 /** Listener for permission flags changes. */ 1984 interface OnPermissionFlagsChangedListener { 1985 /** 1986 * Called when a permission flags change has been made to the upcoming new state. 1987 * 1988 * Implementations should keep this method fast to avoid stalling the locked state mutation, 1989 * and only call external code after [onStateMutated] when the new state has actually become 1990 * the current state visible to external code. 1991 */ 1992 fun onPermissionFlagsChanged( 1993 appId: Int, 1994 userId: Int, 1995 permissionName: String, 1996 oldFlags: Int, 1997 newFlags: Int, 1998 ) 1999 2000 /** 2001 * Called when the upcoming new state has become the current state. 2002 * 2003 * Implementations should keep this method fast to avoid stalling the locked state mutation. 2004 */ 2005 fun onStateMutated() 2006 } 2007 } 2008