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