Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8c89fe8 authored by Hai Zhang's avatar Hai Zhang
Browse files

Make AccessCheckingService a SystemService.

And connect it with the existing parts of the system, so that we can
remove all the stub classes created for compilation.

The new implementations of the app op and permission service interface
are now published via LocalServices and available in services-core.

The external states are now actually available, including the package
states being provided by PackageManagerLocal. The callbacks are
temporarily being delivered by the new permission service because only
it has the blocking callbacks at the right timing during package
changes.

A new intialize() function is added for the new app op and permission
services. It is called when the core system services (including ours)
have read the on-disk state and are ready, so that our services can
now retrieve their dependent services and start working. Any call to
the new services before this call can't have meaningful results and
should be no-op'ed in some way.

Bug: 182523293
Test: presubmit
Change-Id: I9c4ec4b7d56ec9d97c4b097cacc7680fa0a08690
parent 4a51535c
Loading
Loading
Loading
Loading
+76 −13
Original line number Diff line number Diff line
@@ -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() {
        val state = AccessState()
        state.systemState.userIds.apply {
            // TODO: Get and add all user IDs.
            // TODO: Maybe get and add all packages?
    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()
        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) { onStorageVolumeMounted(packageStates, volumeUuid, isSystemUpdated) }
        }
    }

    internal fun onPackageAdded(packageName: String) {
        val packageStates = packageManagerLocal.packageStates
        mutateState {
            with(policy) { onPackageAdded(packageStates, packageName) }
        }
    }

    internal fun onPackageRemoved(packageName: String, appId: Int) {
        val packageStates = packageManagerLocal.packageStates
        mutateState {
            with(policy) { onPackageAdded(packageState) }
            with(policy) { onPackageRemoved(packageStates, packageName, appId) }
        }
    }

    fun onPackageRemoved(packageState: PackageState) {
    internal fun onPackageInstalled(
        packageName: String,
        params: PermissionManagerServiceInternal.PackageInstalledParams,
        userId: Int
    ) {
        val packageStates = packageManagerLocal.packageStates
        mutateState {
            with(policy) { onPackageRemoved(packageState) }
            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()

+95 −23
Original line number Diff line number Diff line
@@ -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) {
    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
        newState.systemState.apply {
            packageStates[packageState.packageName] = packageState
            appIds.getOrPut(packageState.appId) {
        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(packageState.packageName)
        }
        }.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
        // TODO(zhanghai): Remove check before submission.
        check(packageName !in packageStates)
        newState.systemState.appIds.apply appIds@{
            this[appId]?.apply {
                this -= packageName
                if (isEmpty()) {
                        this@appIds -= packageState.appId
                    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) {}

+7 −7
Original line number Diff line number Diff line
@@ -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 },
+2 −3
Original line number Diff line number Diff line
@@ -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)
+7 −3
Original line number Diff line number Diff line
@@ -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
    }
}
Loading