Merge changes I3aa177e5,I2d678ef2,I9c4ec4b7
* changes: Various refactors to UidPermissionPolicy code. Start AccessCheckingService in SystemServer. Make AccessCheckingService a SystemService.
This commit is contained in:
@@ -154,6 +154,7 @@ import com.android.server.os.DeviceIdentifiersPolicyService;
|
||||
import com.android.server.os.NativeTombstoneManagerService;
|
||||
import com.android.server.os.SchedulingPolicyService;
|
||||
import com.android.server.people.PeopleService;
|
||||
import com.android.server.permission.access.AccessCheckingService;
|
||||
import com.android.server.pm.ApexManager;
|
||||
import com.android.server.pm.ApexSystemServiceInfo;
|
||||
import com.android.server.pm.BackgroundInstallControlService;
|
||||
@@ -1110,6 +1111,11 @@ public final class SystemServer implements Dumpable {
|
||||
startMemtrackProxyService();
|
||||
t.traceEnd();
|
||||
|
||||
// Start AccessCheckingService which provides new implementation for permission and app op.
|
||||
t.traceBegin("StartAccessCheckingService");
|
||||
mSystemServiceManager.startService(AccessCheckingService.class);
|
||||
t.traceEnd();
|
||||
|
||||
// Activity manager runs the show.
|
||||
t.traceBegin("StartActivityManager");
|
||||
// TODO: Might need to move after migration to WM.
|
||||
|
||||
@@ -16,11 +16,23 @@
|
||||
|
||||
package com.android.server.permission.access
|
||||
|
||||
import android.content.Context
|
||||
import com.android.internal.annotations.Keep
|
||||
import com.android.server.permission.access.external.PackageState
|
||||
import com.android.server.LocalManagerRegistry
|
||||
import com.android.server.LocalServices
|
||||
import com.android.server.SystemService
|
||||
import com.android.server.appop.AppOpsCheckingServiceInterface
|
||||
import com.android.server.permission.access.appop.AppOpService
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.permission.PermissionService
|
||||
import com.android.server.pm.PackageManagerLocal
|
||||
import com.android.server.pm.UserManagerService
|
||||
import com.android.server.pm.permission.PermissionManagerServiceInterface
|
||||
import com.android.server.pm.permission.PermissionManagerServiceInternal
|
||||
import com.android.server.pm.pkg.PackageState
|
||||
|
||||
@Keep
|
||||
class AccessCheckingService {
|
||||
class AccessCheckingService(context: Context) : SystemService(context) {
|
||||
@Volatile
|
||||
private lateinit var state: AccessState
|
||||
private val stateLock = Any()
|
||||
@@ -29,14 +41,35 @@ class AccessCheckingService {
|
||||
|
||||
private val persistence = AccessPersistence(policy)
|
||||
|
||||
fun init() {
|
||||
private lateinit var appOpService: AppOpService
|
||||
private lateinit var permissionService: PermissionService
|
||||
|
||||
private lateinit var packageManagerLocal: PackageManagerLocal
|
||||
private lateinit var userManagerService: UserManagerService
|
||||
|
||||
override fun onStart() {
|
||||
appOpService = AppOpService(this)
|
||||
permissionService = PermissionService(this)
|
||||
|
||||
LocalServices.addService(AppOpsCheckingServiceInterface::class.java, appOpService)
|
||||
LocalServices.addService(PermissionManagerServiceInterface::class.java, permissionService)
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
packageManagerLocal =
|
||||
LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
|
||||
userManagerService = UserManagerService.getInstance()
|
||||
|
||||
val userIds = IntSet(userManagerService.userIdsIncludingPreCreated)
|
||||
val packageStates = packageManagerLocal.packageStates
|
||||
|
||||
val state = AccessState()
|
||||
state.systemState.userIds.apply {
|
||||
// TODO: Get and add all user IDs.
|
||||
// TODO: Maybe get and add all packages?
|
||||
}
|
||||
policy.initialize(state, userIds, packageStates)
|
||||
persistence.read(state)
|
||||
this.state = state
|
||||
|
||||
appOpService.initialize()
|
||||
permissionService.initialize()
|
||||
}
|
||||
|
||||
fun getDecision(subject: AccessUri, `object`: AccessUri): Int =
|
||||
@@ -50,30 +83,60 @@ class AccessCheckingService {
|
||||
}
|
||||
}
|
||||
|
||||
fun onUserAdded(userId: Int) {
|
||||
internal fun onUserAdded(userId: Int) {
|
||||
mutateState {
|
||||
with(policy) { onUserAdded(userId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun onUserRemoved(userId: Int) {
|
||||
internal fun onUserRemoved(userId: Int) {
|
||||
mutateState {
|
||||
with(policy) { onUserRemoved(userId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun onPackageAdded(packageState: PackageState) {
|
||||
internal fun onStorageVolumeMounted(volumeUuid: String?, isSystemUpdated: Boolean) {
|
||||
val packageStates = packageManagerLocal.packageStates
|
||||
mutateState {
|
||||
with(policy) { onPackageAdded(packageState) }
|
||||
with(policy) { onStorageVolumeMounted(packageStates, volumeUuid, isSystemUpdated) }
|
||||
}
|
||||
}
|
||||
|
||||
fun onPackageRemoved(packageState: PackageState) {
|
||||
internal fun onPackageAdded(packageName: String) {
|
||||
val packageStates = packageManagerLocal.packageStates
|
||||
mutateState {
|
||||
with(policy) { onPackageRemoved(packageState) }
|
||||
with(policy) { onPackageAdded(packageStates, packageName) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun onPackageRemoved(packageName: String, appId: Int) {
|
||||
val packageStates = packageManagerLocal.packageStates
|
||||
mutateState {
|
||||
with(policy) { onPackageRemoved(packageStates, packageName, appId) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun onPackageInstalled(
|
||||
packageName: String,
|
||||
params: PermissionManagerServiceInternal.PackageInstalledParams,
|
||||
userId: Int
|
||||
) {
|
||||
val packageStates = packageManagerLocal.packageStates
|
||||
mutateState {
|
||||
with(policy) { onPackageInstalled(packageStates, packageName, params, userId) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) {
|
||||
val packageStates = packageManagerLocal.packageStates
|
||||
mutateState {
|
||||
with(policy) { onPackageUninstalled(packageStates, packageName, appId, userId) }
|
||||
}
|
||||
}
|
||||
|
||||
private val PackageManagerLocal.packageStates: Map<String, PackageState>
|
||||
get() = withUnfilteredSnapshot().use { it.packageStates }
|
||||
|
||||
internal inline fun <T> getState(action: GetStateScope.() -> T): T =
|
||||
GetStateScope(state).action()
|
||||
|
||||
|
||||
@@ -22,11 +22,12 @@ import com.android.modules.utils.BinaryXmlSerializer
|
||||
import com.android.server.permission.access.appop.PackageAppOpPolicy
|
||||
import com.android.server.permission.access.appop.UidAppOpPolicy
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.external.PackageState
|
||||
import com.android.server.permission.access.permission.UidPermissionPolicy
|
||||
import com.android.server.permission.access.util.forEachTag
|
||||
import com.android.server.permission.access.util.tag
|
||||
import com.android.server.permission.access.util.tagName
|
||||
import com.android.server.pm.permission.PermissionManagerServiceInternal
|
||||
import com.android.server.pm.pkg.PackageState
|
||||
|
||||
class AccessPolicy private constructor(
|
||||
private val schemePolicies: IndexedMap<String, IndexedMap<String, SchemePolicy>>
|
||||
@@ -53,6 +54,17 @@ class AccessPolicy private constructor(
|
||||
with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) }
|
||||
}
|
||||
|
||||
fun initialize(state: AccessState, userIds: IntSet, packageStates: Map<String, PackageState>) {
|
||||
state.systemState.apply {
|
||||
this.userIds += userIds
|
||||
this.packageStates = packageStates
|
||||
packageStates.forEach { (_, packageState) ->
|
||||
appIds.getOrPut(packageState.appId) { IndexedListSet() }
|
||||
.add(packageState.packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun MutateStateScope.onUserAdded(userId: Int) {
|
||||
newState.systemState.userIds += userId
|
||||
newState.userStates[userId] = UserState()
|
||||
@@ -69,18 +81,34 @@ class AccessPolicy private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun MutateStateScope.onPackageAdded(packageState: PackageState) {
|
||||
var isAppIdAdded = false
|
||||
newState.systemState.apply {
|
||||
packageStates[packageState.packageName] = packageState
|
||||
appIds.getOrPut(packageState.appId) {
|
||||
isAppIdAdded = true
|
||||
IndexedListSet()
|
||||
}.add(packageState.packageName)
|
||||
fun MutateStateScope.onStorageVolumeMounted(
|
||||
packageStates: Map<String, PackageState>,
|
||||
volumeUuid: String?,
|
||||
isSystemUpdated: Boolean
|
||||
) {
|
||||
newState.systemState.packageStates = packageStates
|
||||
forEachSchemePolicy {
|
||||
with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) }
|
||||
}
|
||||
}
|
||||
|
||||
fun MutateStateScope.onPackageAdded(
|
||||
packageStates: Map<String, PackageState>,
|
||||
packageName: String
|
||||
) {
|
||||
newState.systemState.packageStates = packageStates
|
||||
var isAppIdAdded = false
|
||||
val packageState = packageStates[packageName]
|
||||
// TODO(zhanghai): Remove check before submission.
|
||||
checkNotNull(packageState)
|
||||
val appId = packageState.appId
|
||||
newState.systemState.appIds.getOrPut(appId) {
|
||||
isAppIdAdded = true
|
||||
IndexedListSet()
|
||||
}.add(packageName)
|
||||
if (isAppIdAdded) {
|
||||
forEachSchemePolicy {
|
||||
with(it) { onAppIdAdded(packageState.appId) }
|
||||
with(it) { onAppIdAdded(appId) }
|
||||
}
|
||||
}
|
||||
forEachSchemePolicy {
|
||||
@@ -88,30 +116,61 @@ class AccessPolicy private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun MutateStateScope.onPackageRemoved(packageState: PackageState) {
|
||||
fun MutateStateScope.onPackageRemoved(
|
||||
packageStates: Map<String, PackageState>,
|
||||
packageName: String,
|
||||
appId: Int
|
||||
) {
|
||||
newState.systemState.packageStates = packageStates
|
||||
var isAppIdRemoved = false
|
||||
newState.systemState.apply {
|
||||
packageStates -= packageState.packageName
|
||||
appIds.apply appIds@{
|
||||
this[packageState.appId]?.apply {
|
||||
this -= packageState.packageName
|
||||
if (isEmpty()) {
|
||||
this@appIds -= packageState.appId
|
||||
isAppIdRemoved = true
|
||||
}
|
||||
// TODO(zhanghai): Remove check before submission.
|
||||
check(packageName !in packageStates)
|
||||
newState.systemState.appIds.apply appIds@{
|
||||
this[appId]?.apply {
|
||||
this -= packageName
|
||||
if (isEmpty()) {
|
||||
this@appIds -= appId
|
||||
isAppIdRemoved = true
|
||||
}
|
||||
}
|
||||
}
|
||||
forEachSchemePolicy {
|
||||
with(it) { onPackageRemoved(packageState) }
|
||||
with(it) { onPackageRemoved(packageName, appId) }
|
||||
}
|
||||
if (isAppIdRemoved) {
|
||||
forEachSchemePolicy {
|
||||
with(it) { onAppIdRemoved(packageState.appId) }
|
||||
with(it) { onAppIdRemoved(appId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun MutateStateScope.onPackageInstalled(
|
||||
packageStates: Map<String, PackageState>,
|
||||
packageName: String,
|
||||
params: PermissionManagerServiceInternal.PackageInstalledParams,
|
||||
userId: Int
|
||||
) {
|
||||
newState.systemState.packageStates = packageStates
|
||||
val packageState = packageStates[packageName]
|
||||
// TODO(zhanghai): Remove check before submission.
|
||||
checkNotNull(packageState)
|
||||
forEachSchemePolicy {
|
||||
with(it) { onPackageInstalled(packageState, params, userId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun MutateStateScope.onPackageUninstalled(
|
||||
packageStates: Map<String, PackageState>,
|
||||
packageName: String,
|
||||
appId: Int,
|
||||
userId: Int
|
||||
) {
|
||||
newState.systemState.packageStates = packageStates
|
||||
forEachSchemePolicy {
|
||||
with(it) { onPackageUninstalled(packageName, appId, userId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun BinaryXmlPullParser.parseSystemState(systemState: SystemState) {
|
||||
forEachTag {
|
||||
when (tagName) {
|
||||
@@ -230,9 +289,22 @@ abstract class SchemePolicy {
|
||||
|
||||
open fun MutateStateScope.onAppIdRemoved(appId: Int) {}
|
||||
|
||||
open fun MutateStateScope.onStorageVolumeMounted(
|
||||
volumeUuid: String?,
|
||||
isSystemUpdated: Boolean
|
||||
) {}
|
||||
|
||||
open fun MutateStateScope.onPackageAdded(packageState: PackageState) {}
|
||||
|
||||
open fun MutateStateScope.onPackageRemoved(packageState: PackageState) {}
|
||||
open fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {}
|
||||
|
||||
open fun MutateStateScope.onPackageInstalled(
|
||||
packageState: PackageState,
|
||||
params: PermissionManagerServiceInternal.PackageInstalledParams,
|
||||
userId: Int
|
||||
) {}
|
||||
|
||||
open fun MutateStateScope.onPackageUninstalled(packageName: String, appId: Int, userId: Int) {}
|
||||
|
||||
open fun BinaryXmlPullParser.parseSystemState(systemState: SystemState) {}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.android.server.permission.access
|
||||
|
||||
import android.content.pm.PermissionGroupInfo
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.data.Permission
|
||||
import com.android.server.permission.access.external.PackageState
|
||||
import com.android.server.permission.access.permission.Permission
|
||||
import com.android.server.pm.pkg.PackageState
|
||||
|
||||
class AccessState private constructor(
|
||||
val systemState: SystemState,
|
||||
@@ -32,8 +32,8 @@ class AccessState private constructor(
|
||||
|
||||
class SystemState private constructor(
|
||||
val userIds: IntSet,
|
||||
val packageStates: IndexedMap<String, PackageState>,
|
||||
val disabledSystemPackageStates: IndexedMap<String, PackageState>,
|
||||
var packageStates: Map<String, PackageState>,
|
||||
var disabledSystemPackageStates: Map<String, PackageState>,
|
||||
val appIds: IntMap<IndexedListSet<String>>,
|
||||
// A map of KnownPackagesInt to a set of known package names
|
||||
val knownPackages: IntMap<IndexedListSet<String>>,
|
||||
@@ -59,7 +59,7 @@ class SystemState private constructor(
|
||||
val permissions: IndexedMap<String, Permission>
|
||||
) : WritableState() {
|
||||
constructor() : this(
|
||||
IntSet(), IndexedMap(), IndexedMap(), IntMap(), IntMap(), IntMap(), IndexedMap(),
|
||||
IntSet(), emptyMap(), emptyMap(), IntMap(), IntMap(), IntMap(), IndexedMap(),
|
||||
IndexedListSet(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(),
|
||||
IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(),
|
||||
IndexedMap(), IndexedMap(), IndexedMap()
|
||||
@@ -68,8 +68,8 @@ class SystemState private constructor(
|
||||
fun copy(): SystemState =
|
||||
SystemState(
|
||||
userIds.copy(),
|
||||
packageStates.copy { it },
|
||||
disabledSystemPackageStates.copy { it },
|
||||
packageStates,
|
||||
disabledSystemPackageStates,
|
||||
appIds.copy { it.copy() },
|
||||
knownPackages.copy { it.copy() },
|
||||
deviceAndProfileOwners.copy { it },
|
||||
@@ -94,14 +94,17 @@ class SystemState private constructor(
|
||||
|
||||
class UserState private constructor(
|
||||
// A map of (appId to a map of (permissionName to permissionFlags))
|
||||
val permissionFlags: IntMap<IndexedMap<String, Int>>,
|
||||
val uidPermissionFlags: IntMap<IndexedMap<String, Int>>,
|
||||
val uidAppOpModes: IntMap<IndexedMap<String, Int>>,
|
||||
val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>>
|
||||
) : WritableState() {
|
||||
constructor() : this(IntMap(), IntMap(), IndexedMap())
|
||||
|
||||
fun copy(): UserState = UserState(permissionFlags.copy { it.copy { it } },
|
||||
uidAppOpModes.copy { it.copy { it } }, packageAppOpModes.copy { it.copy { it } })
|
||||
fun copy(): UserState = UserState(
|
||||
uidPermissionFlags.copy { it.copy { it } },
|
||||
uidAppOpModes.copy { it.copy { it } },
|
||||
packageAppOpModes.copy { it.copy { it } }
|
||||
)
|
||||
}
|
||||
|
||||
object WriteMode {
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
package com.android.server.permission.access
|
||||
|
||||
import com.android.server.permission.access.external.UserHandle
|
||||
import com.android.server.permission.access.external.UserHandleCompat
|
||||
import android.os.UserHandle
|
||||
|
||||
sealed class AccessUri(
|
||||
val scheme: String
|
||||
@@ -70,7 +69,7 @@ data class UidUri(
|
||||
val uid: Int
|
||||
) : AccessUri(SCHEME) {
|
||||
val userId: Int
|
||||
get() = UserHandleCompat.getUserId(uid)
|
||||
get() = UserHandle.getUserId(uid)
|
||||
|
||||
val appId: Int
|
||||
get() = UserHandle.getAppId(uid)
|
||||
|
||||
@@ -24,9 +24,13 @@ import com.android.server.appop.OnOpModeChangedListener
|
||||
import com.android.server.permission.access.AccessCheckingService
|
||||
import java.io.PrintWriter
|
||||
|
||||
class AppOpsCheckingServiceCompatImpl(
|
||||
private val accessCheckingService: AccessCheckingService
|
||||
class AppOpService(
|
||||
private val service: AccessCheckingService
|
||||
) : AppOpsCheckingServiceInterface {
|
||||
fun initialize() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getNonDefaultUidModes(uid: Int): SparseIntArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
@@ -139,6 +143,6 @@ class AppOpsCheckingServiceCompatImpl(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG_TAG = AppOpsCheckingServiceCompatImpl::class.java.simpleName
|
||||
private val LOG_TAG = AppOpService::class.java.simpleName
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import com.android.server.permission.access.MutateStateScope
|
||||
import com.android.server.permission.access.PackageUri
|
||||
import com.android.server.permission.access.UserState
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.external.PackageState
|
||||
|
||||
class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) {
|
||||
override val subjectScheme: String
|
||||
@@ -48,9 +47,9 @@ class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) {
|
||||
newState.userStates[subject.userId]?.packageAppOpModes?.remove(subject.packageName)
|
||||
}
|
||||
|
||||
override fun MutateStateScope.onPackageRemoved(packageState: PackageState) {
|
||||
override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {
|
||||
newState.userStates.forEachIndexed { _, _, userState ->
|
||||
userState.packageAppOpModes -= packageState.packageName
|
||||
userState.packageAppOpModes -= packageName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,18 +72,24 @@ inline operator fun <T> IndexedList<T>.plusAssign(element: T) {
|
||||
add(element)
|
||||
}
|
||||
|
||||
inline fun <T> IndexedList<T>.removeAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> IndexedList<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, this[index])) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun <T> IndexedList<T>.retainAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> IndexedList<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, this[index])) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
@@ -123,18 +123,24 @@ inline operator fun <T> IndexedListSet<T>.plusAssign(element: T) {
|
||||
add(element)
|
||||
}
|
||||
|
||||
inline fun <T> IndexedListSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> IndexedListSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, elementAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun <T> IndexedListSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> IndexedListSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, elementAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
@@ -111,20 +111,26 @@ inline fun <K, V> IndexedMap<K, V>.putWithDefault(key: K, value: V, defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <K, V> IndexedMap<K, V>.removeAllIndexed(predicate: (Int, K, V) -> Boolean) {
|
||||
inline fun <K, V> IndexedMap<K, V>.removeAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, keyAt(index), valueAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun <K, V> IndexedMap<K, V>.retainAllIndexed(predicate: (Int, K, V) -> Boolean) {
|
||||
inline fun <K, V> IndexedMap<K, V>.retainAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, keyAt(index), valueAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
@@ -80,20 +80,26 @@ inline operator fun <T> IndexedSet<T>.plusAssign(element: T) {
|
||||
add(element)
|
||||
}
|
||||
|
||||
inline fun <T> IndexedSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> IndexedSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, elementAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun <T> IndexedSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> IndexedSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, elementAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
@@ -120,20 +120,26 @@ inline fun <T> IntMap<T>.putWithDefault(key: Int, value: T, defaultValue: T): T
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T> IntMap<T>.removeAllIndexed(predicate: (Int, Int, T) -> Boolean) {
|
||||
inline fun <T> IntMap<T>.removeAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, keyAt(index), valueAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun <T> IntMap<T>.retainAllIndexed(predicate: (Int, Int, T) -> Boolean) {
|
||||
inline fun <T> IntMap<T>.retainAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, keyAt(index), valueAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline val <T> IntMap<T>.size: Int
|
||||
|
||||
@@ -51,6 +51,8 @@ class IntSet private constructor(
|
||||
fun copy(): IntSet = IntSet(array.clone())
|
||||
}
|
||||
|
||||
fun IntSet(values: IntArray): IntSet = IntSet().apply{ this += values }
|
||||
|
||||
inline fun IntSet.allIndexed(predicate: (Int, Int) -> Boolean): Boolean {
|
||||
for (index in 0 until size) {
|
||||
if (!predicate(index, elementAt(index))) {
|
||||
@@ -103,18 +105,32 @@ inline operator fun IntSet.plusAssign(element: Int) {
|
||||
add(element)
|
||||
}
|
||||
|
||||
inline fun IntSet.removeAllIndexed(predicate: (Int, Int) -> Boolean) {
|
||||
operator fun IntSet.plusAssign(set: IntSet) {
|
||||
set.forEachIndexed { _, it -> this += it }
|
||||
}
|
||||
|
||||
operator fun IntSet.plusAssign(array: IntArray) {
|
||||
array.forEach { this += it }
|
||||
}
|
||||
|
||||
inline fun IntSet.removeAllIndexed(predicate: (Int, Int) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, elementAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun IntSet.retainAllIndexed(predicate: (Int, Int) -> Boolean) {
|
||||
inline fun IntSet.retainAllIndexed(predicate: (Int, Int) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, elementAt(index))) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
@@ -49,18 +49,24 @@ inline fun <T> List<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
inline fun <T> MutableList<T>.removeAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> MutableList<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (predicate(index, this[index])) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
inline fun <T> MutableList<T>.retainAllIndexed(predicate: (Int, T) -> Boolean) {
|
||||
inline fun <T> MutableList<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
|
||||
var isChanged = false
|
||||
for (index in lastIndex downTo 0) {
|
||||
if (!predicate(index, this[index])) {
|
||||
removeAt(index)
|
||||
isChanged = true
|
||||
}
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.data
|
||||
|
||||
import com.android.server.permission.access.external.AndroidPackage
|
||||
|
||||
class Package(
|
||||
private val androidPackage: AndroidPackage
|
||||
) {
|
||||
val name: String
|
||||
get() = androidPackage.packageName
|
||||
|
||||
val adoptPermissions: List<String>
|
||||
get() = androidPackage.adoptPermissions
|
||||
|
||||
val appId: Int
|
||||
get() = androidPackage.appId
|
||||
|
||||
val requestedPermissions: List<String>
|
||||
get() = androidPackage.requestedPermissions
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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.external
|
||||
|
||||
class CompatibilityPermissionInfo {
|
||||
companion object {
|
||||
val COMPAT_PERMS = arrayOf(CompatibilityPermissionInfo())
|
||||
}
|
||||
|
||||
val name: String
|
||||
get() = throw NotImplementedError()
|
||||
|
||||
val sdkVersion: Int
|
||||
get() = throw NotImplementedError()
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.external
|
||||
|
||||
class KnownPackages {
|
||||
companion object {
|
||||
const val PACKAGE_SYSTEM = 0
|
||||
const val PACKAGE_SETUP_WIZARD = 1
|
||||
const val PACKAGE_INSTALLER = 2
|
||||
const val PACKAGE_VERIFIER = 4
|
||||
const val PACKAGE_SYSTEM_TEXT_CLASSIFIER = 6
|
||||
const val PACKAGE_PERMISSION_CONTROLLER = 7
|
||||
const val PACKAGE_CONFIGURATOR = 10
|
||||
const val PACKAGE_INCIDENT_REPORT_APPROVER = 11
|
||||
const val PACKAGE_APP_PREDICTOR = 12
|
||||
const val PACKAGE_COMPANION = 15
|
||||
const val PACKAGE_RETAIL_DEMO = 16
|
||||
const val PACKAGE_RECENTS = 17
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.external
|
||||
|
||||
import android.content.pm.PermissionGroupInfo
|
||||
import android.content.pm.PermissionInfo
|
||||
|
||||
object PackageInfoUtils {
|
||||
fun generatePermissionInfo(parsedPermission: ParsedPermission, flags: Long): PermissionInfo {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
fun generatePermissionGroupInfo(
|
||||
parsedPermissionGroup: ParsedPermissionGroup,
|
||||
flags: Long
|
||||
): PermissionGroupInfo {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.external
|
||||
|
||||
import android.util.SparseArray
|
||||
|
||||
interface PackageState {
|
||||
val androidPackage: AndroidPackage?
|
||||
val appId: Int
|
||||
val isSystem: Boolean
|
||||
val isUpdatedSystemApp: Boolean
|
||||
val packageName: String
|
||||
val userStates: SparseArray<PackageUserState>
|
||||
val hasSharedUser: Boolean
|
||||
val sharedUserAppId: Int
|
||||
val signingDetails: SigningDetails
|
||||
}
|
||||
|
||||
interface AndroidPackage {
|
||||
val packageName: String
|
||||
val apexModuleName: String?
|
||||
val appId: Int
|
||||
val isPrivileged: Boolean
|
||||
val isOem: Boolean
|
||||
val isVendor: Boolean
|
||||
val isProduct: Boolean
|
||||
val isSystemExt: Boolean
|
||||
val targetSdkVersion: Int
|
||||
val adoptPermissions: List<String>
|
||||
val permissions: List<ParsedPermission>
|
||||
val permissionGroups: List<ParsedPermissionGroup>
|
||||
val requestedPermissions: List<String>
|
||||
val implicitPermissions: List<String>
|
||||
}
|
||||
|
||||
interface ParsedPermission {
|
||||
val name: String
|
||||
val isTree: Boolean
|
||||
val packageName: String
|
||||
val isSignature: Boolean
|
||||
val protectionLevel: Int
|
||||
}
|
||||
|
||||
interface ParsedPermissionGroup {
|
||||
val name: String
|
||||
val packageName: String
|
||||
}
|
||||
|
||||
interface PackageUserState {
|
||||
val isInstantApp: Boolean
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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.external
|
||||
|
||||
class RoSystemProperties {
|
||||
companion object {
|
||||
const val CONTROL_PRIVAPP_PERMISSIONS_DISABLE = false
|
||||
const val CONTROL_PRIVAPP_PERMISSIONS_ENFORCE = false
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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.external
|
||||
|
||||
object SigningDetails {
|
||||
fun hasCommonSignerWithCapability(otherDetails: SigningDetails, flags: Int): Boolean {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
fun hasAncestorOrSelf(oldDetails: SigningDetails): Boolean {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
fun checkCapability(oldDetails: SigningDetails, flags: Int): Boolean {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
fun hasAncestorOrSelfWithDigest(certDigests: Set<String>): Boolean {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
class CertCapabilities {
|
||||
companion object {
|
||||
/** grant SIGNATURE permissions to pkgs with this cert */
|
||||
var PERMISSION = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.external
|
||||
|
||||
interface UserHandle {
|
||||
companion object {
|
||||
fun getAppId(uid: Int): Int {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object UserHandleCompat {
|
||||
fun getUserId(uid: Int): Int {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.permission.access.data
|
||||
package com.android.server.permission.access.permission
|
||||
|
||||
import android.content.pm.PermissionInfo
|
||||
import com.android.server.permission.access.util.hasBits
|
||||
@@ -27,6 +27,7 @@ object PermissionFlags {
|
||||
// For the permissions that are implicit for the package
|
||||
const val IMPLICIT = 1 shl 5
|
||||
|
||||
const val MASK_ALL = 0.inv()
|
||||
const val MASK_GRANTED = INSTALL_GRANTED or PROTECTION_GRANTED or OTHER_GRANTED or ROLE_GRANTED
|
||||
const val MASK_RUNTIME = OTHER_GRANTED or IMPLICIT
|
||||
}
|
||||
|
||||
@@ -33,8 +33,9 @@ import com.android.server.pm.permission.PermissionManagerServiceInterface
|
||||
import com.android.server.permission.access.AccessCheckingService
|
||||
import com.android.server.permission.access.PermissionUri
|
||||
import com.android.server.permission.access.UidUri
|
||||
import com.android.server.permission.access.data.Permission
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.util.hasBits
|
||||
import com.android.server.pm.UserManagerService
|
||||
import com.android.server.pm.permission.LegacyPermission
|
||||
import com.android.server.pm.permission.LegacyPermissionSettings
|
||||
import com.android.server.pm.permission.LegacyPermissionState
|
||||
@@ -46,17 +47,24 @@ import java.io.PrintWriter
|
||||
/**
|
||||
* Modern implementation of [PermissionManagerServiceInterface].
|
||||
*/
|
||||
class ModernPermissionManagerServiceImpl(
|
||||
class PermissionService(
|
||||
private val service: AccessCheckingService
|
||||
) : PermissionManagerServiceInterface {
|
||||
private val policy =
|
||||
service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy
|
||||
|
||||
private val packageManagerInternal =
|
||||
LocalServices.getService(PackageManagerInternal::class.java)
|
||||
private lateinit var packageManagerInternal: PackageManagerInternal
|
||||
private lateinit var packageManagerLocal: PackageManagerLocal
|
||||
private lateinit var userManagerService: UserManagerService
|
||||
|
||||
private val packageManagerLocal =
|
||||
LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
|
||||
private val mountedStorageVolumes = IndexedSet<String?>()
|
||||
|
||||
fun initialize() {
|
||||
packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java)
|
||||
packageManagerLocal =
|
||||
LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
|
||||
userManagerService = UserManagerService.getInstance()
|
||||
}
|
||||
|
||||
override fun getAllPermissionGroups(flags: Int): List<PermissionGroupInfo> {
|
||||
TODO("Not yet implemented")
|
||||
@@ -351,6 +359,8 @@ class ModernPermissionManagerServiceImpl(
|
||||
}
|
||||
|
||||
override fun readLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
|
||||
// Package settings has been read when this method is called.
|
||||
service.initialize()
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@@ -375,15 +385,18 @@ class ModernPermissionManagerServiceImpl(
|
||||
}
|
||||
|
||||
override fun onUserCreated(userId: Int) {
|
||||
TODO("Not yet implemented")
|
||||
service.onUserAdded(userId)
|
||||
}
|
||||
|
||||
override fun onUserRemoved(userId: Int) {
|
||||
TODO("Not yet implemented")
|
||||
service.onUserRemoved(userId)
|
||||
}
|
||||
|
||||
override fun onStorageVolumeMounted(volumeUuid: String, fingerprintChanged: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
service.onStorageVolumeMounted(volumeUuid, fingerprintChanged)
|
||||
synchronized(mountedStorageVolumes) {
|
||||
mountedStorageVolumes += volumeUuid
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPackageAdded(
|
||||
@@ -391,7 +404,18 @@ class ModernPermissionManagerServiceImpl(
|
||||
isInstantApp: Boolean,
|
||||
oldPackage: AndroidPackage?
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
synchronized(mountedStorageVolumes) {
|
||||
if (androidPackage.volumeUuid !in mountedStorageVolumes) {
|
||||
// Wait for the storage volume to be mounted and batch the state mutation there.
|
||||
return
|
||||
}
|
||||
}
|
||||
service.onPackageAdded(androidPackage.packageName)
|
||||
}
|
||||
|
||||
override fun onPackageRemoved(androidPackage: AndroidPackage) {
|
||||
// This may not be a full removal so ignored - we'll figure out full removal in
|
||||
// onPackageUninstalled().
|
||||
}
|
||||
|
||||
override fun onPackageInstalled(
|
||||
@@ -400,21 +424,37 @@ class ModernPermissionManagerServiceImpl(
|
||||
params: PermissionManagerServiceInternal.PackageInstalledParams,
|
||||
userId: Int
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
synchronized(mountedStorageVolumes) {
|
||||
if (androidPackage.volumeUuid !in mountedStorageVolumes) {
|
||||
// Wait for the storage volume to be mounted and batch the state mutation there.
|
||||
return
|
||||
}
|
||||
}
|
||||
val userIds = if (userId == UserHandle.USER_ALL) {
|
||||
userManagerService.userIdsIncludingPreCreated
|
||||
} else {
|
||||
intArrayOf(userId)
|
||||
}
|
||||
userIds.forEach { service.onPackageInstalled(androidPackage.packageName, params, it) }
|
||||
}
|
||||
|
||||
override fun onPackageUninstalled(
|
||||
packageName: String,
|
||||
appId: Int,
|
||||
androidPackage: AndroidPackage?,
|
||||
sharedUserPkgs: MutableList<AndroidPackage>,
|
||||
sharedUserPkgs: List<AndroidPackage>,
|
||||
userId: Int
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onPackageRemoved(androidPackage: AndroidPackage) {
|
||||
TODO("Not yet implemented")
|
||||
val userIds = if (userId == UserHandle.USER_ALL) {
|
||||
userManagerService.userIdsIncludingPreCreated
|
||||
} else {
|
||||
intArrayOf(userId)
|
||||
}
|
||||
userIds.forEach { service.onPackageUninstalled(packageName, appId, it) }
|
||||
val packageState = packageManagerInternal.packageStates[packageName]
|
||||
if (packageState == null) {
|
||||
service.onPackageRemoved(packageName, appId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,7 +22,6 @@ import com.android.modules.utils.BinaryXmlPullParser
|
||||
import com.android.modules.utils.BinaryXmlSerializer
|
||||
import com.android.server.permission.access.SystemState
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.data.Permission
|
||||
import com.android.server.permission.access.util.attribute
|
||||
import com.android.server.permission.access.util.attributeInt
|
||||
import com.android.server.permission.access.util.attributeIntHex
|
||||
|
||||
@@ -20,9 +20,11 @@ import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PermissionGroupInfo
|
||||
import android.content.pm.PermissionInfo
|
||||
import android.content.pm.SigningDetails
|
||||
import android.os.Build
|
||||
import android.os.UserHandle
|
||||
import android.util.Log
|
||||
import com.android.internal.os.RoSystemProperties
|
||||
import com.android.modules.utils.BinaryXmlPullParser
|
||||
import com.android.modules.utils.BinaryXmlSerializer
|
||||
import com.android.server.permission.access.AccessState
|
||||
@@ -33,22 +35,24 @@ import com.android.server.permission.access.PermissionUri
|
||||
import com.android.server.permission.access.SchemePolicy
|
||||
import com.android.server.permission.access.SystemState
|
||||
import com.android.server.permission.access.UidUri
|
||||
import com.android.server.permission.access.UserState
|
||||
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
|
||||
import com.android.server.permission.access.data.Permission
|
||||
import com.android.server.permission.access.external.AndroidPackage
|
||||
import com.android.server.permission.access.external.CompatibilityPermissionInfo
|
||||
import com.android.server.permission.access.external.KnownPackages
|
||||
import com.android.server.permission.access.external.PackageInfoUtils
|
||||
import com.android.server.permission.access.external.PackageState
|
||||
import com.android.server.permission.access.external.RoSystemProperties
|
||||
import com.android.server.permission.access.external.SigningDetails
|
||||
import com.android.server.permission.access.util.andInv
|
||||
import com.android.server.permission.access.util.hasAnyBit
|
||||
import com.android.server.permission.access.util.hasBits
|
||||
import com.android.server.pm.KnownPackages
|
||||
import com.android.server.pm.parsing.PackageInfoUtils
|
||||
import com.android.server.pm.permission.CompatibilityPermissionInfo
|
||||
import com.android.server.pm.pkg.AndroidPackage
|
||||
import com.android.server.pm.pkg.PackageState
|
||||
|
||||
class UidPermissionPolicy : SchemePolicy() {
|
||||
private val persistence = UidPermissionPersistence()
|
||||
|
||||
@Volatile
|
||||
private var onPermissionFlagsChangedListeners =
|
||||
IndexedListSet<OnPermissionFlagsChangedListener>()
|
||||
private val onPermissionFlagsChangedListenersLock = Any()
|
||||
|
||||
override val subjectScheme: String
|
||||
get() = UidUri.SCHEME
|
||||
|
||||
@@ -58,8 +62,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int {
|
||||
subject as UidUri
|
||||
`object` as PermissionUri
|
||||
return state.userStates[subject.userId]?.permissionFlags?.get(subject.appId)
|
||||
?.get(`object`.permissionName) ?: 0
|
||||
return getPermissionFlags(subject.appId, subject.userId, `object`.permissionName)
|
||||
}
|
||||
|
||||
override fun MutateStateScope.setDecision(
|
||||
@@ -69,26 +72,22 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
) {
|
||||
subject as UidUri
|
||||
`object` as PermissionUri
|
||||
val uidFlags = newState.userStates.getOrPut(subject.userId) { UserState() }
|
||||
.permissionFlags.getOrPut(subject.appId) { IndexedMap() }
|
||||
uidFlags[`object`.permissionName] = decision
|
||||
setPermissionFlags(subject.appId, subject.userId, `object`.permissionName, decision)
|
||||
}
|
||||
|
||||
override fun MutateStateScope.onUserAdded(userId: Int) {
|
||||
newState.systemState.packageStates.forEachValueIndexed { _, packageState ->
|
||||
evaluateAllPermissionStatesForPackageAndUser(packageState, null, userId)
|
||||
newState.systemState.packageStates.forEach { (_, packageState) ->
|
||||
evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null)
|
||||
grantImplicitPermissions(packageState, userId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun MutateStateScope.onAppIdAdded(appId: Int) {
|
||||
newState.userStates.forEachIndexed { _, _, userState ->
|
||||
userState.permissionFlags.getOrPut(appId) { IndexedMap() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun MutateStateScope.onAppIdRemoved(appId: Int) {
|
||||
newState.userStates.forEachIndexed { _, _, userState -> userState.permissionFlags -= appId }
|
||||
newState.userStates.forEachValueIndexed { _, userState ->
|
||||
userState.uidPermissionFlags -= appId
|
||||
userState.requestWrite()
|
||||
// Skip notifying the change listeners since the app ID no longer exists.
|
||||
}
|
||||
}
|
||||
|
||||
override fun MutateStateScope.onPackageAdded(packageState: PackageState) {
|
||||
@@ -97,7 +96,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
addPermissionGroups(packageState)
|
||||
addPermissions(packageState, changedPermissionNames)
|
||||
// TODO: revokeStoragePermissionsIfScopeExpandedInternal()
|
||||
trimPermissions(packageState.packageName)
|
||||
trimPermissions(packageState.packageName, changedPermissionNames)
|
||||
changedPermissionNames.forEachIndexed { _, permissionName ->
|
||||
evaluatePermissionStateForAllPackages(permissionName, packageState)
|
||||
}
|
||||
@@ -121,22 +120,23 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
if (!canAdoptPermissions(packageName, originalPackageName)) {
|
||||
return@forEachIndexed
|
||||
}
|
||||
newState.systemState.permissions.let { permissions ->
|
||||
permissions.forEachIndexed permissions@ {
|
||||
permissionIndex, permissionName, oldPermission ->
|
||||
if (oldPermission.packageName != originalPackageName) {
|
||||
return@permissions
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
val newPermissionInfo = PermissionInfo().apply {
|
||||
name = oldPermission.permissionInfo.name
|
||||
this.packageName = packageName
|
||||
protectionLevel = oldPermission.permissionInfo.protectionLevel
|
||||
}
|
||||
val newPermission = Permission(newPermissionInfo, false, oldPermission.type, 0)
|
||||
changedPermissionNames += permissionName
|
||||
permissions.setValueAt(permissionIndex, newPermission)
|
||||
val systemState = newState.systemState
|
||||
val permissions = systemState.permissions
|
||||
permissions.forEachIndexed permissions@ {
|
||||
permissionIndex, permissionName, oldPermission ->
|
||||
if (oldPermission.packageName != originalPackageName) {
|
||||
return@permissions
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
val newPermissionInfo = PermissionInfo().apply {
|
||||
name = oldPermission.permissionInfo.name
|
||||
this.packageName = packageName
|
||||
protectionLevel = oldPermission.permissionInfo.protectionLevel
|
||||
}
|
||||
val newPermission = Permission(newPermissionInfo, false, oldPermission.type, 0)
|
||||
permissions.setValueAt(permissionIndex, newPermission)
|
||||
systemState.requestWrite()
|
||||
changedPermissionNames += permissionName
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
packageState.androidPackage!!.permissionGroups.forEachIndexed { _, parsedPermissionGroup ->
|
||||
val newPermissionGroup = PackageInfoUtils.generatePermissionGroupInfo(
|
||||
parsedPermissionGroup, PackageManager.GET_META_DATA.toLong()
|
||||
)
|
||||
)!!
|
||||
// TODO: Clear permission state on group take-over?
|
||||
val permissionGroupName = newPermissionGroup.name
|
||||
val oldPermissionGroup = newState.systemState.permissionGroups[permissionGroupName]
|
||||
@@ -211,13 +211,14 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
// }
|
||||
val newPermissionInfo = PackageInfoUtils.generatePermissionInfo(
|
||||
parsedPermission, PackageManager.GET_META_DATA.toLong()
|
||||
)
|
||||
)!!
|
||||
// TODO: newPermissionInfo.flags |= PermissionInfo.FLAG_INSTALLED
|
||||
val systemState = newState.systemState
|
||||
val permissionName = newPermissionInfo.name
|
||||
val oldPermission = if (parsedPermission.isTree) {
|
||||
newState.systemState.permissionTrees[permissionName]
|
||||
systemState.permissionTrees[permissionName]
|
||||
} else {
|
||||
newState.systemState.permissions[permissionName]
|
||||
systemState.permissions[permissionName]
|
||||
}
|
||||
// Different from the old implementation, which may add an (incomplete) signature
|
||||
// permission inside another package's permission tree, we now consistently ignore such
|
||||
@@ -247,19 +248,18 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
if (oldPermission.type == Permission.TYPE_CONFIG && !oldPermission.isReconciled) {
|
||||
// It's a config permission and has no owner, take ownership now.
|
||||
Permission(newPermissionInfo, true, Permission.TYPE_CONFIG, packageState.appId)
|
||||
} else if (newState.systemState.packageStates[oldPackageName]?.isSystem != true) {
|
||||
} else if (systemState.packageStates[oldPackageName]?.isSystem != true) {
|
||||
Log.w(
|
||||
LOG_TAG, "Overriding permission $permissionName with new declaration in" +
|
||||
" system package $newPackageName: originally declared in another" +
|
||||
" package $oldPackageName"
|
||||
)
|
||||
// Remove permission state on owner change.
|
||||
newState.userStates.forEachValueIndexed { _, userState ->
|
||||
userState.permissionFlags.forEachValueIndexed { _, permissionFlags ->
|
||||
permissionFlags -= newPermissionInfo.name
|
||||
systemState.userIds.forEachIndexed { _, userId ->
|
||||
systemState.appIds.forEachKeyIndexed { _, appId ->
|
||||
setPermissionFlags(appId, userId, permissionName, 0)
|
||||
}
|
||||
}
|
||||
// TODO: Notify re-evaluation of this permission.
|
||||
Permission(
|
||||
newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId
|
||||
)
|
||||
@@ -278,23 +278,28 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
Permission(newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId)
|
||||
}
|
||||
|
||||
changedPermissionNames += permissionName
|
||||
if (parsedPermission.isTree) {
|
||||
newState.systemState.permissionTrees[permissionName] = newPermission
|
||||
systemState.permissionTrees[permissionName] = newPermission
|
||||
} else {
|
||||
newState.systemState.permissions[permissionName] = newPermission
|
||||
systemState.permissions[permissionName] = newPermission
|
||||
}
|
||||
systemState.requestWrite()
|
||||
changedPermissionNames += permissionName
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutateStateScope.trimPermissions(packageName: String) {
|
||||
val packageState = newState.systemState.packageStates[packageName]
|
||||
private fun MutateStateScope.trimPermissions(
|
||||
packageName: String,
|
||||
changedPermissionNames: IndexedSet<String>
|
||||
) {
|
||||
val systemState = newState.systemState
|
||||
val packageState = systemState.packageStates[packageName]
|
||||
val androidPackage = packageState?.androidPackage
|
||||
if (packageState != null && androidPackage == null) {
|
||||
return
|
||||
}
|
||||
|
||||
newState.systemState.permissionTrees.removeAllIndexed {
|
||||
val isPermissionTreeRemoved = systemState.permissionTrees.removeAllIndexed {
|
||||
_, permissionTreeName, permissionTree ->
|
||||
permissionTree.packageName == packageName && (
|
||||
packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
|
||||
@@ -302,26 +307,30 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
}
|
||||
)
|
||||
}
|
||||
if (isPermissionTreeRemoved) {
|
||||
systemState.requestWrite()
|
||||
}
|
||||
|
||||
newState.systemState.permissions.removeAllIndexed { i, permissionName, permission ->
|
||||
systemState.permissions.removeAllIndexed { permissionIndex, permissionName, permission ->
|
||||
val updatedPermission = updatePermissionIfDynamic(permission)
|
||||
newState.systemState.permissions.setValueAt(i, updatedPermission)
|
||||
newState.systemState.permissions.setValueAt(permissionIndex, updatedPermission)
|
||||
if (updatedPermission.packageName == packageName && (
|
||||
packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
|
||||
!it.isTree && it.name == permissionName
|
||||
}
|
||||
)) {
|
||||
if (!isPermissionDeclaredByDisabledSystemPackage(permission)) {
|
||||
newState.userStates.forEachIndexed { _, userId, userState ->
|
||||
userState.permissionFlags.forEachKeyIndexed { _, appId ->
|
||||
setPermissionFlags(
|
||||
appId, permissionName, getPermissionFlags(
|
||||
appId, permissionName, userId
|
||||
) and PermissionFlags.INSTALL_REVOKED, userId
|
||||
)
|
||||
}
|
||||
// Different from the old implementation where we keep the permission state if the
|
||||
// permission is declared by a disabled system package (ag/15189282), we now
|
||||
// shouldn't be notified when the updated system package is removed but the disabled
|
||||
// system package isn't re-enabled yet, so we don't need to maintain that brittle
|
||||
// special case either.
|
||||
systemState.userIds.forEachIndexed { _, userId ->
|
||||
systemState.appIds.forEachKeyIndexed { _, appId ->
|
||||
setPermissionFlags(appId, userId, permissionName, 0)
|
||||
}
|
||||
}
|
||||
changedPermissionNames += permissionName
|
||||
systemState.requestWrite()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -329,16 +338,6 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutateStateScope.isPermissionDeclaredByDisabledSystemPackage(
|
||||
permission: Permission
|
||||
): Boolean {
|
||||
val disabledSystemPackage = newState.systemState
|
||||
.disabledSystemPackageStates[permission.packageName]?.androidPackage ?: return false
|
||||
return disabledSystemPackage.permissions.anyIndexed { _, it ->
|
||||
it.name == permission.name && it.protectionLevel == permission.protectionLevel
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutateStateScope.updatePermissionIfDynamic(permission: Permission): Permission {
|
||||
if (!permission.isDynamic) {
|
||||
return permission
|
||||
@@ -368,11 +367,14 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
permissionName: String,
|
||||
installedPackageState: PackageState?
|
||||
) {
|
||||
newState.systemState.userIds.forEachIndexed { _, userId ->
|
||||
oldState.userStates[userId]?.permissionFlags?.forEachIndexed {
|
||||
_, appId, permissionFlags ->
|
||||
if (permissionName in permissionFlags) {
|
||||
evaluatePermissionState(appId, permissionName, installedPackageState, userId)
|
||||
val systemState = newState.systemState
|
||||
systemState.userIds.forEachIndexed { _, userId ->
|
||||
systemState.appIds.forEachKeyIndexed { _, appId ->
|
||||
val isPermissionRequested = anyPackageInAppId(appId) { packageState ->
|
||||
permissionName in packageState.androidPackage!!.requestedPermissions
|
||||
}
|
||||
if (isPermissionRequested) {
|
||||
evaluatePermissionState(appId, userId, permissionName, installedPackageState)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,28 +386,28 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
) {
|
||||
newState.systemState.userIds.forEachIndexed { _, userId ->
|
||||
evaluateAllPermissionStatesForPackageAndUser(
|
||||
packageState, installedPackageState, userId
|
||||
packageState, userId, installedPackageState
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutateStateScope.evaluateAllPermissionStatesForPackageAndUser(
|
||||
packageState: PackageState,
|
||||
installedPackageState: PackageState?,
|
||||
userId: Int
|
||||
userId: Int,
|
||||
installedPackageState: PackageState?
|
||||
) {
|
||||
packageState.androidPackage?.requestedPermissions?.forEachIndexed { _, permissionName ->
|
||||
evaluatePermissionState(
|
||||
packageState.appId, permissionName, installedPackageState, userId
|
||||
packageState.appId, userId, permissionName, installedPackageState
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutateStateScope.evaluatePermissionState(
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String,
|
||||
installedPackageState: PackageState?,
|
||||
userId: Int
|
||||
installedPackageState: PackageState?
|
||||
) {
|
||||
val packageNames = newState.systemState.appIds[appId]
|
||||
val hasMissingPackage = packageNames.anyIndexed { _, packageName ->
|
||||
@@ -416,7 +418,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
return
|
||||
}
|
||||
val permission = newState.systemState.permissions[permissionName] ?: return
|
||||
val oldFlags = getPermissionFlags(appId, permissionName, userId)
|
||||
val oldFlags = getPermissionFlags(appId, userId, permissionName)
|
||||
if (permission.isNormal) {
|
||||
val wasGranted = oldFlags.hasBits(PermissionFlags.INSTALL_GRANTED)
|
||||
if (!wasGranted) {
|
||||
@@ -438,7 +440,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
} else {
|
||||
PermissionFlags.INSTALL_REVOKED
|
||||
}
|
||||
setPermissionFlags(appId, permissionName, newFlags, userId)
|
||||
setPermissionFlags(appId, userId, permissionName, newFlags)
|
||||
}
|
||||
} else if (permission.isSignature || permission.isInternal) {
|
||||
val wasProtectionGranted = oldFlags.hasBits(PermissionFlags.PROTECTION_GRANTED)
|
||||
@@ -477,7 +479,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
if (permission.isRole) {
|
||||
newFlags = newFlags or (oldFlags and PermissionFlags.ROLE_GRANTED)
|
||||
}
|
||||
setPermissionFlags(appId, permissionName, newFlags, userId)
|
||||
setPermissionFlags(appId, userId, permissionName, newFlags)
|
||||
} else if (permission.isRuntime) {
|
||||
// TODO: add runtime permissions
|
||||
} else {
|
||||
@@ -503,7 +505,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
}
|
||||
// Explicitly check against the old state to determine if this permission is new.
|
||||
val isNewPermission = getPermissionFlags(
|
||||
appId, implicitPermissionName, userId, oldState
|
||||
appId, userId, implicitPermissionName, oldState
|
||||
) == 0
|
||||
if (!isNewPermission) {
|
||||
return@implicitPermissions
|
||||
@@ -516,7 +518,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
checkNotNull(sourcePermission) {
|
||||
"Unknown source permission $sourcePermissionName in split permissions"
|
||||
}
|
||||
val sourceFlags = getPermissionFlags(appId, sourcePermissionName, userId)
|
||||
val sourceFlags = getPermissionFlags(appId, userId, sourcePermissionName)
|
||||
val isSourceGranted = sourceFlags.hasAnyBit(PermissionFlags.MASK_GRANTED)
|
||||
val isNewGranted = newFlags.hasAnyBit(PermissionFlags.MASK_GRANTED)
|
||||
val isGrantingNewFromRevoke = isSourceGranted && !isNewGranted
|
||||
@@ -531,27 +533,10 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
}
|
||||
}
|
||||
newFlags = newFlags or PermissionFlags.IMPLICIT
|
||||
setPermissionFlags(appId, implicitPermissionName, newFlags, userId)
|
||||
setPermissionFlags(appId, userId, implicitPermissionName, newFlags)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutateStateScope.getPermissionFlags(
|
||||
appId: Int,
|
||||
permissionName: String,
|
||||
userId: Int,
|
||||
state: AccessState = newState
|
||||
): Int = state.userStates[userId].permissionFlags[appId].getWithDefault(permissionName, 0)
|
||||
|
||||
private fun MutateStateScope.setPermissionFlags(
|
||||
appId: Int,
|
||||
permissionName: String,
|
||||
flags: Int,
|
||||
userId: Int
|
||||
) {
|
||||
newState.userStates[userId].permissionFlags[appId]!!
|
||||
.putWithDefault(permissionName, flags, 0)
|
||||
}
|
||||
|
||||
private fun isCompatibilityPermissionForPackage(
|
||||
androidPackage: AndroidPackage,
|
||||
permissionName: String
|
||||
@@ -573,23 +558,24 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
packageState: PackageState,
|
||||
permission: Permission
|
||||
): Boolean {
|
||||
// check if the package is allow to use this signature permission. A package is allowed to
|
||||
// use a signature permission if:
|
||||
// - it has the same set of signing certificates as the source package
|
||||
// - or its signing certificate was rotated from the source package's certificate
|
||||
// - or its signing certificate is a previous signing certificate of the defining
|
||||
// package, and the defining package still trusts the old certificate for permissions
|
||||
// - or it shares a common signing certificate in its lineage with the defining package,
|
||||
// and the defining package still trusts the old certificate for permissions
|
||||
// - or it shares the above relationships with the system package
|
||||
// Check if the package is allowed to use this signature permission. A package is allowed
|
||||
// to use a signature permission if:
|
||||
// - it has the same set of signing certificates as the source package
|
||||
// - or its signing certificate was rotated from the source package's certificate
|
||||
// - or its signing certificate is a previous signing certificate of the defining
|
||||
// package, and the defining package still trusts the old certificate for permissions
|
||||
// - or it shares a common signing certificate in its lineage with the defining package,
|
||||
// and the defining package still trusts the old certificate for permissions
|
||||
// - or it shares the above relationships with the system package
|
||||
val packageSigningDetails = packageState.androidPackage!!.signingDetails
|
||||
val sourceSigningDetails = newState.systemState
|
||||
.packageStates[permission.packageName]?.signingDetails
|
||||
.packageStates[permission.packageName]?.androidPackage?.signingDetails
|
||||
val platformSigningDetails = newState.systemState
|
||||
.packageStates[PLATFORM_PACKAGE_NAME]!!.signingDetails
|
||||
return sourceSigningDetails?.hasCommonSignerWithCapability(packageState.signingDetails,
|
||||
.packageStates[PLATFORM_PACKAGE_NAME]!!.androidPackage!!.signingDetails
|
||||
return sourceSigningDetails?.hasCommonSignerWithCapability(packageSigningDetails,
|
||||
SigningDetails.CertCapabilities.PERMISSION) == true ||
|
||||
packageState.signingDetails.hasAncestorOrSelf(platformSigningDetails) ||
|
||||
platformSigningDetails.checkCapability(packageState.signingDetails,
|
||||
packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) ||
|
||||
platformSigningDetails.checkCapability(packageSigningDetails,
|
||||
SigningDetails.CertCapabilities.PERMISSION)
|
||||
}
|
||||
|
||||
@@ -629,7 +615,10 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
androidPackage: AndroidPackage,
|
||||
permissionName: String
|
||||
): Boolean {
|
||||
val apexModuleName = androidPackage.apexModuleName
|
||||
// TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for
|
||||
// passing compilation but won't actually work.
|
||||
//val apexModuleName = androidPackage.apexModuleName
|
||||
val apexModuleName = androidPackage.packageName
|
||||
val systemState = newState.systemState
|
||||
val packageName = androidPackage.packageName
|
||||
val permissionNames = when {
|
||||
@@ -657,7 +646,10 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
): Boolean {
|
||||
// Different from the previous implementation, which may incorrectly use the APEX package
|
||||
// name, we now use the APEX module name to be consistent with the allowlist.
|
||||
val apexModuleName = androidPackage.apexModuleName
|
||||
// TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for
|
||||
// passing compilation but won't actually work.
|
||||
//val apexModuleName = androidPackage.apexModuleName
|
||||
val apexModuleName = androidPackage.packageName
|
||||
val systemState = newState.systemState
|
||||
val packageName = androidPackage.packageName
|
||||
val permissionNames = when {
|
||||
@@ -741,7 +733,7 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
return true
|
||||
}
|
||||
if (permission.isKnownSigner &&
|
||||
packageState.signingDetails.hasAncestorOrSelfWithDigest(permission.knownCerts)) {
|
||||
androidPackage.signingDetails.hasAncestorOrSelfWithDigest(permission.knownCerts)) {
|
||||
// If the permission is to be granted to a known signer then check if any of this
|
||||
// app's signing certificates are in the trusted certificate digest Set.
|
||||
return true
|
||||
@@ -840,8 +832,11 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
return uid == ownerUid
|
||||
}
|
||||
|
||||
override fun MutateStateScope.onPackageRemoved(packageState: PackageState) {
|
||||
// TODO
|
||||
override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {
|
||||
// TODO: STOPSHIP: Remove this check or at least turn into logging.
|
||||
check(packageName !in newState.systemState.disabledSystemPackageStates) {
|
||||
"Package $packageName reported as removed before disabled system package is enabled"
|
||||
}
|
||||
}
|
||||
|
||||
override fun BinaryXmlPullParser.parseSystemState(systemState: SystemState) {
|
||||
@@ -858,6 +853,76 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
fun GetStateScope.getPermission(permissionName: String): Permission? =
|
||||
state.systemState.permissions[permissionName]
|
||||
|
||||
fun GetStateScope.getPermissionFlags(
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String
|
||||
): Int = getPermissionFlags(state, appId, userId, permissionName)
|
||||
|
||||
private fun MutateStateScope.getPermissionFlags(
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String,
|
||||
state: AccessState = newState
|
||||
): Int = getPermissionFlags(state, appId, userId, permissionName)
|
||||
|
||||
private fun getPermissionFlags(
|
||||
state: AccessState,
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String
|
||||
): Int = state.userStates[userId].uidPermissionFlags[appId].getWithDefault(permissionName, 0)
|
||||
|
||||
fun MutateStateScope.setPermissionFlags(
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String,
|
||||
flags: Int
|
||||
): Boolean =
|
||||
updatePermissionFlags(appId, userId, permissionName, PermissionFlags.MASK_ALL, flags)
|
||||
|
||||
fun MutateStateScope.updatePermissionFlags(
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String,
|
||||
flagMask: Int,
|
||||
flagValues: Int
|
||||
): Boolean {
|
||||
val userState = newState.userStates[userId]
|
||||
val uidPermissionFlags = userState.uidPermissionFlags
|
||||
var permissionFlags = uidPermissionFlags[appId]
|
||||
val oldFlags = permissionFlags.getWithDefault(permissionName, 0)
|
||||
val newFlags = (oldFlags andInv flagMask) or flagValues
|
||||
if (oldFlags == newFlags) {
|
||||
return false
|
||||
}
|
||||
if (permissionFlags == null) {
|
||||
permissionFlags = IndexedMap()
|
||||
uidPermissionFlags[appId] = permissionFlags
|
||||
}
|
||||
permissionFlags.putWithDefault(permissionName, newFlags, 0)
|
||||
if (permissionFlags.isEmpty()) {
|
||||
uidPermissionFlags -= appId
|
||||
}
|
||||
userState.requestWrite()
|
||||
onPermissionFlagsChangedListeners.forEachIndexed { _, it ->
|
||||
it.onPermissionFlagsChanged(appId, userId, permissionName, oldFlags, newFlags)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun addOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) {
|
||||
synchronized(onPermissionFlagsChangedListenersLock) {
|
||||
onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners + listener
|
||||
}
|
||||
}
|
||||
|
||||
fun removeOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) {
|
||||
synchronized(onPermissionFlagsChangedListenersLock) {
|
||||
onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners - listener
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG_TAG = UidPermissionPolicy::class.java.simpleName
|
||||
|
||||
@@ -872,4 +937,14 @@ class UidPermissionPolicy : SchemePolicy() {
|
||||
Manifest.permission.READ_MEDIA_VIDEO,
|
||||
)
|
||||
}
|
||||
|
||||
fun interface OnPermissionFlagsChangedListener {
|
||||
fun onPermissionFlagsChanged(
|
||||
appId: Int,
|
||||
userId: Int,
|
||||
permissionName: String,
|
||||
oldFlags: Int,
|
||||
newFlags: Int
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user