Loading services/permission/java/com/android/server/permission/access/immutable/IndexedListExtensions.kt +12 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,18 @@ inline fun <T> IndexedList<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boole operator fun <T> IndexedList<T>.plus(element: T): MutableIndexedList<T> = toMutable().apply { this += element } // Using Int instead of <R> to avoid autoboxing, since we only have the use case for Int. inline fun <T> IndexedList<T>.reduceIndexed( initialValue: Int, accumulator: (Int, Int, T) -> Int ): Int { var value = initialValue forEachIndexed { index, element -> value = accumulator(value, index, element) } return value } @Suppress("NOTHING_TO_INLINE") inline operator fun <T> MutableIndexedList<T>.minusAssign(element: T) { remove(element) Loading services/permission/java/com/android/server/permission/access/immutable/IndexedListSetExtensions.kt +12 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,18 @@ inline fun <T> IndexedListSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Bo operator fun <T> IndexedListSet<T>.plus(element: T): MutableIndexedListSet<T> = toMutable().apply { this += element } // Using Int instead of <R> to avoid autoboxing, since we only have the use case for Int. inline fun <T> IndexedListSet<T>.reduceIndexed( initialValue: Int, accumulator: (Int, Int, T) -> Int ): Int { var value = initialValue forEachIndexed { index, element -> value = accumulator(value, index, element) } return value } @Suppress("NOTHING_TO_INLINE") inline operator fun <T> MutableIndexedListSet<T>.minusAssign(element: T) { remove(element) Loading services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt +95 −82 Original line number Diff line number Diff line Loading @@ -205,8 +205,9 @@ class AppIdPermissionPolicy : SchemePolicy() { if (!permission.isHardOrSoftRestricted) { return@forEach } val isRequestedBySystemPackage = anyRequestingPackageInAppId(appId, permissionName) { it.isSystem } val isRequestedBySystemPackage = anyPackageInAppId(appId) { it.isSystem && permissionName in it.androidPackage!!.requestedPermissions } if (isRequestedBySystemPackage) { return@forEach } Loading Loading @@ -247,8 +248,9 @@ class AppIdPermissionPolicy : SchemePolicy() { if (permission.isRemoved) { return@forEach } val isRequestedByOtherPackages = anyRequestingPackageInAppId(appId, permissionName) { it.packageName != packageName val isRequestedByOtherPackages = anyPackageInAppId(appId) { it.packageName != packageName && permissionName in it.androidPackage!!.requestedPermissions } if (isRequestedByOtherPackages) { return@forEach Loading Loading @@ -630,32 +632,45 @@ class AppIdPermissionPolicy : SchemePolicy() { // information about the package before OTA anyway. return } // If the app is updated, and has scoped storage permissions, then it is possible that the // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions. newState.userStates.forEachIndexed { _, userId, userState -> userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, oldFlags -> if (permissionName !in STORAGE_AND_MEDIA_PERMISSIONS || oldFlags == 0) { return@forEachReversedIndexed val oldTargetSdkVersion = reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, oldState) { targetSdkVersion, packageState -> targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) } val oldTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, oldState) val newTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, newState) val newTargetSdkVersion = reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, newState) { targetSdkVersion, packageState -> targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) } @Suppress("ConvertTwoComparisonsToRangeCheck") val isTargetSdkVersionDowngraded = oldTargetSdkVersion >= Build.VERSION_CODES.Q && newTargetSdkVersion < Build.VERSION_CODES.Q @Suppress("ConvertTwoComparisonsToRangeCheck") val isTargetSdkVersionUpgraded = oldTargetSdkVersion < Build.VERSION_CODES.Q && newTargetSdkVersion >= Build.VERSION_CODES.Q val oldIsRequestLegacyExternalStorage = anyRequestingPackageInAppId( appId, permissionName, oldState ) { it.androidPackage!!.isRequestLegacyExternalStorage } val newIsRequestLegacyExternalStorage = anyRequestingPackageInAppId( appId, permissionName, newState ) { it.androidPackage!!.isRequestLegacyExternalStorage } val oldIsRequestLegacyExternalStorage = anyPackageInAppId(appId, oldState) { it.androidPackage!!.isRequestLegacyExternalStorage } val newIsRequestLegacyExternalStorage = anyPackageInAppId(appId, newState) { it.androidPackage!!.isRequestLegacyExternalStorage } val isNewlyRequestingLegacyExternalStorage = !isTargetSdkVersionUpgraded && !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage if ((isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded) && val shouldRevokeStorageAndMediaPermissions = isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded if (shouldRevokeStorageAndMediaPermissions) { newState.userStates.forEachIndexed { _, userId, userState -> userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, oldFlags -> if (permissionName in STORAGE_AND_MEDIA_PERMISSIONS && oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED)) { Slog.v(LOG_TAG, "Revoking storage permission: $permissionName for appId: " + " $appId and user: $userId") Slog.v( LOG_TAG, "Revoking storage permission: $permissionName for appId: " + " $appId and user: $userId" ) val newFlags = oldFlags andInv ( PermissionFlags.RUNTIME_GRANTED or USER_SETTABLE_MASK ) Loading @@ -664,6 +679,7 @@ class AppIdPermissionPolicy : SchemePolicy() { } } } } private fun MutateStateScope.evaluatePermissionStateForAllPackages( permissionName: String, Loading @@ -672,8 +688,9 @@ class AppIdPermissionPolicy : SchemePolicy() { val externalState = newState.externalState externalState.userIds.forEachIndexed { _, userId -> externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> val isPermissionRequested = anyRequestingPackageInAppId(appId, permissionName) { true } val isPermissionRequested = anyPackageInAppId(appId) { permissionName in it.androidPackage!!.requestedPermissions } if (isPermissionRequested) { evaluatePermissionState(appId, userId, permissionName, installedPackageState) } Loading Loading @@ -711,8 +728,21 @@ class AppIdPermissionPolicy : SchemePolicy() { installedPackageState: PackageState? ) { val packageNames = newState.externalState.appIdPackageNames[appId]!! val hasMissingPackage = packageNames.anyIndexed { _, packageName -> newState.externalState.packageStates[packageName]!!.androidPackage == null // Repeatedly checking whether a permission is requested can actually be costly, so we cache // the result for this method which is frequently called during boot, instead of calling // anyPackageInAppId() and checking requested permissions multiple times. val requestingPackageStates = MutableIndexedList<PackageState>() var hasMissingPackage = false packageNames.forEachIndexed { _, packageName -> val packageState = newState.externalState.packageStates[packageName]!! val androidPackage = packageState.androidPackage if (androidPackage != null) { if (permissionName in androidPackage.requestedPermissions) { requestingPackageStates += packageState } } else { hasMissingPackage = true } } if (packageNames.size == 1 && hasMissingPackage) { // For non-shared-user packages with missing androidPackage, skip evaluation. Loading @@ -736,8 +766,8 @@ class AppIdPermissionPolicy : SchemePolicy() { val isRequestedByInstalledPackage = installedPackageState != null && permissionName in installedPackageState.androidPackage!!.requestedPermissions val isRequestedBySystemPackage = anyRequestingPackageInAppId(appId, permissionName) { it.isSystem } val isCompatibilityPermission = anyRequestingPackageInAppId(appId, permissionName) { requestingPackageStates.anyIndexed { _, it -> it.isSystem } val isCompatibilityPermission = requestingPackageStates.anyIndexed { _, it -> isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName) } // If this is an existing, non-system package, Loading @@ -762,18 +792,15 @@ class AppIdPermissionPolicy : SchemePolicy() { // Keep the non-runtime permission grants for shared UID with missing androidPackage PermissionFlags.PROTECTION_GRANTED } else { val mayGrantByPrivileged = !permission.isPrivileged || ( anyRequestingPackageInAppId(appId, permissionName) { val mayGrantByPrivileged = !permission.isPrivileged || requestingPackageStates.anyIndexed { _, it -> checkPrivilegedPermissionAllowlist(it, permission) } ) val shouldGrantBySignature = permission.isSignature && ( anyRequestingPackageInAppId(appId, permissionName) { val shouldGrantBySignature = permission.isSignature && requestingPackageStates.anyIndexed { _, it -> shouldGrantPermissionBySignature(it, permission) } ) val shouldGrantByProtectionFlags = anyRequestingPackageInAppId(appId, permissionName) { val shouldGrantByProtectionFlags = requestingPackageStates.anyIndexed { _, it -> shouldGrantPermissionByProtectionFlags(it, permission) } if (mayGrantByPrivileged && Loading Loading @@ -805,7 +832,12 @@ class AppIdPermissionPolicy : SchemePolicy() { } else if (permission.isRuntime) { var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME val wasRevoked = newFlags != 0 && !PermissionFlags.isPermissionGranted(newFlags) if (getAppIdTargetSdkVersion(appId, permissionName) < Build.VERSION_CODES.M) { val targetSdkVersion = requestingPackageStates.reduceIndexed(Build.VERSION_CODES.CUR_DEVELOPMENT) { targetSdkVersion, _, packageState -> targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) } if (targetSdkVersion < Build.VERSION_CODES.M) { if (permission.isRuntimeOnly) { // Different from the old implementation, which simply skips a runtime-only // permission, we now only allow holding on to the restriction related flags, Loading Loading @@ -837,7 +869,7 @@ class AppIdPermissionPolicy : SchemePolicy() { val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED) val isLeanbackNotificationsPermission = newState.externalState.isLeanback && permissionName in NOTIFICATIONS_PERMISSIONS val isImplicitPermission = anyRequestingPackageInAppId(appId, permissionName) { val isImplicitPermission = requestingPackageStates.anyIndexed { _, it -> permissionName in it.androidPackage!!.implicitPermissions } val sourcePermissions = newState.externalState Loading Loading @@ -1108,18 +1140,6 @@ class AppIdPermissionPolicy : SchemePolicy() { } } private fun MutateStateScope.getAppIdTargetSdkVersion( appId: Int, permissionName: String, state: AccessState = newState ): Int { var targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT forEachRequestingPackageInAppId(appId, permissionName, state) { targetSdkVersion = targetSdkVersion.coerceAtMost(it.androidPackage!!.targetSdkVersion) } return targetSdkVersion } private inline fun MutateStateScope.anyPackageInAppId( appId: Int, state: AccessState = newState, Loading @@ -1128,22 +1148,10 @@ class AppIdPermissionPolicy : SchemePolicy() { val packageNames = state.externalState.appIdPackageNames[appId]!! return packageNames.anyIndexed { _, packageName -> val packageState = state.externalState.packageStates[packageName]!! val androidPackage = packageState.androidPackage androidPackage != null && predicate(packageState) packageState.androidPackage != null && predicate(packageState) } } private inline fun MutateStateScope.anyRequestingPackageInAppId( appId: Int, permissionName: String, state: AccessState = newState, predicate: (PackageState) -> Boolean ): Boolean = anyPackageInAppId(appId, state) { packageState -> permissionName in packageState.androidPackage!!.requestedPermissions && predicate(packageState) } private inline fun MutateStateScope.forEachPackageInAppId( appId: Int, state: AccessState = newState, Loading @@ -1158,15 +1166,20 @@ class AppIdPermissionPolicy : SchemePolicy() { } } private inline fun MutateStateScope.forEachRequestingPackageInAppId( // Using Int instead of <T> to avoid autoboxing, since we only have the use case for Int. private inline fun MutateStateScope.reducePackageInAppId( appId: Int, permissionName: String, initialValue: Int, state: AccessState = newState, action: (PackageState) -> Unit ) { forEachPackageInAppId(appId, state) { packageState -> if (permissionName in packageState.androidPackage!!.requestedPermissions) { action(packageState) accumulator: (Int, PackageState) -> Int ): Int { val packageNames = state.externalState.appIdPackageNames[appId]!! return packageNames.reduceIndexed(initialValue) { value, _, packageName -> val packageState = state.externalState.packageStates[packageName]!! if (packageState.androidPackage != null) { accumulator(value, packageState) } else { value } } } Loading Loading
services/permission/java/com/android/server/permission/access/immutable/IndexedListExtensions.kt +12 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,18 @@ inline fun <T> IndexedList<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boole operator fun <T> IndexedList<T>.plus(element: T): MutableIndexedList<T> = toMutable().apply { this += element } // Using Int instead of <R> to avoid autoboxing, since we only have the use case for Int. inline fun <T> IndexedList<T>.reduceIndexed( initialValue: Int, accumulator: (Int, Int, T) -> Int ): Int { var value = initialValue forEachIndexed { index, element -> value = accumulator(value, index, element) } return value } @Suppress("NOTHING_TO_INLINE") inline operator fun <T> MutableIndexedList<T>.minusAssign(element: T) { remove(element) Loading
services/permission/java/com/android/server/permission/access/immutable/IndexedListSetExtensions.kt +12 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,18 @@ inline fun <T> IndexedListSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Bo operator fun <T> IndexedListSet<T>.plus(element: T): MutableIndexedListSet<T> = toMutable().apply { this += element } // Using Int instead of <R> to avoid autoboxing, since we only have the use case for Int. inline fun <T> IndexedListSet<T>.reduceIndexed( initialValue: Int, accumulator: (Int, Int, T) -> Int ): Int { var value = initialValue forEachIndexed { index, element -> value = accumulator(value, index, element) } return value } @Suppress("NOTHING_TO_INLINE") inline operator fun <T> MutableIndexedListSet<T>.minusAssign(element: T) { remove(element) Loading
services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt +95 −82 Original line number Diff line number Diff line Loading @@ -205,8 +205,9 @@ class AppIdPermissionPolicy : SchemePolicy() { if (!permission.isHardOrSoftRestricted) { return@forEach } val isRequestedBySystemPackage = anyRequestingPackageInAppId(appId, permissionName) { it.isSystem } val isRequestedBySystemPackage = anyPackageInAppId(appId) { it.isSystem && permissionName in it.androidPackage!!.requestedPermissions } if (isRequestedBySystemPackage) { return@forEach } Loading Loading @@ -247,8 +248,9 @@ class AppIdPermissionPolicy : SchemePolicy() { if (permission.isRemoved) { return@forEach } val isRequestedByOtherPackages = anyRequestingPackageInAppId(appId, permissionName) { it.packageName != packageName val isRequestedByOtherPackages = anyPackageInAppId(appId) { it.packageName != packageName && permissionName in it.androidPackage!!.requestedPermissions } if (isRequestedByOtherPackages) { return@forEach Loading Loading @@ -630,32 +632,45 @@ class AppIdPermissionPolicy : SchemePolicy() { // information about the package before OTA anyway. return } // If the app is updated, and has scoped storage permissions, then it is possible that the // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions. newState.userStates.forEachIndexed { _, userId, userState -> userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, oldFlags -> if (permissionName !in STORAGE_AND_MEDIA_PERMISSIONS || oldFlags == 0) { return@forEachReversedIndexed val oldTargetSdkVersion = reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, oldState) { targetSdkVersion, packageState -> targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) } val oldTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, oldState) val newTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, newState) val newTargetSdkVersion = reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, newState) { targetSdkVersion, packageState -> targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) } @Suppress("ConvertTwoComparisonsToRangeCheck") val isTargetSdkVersionDowngraded = oldTargetSdkVersion >= Build.VERSION_CODES.Q && newTargetSdkVersion < Build.VERSION_CODES.Q @Suppress("ConvertTwoComparisonsToRangeCheck") val isTargetSdkVersionUpgraded = oldTargetSdkVersion < Build.VERSION_CODES.Q && newTargetSdkVersion >= Build.VERSION_CODES.Q val oldIsRequestLegacyExternalStorage = anyRequestingPackageInAppId( appId, permissionName, oldState ) { it.androidPackage!!.isRequestLegacyExternalStorage } val newIsRequestLegacyExternalStorage = anyRequestingPackageInAppId( appId, permissionName, newState ) { it.androidPackage!!.isRequestLegacyExternalStorage } val oldIsRequestLegacyExternalStorage = anyPackageInAppId(appId, oldState) { it.androidPackage!!.isRequestLegacyExternalStorage } val newIsRequestLegacyExternalStorage = anyPackageInAppId(appId, newState) { it.androidPackage!!.isRequestLegacyExternalStorage } val isNewlyRequestingLegacyExternalStorage = !isTargetSdkVersionUpgraded && !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage if ((isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded) && val shouldRevokeStorageAndMediaPermissions = isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded if (shouldRevokeStorageAndMediaPermissions) { newState.userStates.forEachIndexed { _, userId, userState -> userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, oldFlags -> if (permissionName in STORAGE_AND_MEDIA_PERMISSIONS && oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED)) { Slog.v(LOG_TAG, "Revoking storage permission: $permissionName for appId: " + " $appId and user: $userId") Slog.v( LOG_TAG, "Revoking storage permission: $permissionName for appId: " + " $appId and user: $userId" ) val newFlags = oldFlags andInv ( PermissionFlags.RUNTIME_GRANTED or USER_SETTABLE_MASK ) Loading @@ -664,6 +679,7 @@ class AppIdPermissionPolicy : SchemePolicy() { } } } } private fun MutateStateScope.evaluatePermissionStateForAllPackages( permissionName: String, Loading @@ -672,8 +688,9 @@ class AppIdPermissionPolicy : SchemePolicy() { val externalState = newState.externalState externalState.userIds.forEachIndexed { _, userId -> externalState.appIdPackageNames.forEachIndexed { _, appId, _ -> val isPermissionRequested = anyRequestingPackageInAppId(appId, permissionName) { true } val isPermissionRequested = anyPackageInAppId(appId) { permissionName in it.androidPackage!!.requestedPermissions } if (isPermissionRequested) { evaluatePermissionState(appId, userId, permissionName, installedPackageState) } Loading Loading @@ -711,8 +728,21 @@ class AppIdPermissionPolicy : SchemePolicy() { installedPackageState: PackageState? ) { val packageNames = newState.externalState.appIdPackageNames[appId]!! val hasMissingPackage = packageNames.anyIndexed { _, packageName -> newState.externalState.packageStates[packageName]!!.androidPackage == null // Repeatedly checking whether a permission is requested can actually be costly, so we cache // the result for this method which is frequently called during boot, instead of calling // anyPackageInAppId() and checking requested permissions multiple times. val requestingPackageStates = MutableIndexedList<PackageState>() var hasMissingPackage = false packageNames.forEachIndexed { _, packageName -> val packageState = newState.externalState.packageStates[packageName]!! val androidPackage = packageState.androidPackage if (androidPackage != null) { if (permissionName in androidPackage.requestedPermissions) { requestingPackageStates += packageState } } else { hasMissingPackage = true } } if (packageNames.size == 1 && hasMissingPackage) { // For non-shared-user packages with missing androidPackage, skip evaluation. Loading @@ -736,8 +766,8 @@ class AppIdPermissionPolicy : SchemePolicy() { val isRequestedByInstalledPackage = installedPackageState != null && permissionName in installedPackageState.androidPackage!!.requestedPermissions val isRequestedBySystemPackage = anyRequestingPackageInAppId(appId, permissionName) { it.isSystem } val isCompatibilityPermission = anyRequestingPackageInAppId(appId, permissionName) { requestingPackageStates.anyIndexed { _, it -> it.isSystem } val isCompatibilityPermission = requestingPackageStates.anyIndexed { _, it -> isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName) } // If this is an existing, non-system package, Loading @@ -762,18 +792,15 @@ class AppIdPermissionPolicy : SchemePolicy() { // Keep the non-runtime permission grants for shared UID with missing androidPackage PermissionFlags.PROTECTION_GRANTED } else { val mayGrantByPrivileged = !permission.isPrivileged || ( anyRequestingPackageInAppId(appId, permissionName) { val mayGrantByPrivileged = !permission.isPrivileged || requestingPackageStates.anyIndexed { _, it -> checkPrivilegedPermissionAllowlist(it, permission) } ) val shouldGrantBySignature = permission.isSignature && ( anyRequestingPackageInAppId(appId, permissionName) { val shouldGrantBySignature = permission.isSignature && requestingPackageStates.anyIndexed { _, it -> shouldGrantPermissionBySignature(it, permission) } ) val shouldGrantByProtectionFlags = anyRequestingPackageInAppId(appId, permissionName) { val shouldGrantByProtectionFlags = requestingPackageStates.anyIndexed { _, it -> shouldGrantPermissionByProtectionFlags(it, permission) } if (mayGrantByPrivileged && Loading Loading @@ -805,7 +832,12 @@ class AppIdPermissionPolicy : SchemePolicy() { } else if (permission.isRuntime) { var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME val wasRevoked = newFlags != 0 && !PermissionFlags.isPermissionGranted(newFlags) if (getAppIdTargetSdkVersion(appId, permissionName) < Build.VERSION_CODES.M) { val targetSdkVersion = requestingPackageStates.reduceIndexed(Build.VERSION_CODES.CUR_DEVELOPMENT) { targetSdkVersion, _, packageState -> targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion) } if (targetSdkVersion < Build.VERSION_CODES.M) { if (permission.isRuntimeOnly) { // Different from the old implementation, which simply skips a runtime-only // permission, we now only allow holding on to the restriction related flags, Loading Loading @@ -837,7 +869,7 @@ class AppIdPermissionPolicy : SchemePolicy() { val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED) val isLeanbackNotificationsPermission = newState.externalState.isLeanback && permissionName in NOTIFICATIONS_PERMISSIONS val isImplicitPermission = anyRequestingPackageInAppId(appId, permissionName) { val isImplicitPermission = requestingPackageStates.anyIndexed { _, it -> permissionName in it.androidPackage!!.implicitPermissions } val sourcePermissions = newState.externalState Loading Loading @@ -1108,18 +1140,6 @@ class AppIdPermissionPolicy : SchemePolicy() { } } private fun MutateStateScope.getAppIdTargetSdkVersion( appId: Int, permissionName: String, state: AccessState = newState ): Int { var targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT forEachRequestingPackageInAppId(appId, permissionName, state) { targetSdkVersion = targetSdkVersion.coerceAtMost(it.androidPackage!!.targetSdkVersion) } return targetSdkVersion } private inline fun MutateStateScope.anyPackageInAppId( appId: Int, state: AccessState = newState, Loading @@ -1128,22 +1148,10 @@ class AppIdPermissionPolicy : SchemePolicy() { val packageNames = state.externalState.appIdPackageNames[appId]!! return packageNames.anyIndexed { _, packageName -> val packageState = state.externalState.packageStates[packageName]!! val androidPackage = packageState.androidPackage androidPackage != null && predicate(packageState) packageState.androidPackage != null && predicate(packageState) } } private inline fun MutateStateScope.anyRequestingPackageInAppId( appId: Int, permissionName: String, state: AccessState = newState, predicate: (PackageState) -> Boolean ): Boolean = anyPackageInAppId(appId, state) { packageState -> permissionName in packageState.androidPackage!!.requestedPermissions && predicate(packageState) } private inline fun MutateStateScope.forEachPackageInAppId( appId: Int, state: AccessState = newState, Loading @@ -1158,15 +1166,20 @@ class AppIdPermissionPolicy : SchemePolicy() { } } private inline fun MutateStateScope.forEachRequestingPackageInAppId( // Using Int instead of <T> to avoid autoboxing, since we only have the use case for Int. private inline fun MutateStateScope.reducePackageInAppId( appId: Int, permissionName: String, initialValue: Int, state: AccessState = newState, action: (PackageState) -> Unit ) { forEachPackageInAppId(appId, state) { packageState -> if (permissionName in packageState.androidPackage!!.requestedPermissions) { action(packageState) accumulator: (Int, PackageState) -> Int ): Int { val packageNames = state.externalState.appIdPackageNames[appId]!! return packageNames.reduceIndexed(initialValue) { value, _, packageName -> val packageState = state.externalState.packageStates[packageName]!! if (packageState.androidPackage != null) { accumulator(value, packageState) } else { value } } } Loading