Loading services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +1 −0 Original line number Diff line number Diff line Loading @@ -161,6 +161,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { MutateStateScope(oldState, newState).action() persistence.write(newState) state = newState with(policy) { GetStateScope(newState).onStateMutated() } } } Loading services/permission/java/com/android/server/permission/access/AccessPolicy.kt +8 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,12 @@ class AccessPolicy private constructor( } } fun GetStateScope.onStateMutated() { forEachSchemePolicy { with(it) { onStateMutated() } } } fun MutateStateScope.onUserAdded(userId: Int) { newState.systemState.userIds += userId newState.userStates[userId] = UserState() Loading Loading @@ -284,6 +290,8 @@ abstract class SchemePolicy { decision: Int ) open fun GetStateScope.onStateMutated() {} open fun MutateStateScope.onUserAdded(userId: Int) {} open fun MutateStateScope.onUserRemoved(userId: Int) {} Loading services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt +23 −2 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) { setAppOpMode(subject.packageName, subject.userId, `object`.appOpName, decision) } override fun GetStateScope.onStateMutated() { onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } } override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) { newState.userStates.forEachIndexed { _, _, userState -> userState.packageAppOpModes -= packageName Loading Loading @@ -113,13 +117,30 @@ class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) { } } fun interface OnAppOpModeChangedListener { fun onAppOpModeChanged( /** * Listener for app op mode changes. */ abstract class OnAppOpModeChangedListener { /** * Called when an app op mode change has been made to the upcoming new state. * * Implementations should keep this method fast to avoid stalling the locked state mutation, * and only call external code after [onStateMutated] when the new state has actually become * the current state visible to external code. */ abstract fun onAppOpModeChanged( packageName: String, userId: Int, appOpName: String, oldMode: Int, newMode: Int ) /** * Called when the upcoming new state has become the current state. * * Implementations should keep this method fast to avoid stalling the locked state mutation. */ abstract fun onStateMutated() } } services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt +23 −2 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) { setAppOpMode(subject.appId, subject.userId, `object`.appOpName, decision) } override fun GetStateScope.onStateMutated() { onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } } override fun MutateStateScope.onAppIdRemoved(appId: Int) { newState.userStates.forEachIndexed { _, _, userState -> userState.uidAppOpModes -= appId Loading Loading @@ -113,13 +117,30 @@ class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) { } } fun interface OnAppOpModeChangedListener { fun onAppOpModeChanged( /** * Listener for app op mode changes. */ abstract class OnAppOpModeChangedListener { /** * Called when an app op mode change has been made to the upcoming new state. * * Implementations should keep this method fast to avoid stalling the locked state mutation, * and only call external code after [onStateMutated] when the new state has actually become * the current state visible to external code. */ abstract fun onAppOpModeChanged( appId: Int, userId: Int, appOpName: String, oldMode: Int, newMode: Int ) /** * Called when the upcoming new state has become the current state. * * Implementations should keep this method fast to avoid stalling the locked state mutation. */ abstract fun onStateMutated() } } services/permission/java/com/android/server/permission/access/collection/IntBooleanMap.kt 0 → 100644 +171 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.permission.access.collection import android.util.SparseBooleanArray typealias IntBooleanMap = SparseBooleanArray inline fun IntBooleanMap.allIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { forEachIndexed { index, key, value -> if (!predicate(index, key, value)) { return false } } return true } inline fun IntBooleanMap.anyIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { forEachIndexed { index, key, value -> if (predicate(index, key, value)) { return true } } return false } @Suppress("NOTHING_TO_INLINE") inline fun IntBooleanMap.copy(): IntBooleanMap = clone() inline fun <R> IntBooleanMap.firstNotNullOfOrNullIndexed(transform: (Int, Int, Boolean) -> R): R? { forEachIndexed { index, key, value -> transform(index, key, value)?.let { return it } } return null } inline fun IntBooleanMap.forEachIndexed(action: (Int, Int, Boolean) -> Unit) { for (index in 0 until size) { action(index, keyAt(index), valueAt(index)) } } inline fun IntBooleanMap.forEachKeyIndexed(action: (Int, Int) -> Unit) { for (index in 0 until size) { action(index, keyAt(index)) } } inline fun IntBooleanMap.forEachReversedIndexed(action: (Int, Int, Boolean) -> Unit) { for (index in lastIndex downTo 0) { action(index, keyAt(index), valueAt(index)) } } inline fun IntBooleanMap.forEachValueIndexed(action: (Int, Boolean) -> Unit) { for (index in 0 until size) { action(index, valueAt(index)) } } inline fun IntBooleanMap.getOrPut(key: Int, defaultValue: () -> Boolean): Boolean { val index = indexOfKey(key) return if (index >= 0) { valueAt(index) } else { defaultValue().also { put(key, it) } } } @Suppress("NOTHING_TO_INLINE") inline fun IntBooleanMap?.getWithDefault(key: Int, defaultValue: Boolean): Boolean { this ?: return defaultValue return get(key, defaultValue) } inline val IntBooleanMap.lastIndex: Int get() = size - 1 @Suppress("NOTHING_TO_INLINE") inline operator fun IntBooleanMap.minusAssign(key: Int) { delete(key) } inline fun IntBooleanMap.noneIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { forEachIndexed { index, key, value -> if (predicate(index, key, value)) { return false } } return true } @Suppress("NOTHING_TO_INLINE") inline fun IntBooleanMap.putWithDefault(key: Int, value: Boolean, defaultValue: Boolean): Boolean { val index = indexOfKey(key) if (index >= 0) { val oldValue = valueAt(index) if (value != oldValue) { if (value == defaultValue) { removeAt(index) } else { setValueAt(index, value) } } return oldValue } else { if (value != defaultValue) { put(key, value) } return defaultValue } } fun IntBooleanMap.remove(key: Int) { delete(key) } fun IntBooleanMap.remove(key: Int, defaultValue: Boolean): Boolean { val index = indexOfKey(key) return if (index >= 0) { val oldValue = valueAt(index) removeAt(index) oldValue } else { defaultValue } } inline fun IntBooleanMap.removeAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { var isChanged = false forEachReversedIndexed { index, key, value -> if (predicate(index, key, value)) { removeAt(index) isChanged = true } } return isChanged } inline fun IntBooleanMap.retainAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { var isChanged = false forEachReversedIndexed { index, key, value -> if (!predicate(index, key, value)) { removeAt(index) isChanged = true } } return isChanged } @Suppress("NOTHING_TO_INLINE") inline operator fun IntBooleanMap.set(key: Int, value: Boolean) { put(key, value) } inline val IntBooleanMap.size: Int get() = size() Loading
services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +1 −0 Original line number Diff line number Diff line Loading @@ -161,6 +161,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { MutateStateScope(oldState, newState).action() persistence.write(newState) state = newState with(policy) { GetStateScope(newState).onStateMutated() } } } Loading
services/permission/java/com/android/server/permission/access/AccessPolicy.kt +8 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,12 @@ class AccessPolicy private constructor( } } fun GetStateScope.onStateMutated() { forEachSchemePolicy { with(it) { onStateMutated() } } } fun MutateStateScope.onUserAdded(userId: Int) { newState.systemState.userIds += userId newState.userStates[userId] = UserState() Loading Loading @@ -284,6 +290,8 @@ abstract class SchemePolicy { decision: Int ) open fun GetStateScope.onStateMutated() {} open fun MutateStateScope.onUserAdded(userId: Int) {} open fun MutateStateScope.onUserRemoved(userId: Int) {} Loading
services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt +23 −2 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) { setAppOpMode(subject.packageName, subject.userId, `object`.appOpName, decision) } override fun GetStateScope.onStateMutated() { onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } } override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) { newState.userStates.forEachIndexed { _, _, userState -> userState.packageAppOpModes -= packageName Loading Loading @@ -113,13 +117,30 @@ class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) { } } fun interface OnAppOpModeChangedListener { fun onAppOpModeChanged( /** * Listener for app op mode changes. */ abstract class OnAppOpModeChangedListener { /** * Called when an app op mode change has been made to the upcoming new state. * * Implementations should keep this method fast to avoid stalling the locked state mutation, * and only call external code after [onStateMutated] when the new state has actually become * the current state visible to external code. */ abstract fun onAppOpModeChanged( packageName: String, userId: Int, appOpName: String, oldMode: Int, newMode: Int ) /** * Called when the upcoming new state has become the current state. * * Implementations should keep this method fast to avoid stalling the locked state mutation. */ abstract fun onStateMutated() } }
services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt +23 −2 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) { setAppOpMode(subject.appId, subject.userId, `object`.appOpName, decision) } override fun GetStateScope.onStateMutated() { onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } } override fun MutateStateScope.onAppIdRemoved(appId: Int) { newState.userStates.forEachIndexed { _, _, userState -> userState.uidAppOpModes -= appId Loading Loading @@ -113,13 +117,30 @@ class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) { } } fun interface OnAppOpModeChangedListener { fun onAppOpModeChanged( /** * Listener for app op mode changes. */ abstract class OnAppOpModeChangedListener { /** * Called when an app op mode change has been made to the upcoming new state. * * Implementations should keep this method fast to avoid stalling the locked state mutation, * and only call external code after [onStateMutated] when the new state has actually become * the current state visible to external code. */ abstract fun onAppOpModeChanged( appId: Int, userId: Int, appOpName: String, oldMode: Int, newMode: Int ) /** * Called when the upcoming new state has become the current state. * * Implementations should keep this method fast to avoid stalling the locked state mutation. */ abstract fun onStateMutated() } }
services/permission/java/com/android/server/permission/access/collection/IntBooleanMap.kt 0 → 100644 +171 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.permission.access.collection import android.util.SparseBooleanArray typealias IntBooleanMap = SparseBooleanArray inline fun IntBooleanMap.allIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { forEachIndexed { index, key, value -> if (!predicate(index, key, value)) { return false } } return true } inline fun IntBooleanMap.anyIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { forEachIndexed { index, key, value -> if (predicate(index, key, value)) { return true } } return false } @Suppress("NOTHING_TO_INLINE") inline fun IntBooleanMap.copy(): IntBooleanMap = clone() inline fun <R> IntBooleanMap.firstNotNullOfOrNullIndexed(transform: (Int, Int, Boolean) -> R): R? { forEachIndexed { index, key, value -> transform(index, key, value)?.let { return it } } return null } inline fun IntBooleanMap.forEachIndexed(action: (Int, Int, Boolean) -> Unit) { for (index in 0 until size) { action(index, keyAt(index), valueAt(index)) } } inline fun IntBooleanMap.forEachKeyIndexed(action: (Int, Int) -> Unit) { for (index in 0 until size) { action(index, keyAt(index)) } } inline fun IntBooleanMap.forEachReversedIndexed(action: (Int, Int, Boolean) -> Unit) { for (index in lastIndex downTo 0) { action(index, keyAt(index), valueAt(index)) } } inline fun IntBooleanMap.forEachValueIndexed(action: (Int, Boolean) -> Unit) { for (index in 0 until size) { action(index, valueAt(index)) } } inline fun IntBooleanMap.getOrPut(key: Int, defaultValue: () -> Boolean): Boolean { val index = indexOfKey(key) return if (index >= 0) { valueAt(index) } else { defaultValue().also { put(key, it) } } } @Suppress("NOTHING_TO_INLINE") inline fun IntBooleanMap?.getWithDefault(key: Int, defaultValue: Boolean): Boolean { this ?: return defaultValue return get(key, defaultValue) } inline val IntBooleanMap.lastIndex: Int get() = size - 1 @Suppress("NOTHING_TO_INLINE") inline operator fun IntBooleanMap.minusAssign(key: Int) { delete(key) } inline fun IntBooleanMap.noneIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { forEachIndexed { index, key, value -> if (predicate(index, key, value)) { return false } } return true } @Suppress("NOTHING_TO_INLINE") inline fun IntBooleanMap.putWithDefault(key: Int, value: Boolean, defaultValue: Boolean): Boolean { val index = indexOfKey(key) if (index >= 0) { val oldValue = valueAt(index) if (value != oldValue) { if (value == defaultValue) { removeAt(index) } else { setValueAt(index, value) } } return oldValue } else { if (value != defaultValue) { put(key, value) } return defaultValue } } fun IntBooleanMap.remove(key: Int) { delete(key) } fun IntBooleanMap.remove(key: Int, defaultValue: Boolean): Boolean { val index = indexOfKey(key) return if (index >= 0) { val oldValue = valueAt(index) removeAt(index) oldValue } else { defaultValue } } inline fun IntBooleanMap.removeAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { var isChanged = false forEachReversedIndexed { index, key, value -> if (predicate(index, key, value)) { removeAt(index) isChanged = true } } return isChanged } inline fun IntBooleanMap.retainAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean { var isChanged = false forEachReversedIndexed { index, key, value -> if (!predicate(index, key, value)) { removeAt(index) isChanged = true } } return isChanged } @Suppress("NOTHING_TO_INLINE") inline operator fun IntBooleanMap.set(key: Int, value: Boolean) { put(key, value) } inline val IntBooleanMap.size: Int get() = size()