From a8c89fe80740a58094a925f9cf73885f2c759fb4 Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Sat, 10 Dec 2022 22:46:56 -0800 Subject: [PATCH] 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 --- .../access/AccessCheckingService.kt | 89 +++++++++++-- .../server/permission/access/AccessPolicy.kt | 118 ++++++++++++++---- .../server/permission/access/AccessState.kt | 14 +-- .../server/permission/access/AccessUri.kt | 5 +- ...ngServiceCompatImpl.kt => AppOpService.kt} | 10 +- .../access/appop/PackageAppOpPolicy.kt | 5 +- .../permission/access/collection/IntSet.kt | 10 ++ .../server/permission/access/data/Package.kt | 43 ------- .../external/CompatibilityPermissionInfo.kt | 29 ----- .../access/external/KnownPackages.kt | 34 ----- .../access/external/PackageInfoUtils.kt | 33 ----- .../access/external/PackageState.kt | 65 ---------- .../access/external/RoSystemProperties.kt | 24 ---- .../access/external/SigningDetails.kt | 42 ------- .../permission/access/external/UserHandle.kt | 31 ----- .../access/{data => permission}/Permission.kt | 2 +- ...gerServiceImpl.kt => PermissionService.kt} | 74 ++++++++--- .../permission/UidPermissionPersistence.kt | 1 - .../access/permission/UidPermissionPolicy.kt | 64 +++++----- 19 files changed, 292 insertions(+), 401 deletions(-) rename services/permission/java/com/android/server/permission/access/appop/{AppOpsCheckingServiceCompatImpl.kt => AppOpService.kt} (95%) delete mode 100644 services/permission/java/com/android/server/permission/access/data/Package.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/CompatibilityPermissionInfo.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/KnownPackages.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/PackageInfoUtils.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/PackageState.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/RoSystemProperties.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/SigningDetails.kt delete mode 100644 services/permission/java/com/android/server/permission/access/external/UserHandle.kt rename services/permission/java/com/android/server/permission/access/{data => permission}/Permission.kt (98%) rename services/permission/java/com/android/server/permission/access/permission/{ModernPermissionManagerServiceImpl.kt => PermissionService.kt} (84%) diff --git a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt index 7b96d42c8abe4..73c2cccc550d0 100644 --- a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +++ b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt @@ -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 + get() = withUnfilteredSnapshot().use { it.packageStates } + internal inline fun getState(action: GetStateScope.() -> T): T = GetStateScope(state).action() diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt index e9741c69aa5be..0201dd0d0c799 100644 --- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt @@ -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> @@ -53,6 +54,17 @@ class AccessPolicy private constructor( with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) } } + fun initialize(state: AccessState, userIds: IntSet, packageStates: Map) { + 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, + volumeUuid: String?, + isSystemUpdated: Boolean + ) { + newState.systemState.packageStates = packageStates + forEachSchemePolicy { + with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) } } + } + + fun MutateStateScope.onPackageAdded( + packageStates: Map, + 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, + 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, + 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, + 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) {} diff --git a/services/permission/java/com/android/server/permission/access/AccessState.kt b/services/permission/java/com/android/server/permission/access/AccessState.kt index cf8f38360cffa..4c794931cf981 100644 --- a/services/permission/java/com/android/server/permission/access/AccessState.kt +++ b/services/permission/java/com/android/server/permission/access/AccessState.kt @@ -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, - val disabledSystemPackageStates: IndexedMap, + var packageStates: Map, + var disabledSystemPackageStates: Map, val appIds: IntMap>, // A map of KnownPackagesInt to a set of known package names val knownPackages: IntMap>, @@ -59,7 +59,7 @@ class SystemState private constructor( val permissions: IndexedMap ) : 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 }, diff --git a/services/permission/java/com/android/server/permission/access/AccessUri.kt b/services/permission/java/com/android/server/permission/access/AccessUri.kt index 7e98d2cb13e76..d1abc0455245b 100644 --- a/services/permission/java/com/android/server/permission/access/AccessUri.kt +++ b/services/permission/java/com/android/server/permission/access/AccessUri.kt @@ -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) diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpsCheckingServiceCompatImpl.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt similarity index 95% rename from services/permission/java/com/android/server/permission/access/appop/AppOpsCheckingServiceCompatImpl.kt rename to services/permission/java/com/android/server/permission/access/appop/AppOpService.kt index a565feb959c2c..b8d6aa3b4e496 100644 --- a/services/permission/java/com/android/server/permission/access/appop/AppOpsCheckingServiceCompatImpl.kt +++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt @@ -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 } } diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt index 966489f72aa22..f4d6bfd0a000e 100644 --- a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt @@ -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 } } } diff --git a/services/permission/java/com/android/server/permission/access/collection/IntSet.kt b/services/permission/java/com/android/server/permission/access/collection/IntSet.kt index d6dfe9d0eb371..7cc2fe498b301 100644 --- a/services/permission/java/com/android/server/permission/access/collection/IntSet.kt +++ b/services/permission/java/com/android/server/permission/access/collection/IntSet.kt @@ -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,6 +105,14 @@ inline operator fun IntSet.plusAssign(element: Int) { add(element) } +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) { for (index in lastIndex downTo 0) { if (predicate(index, elementAt(index))) { diff --git a/services/permission/java/com/android/server/permission/access/data/Package.kt b/services/permission/java/com/android/server/permission/access/data/Package.kt deleted file mode 100644 index d6f98ab256cf1..0000000000000 --- a/services/permission/java/com/android/server/permission/access/data/Package.kt +++ /dev/null @@ -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 - get() = androidPackage.adoptPermissions - - val appId: Int - get() = androidPackage.appId - - val requestedPermissions: List - get() = androidPackage.requestedPermissions - - override fun equals(other: Any?): Boolean { - throw NotImplementedError() - } - - override fun hashCode(): Int { - throw NotImplementedError() - } -} diff --git a/services/permission/java/com/android/server/permission/access/external/CompatibilityPermissionInfo.kt b/services/permission/java/com/android/server/permission/access/external/CompatibilityPermissionInfo.kt deleted file mode 100644 index aadd8baedc812..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/CompatibilityPermissionInfo.kt +++ /dev/null @@ -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() -} diff --git a/services/permission/java/com/android/server/permission/access/external/KnownPackages.kt b/services/permission/java/com/android/server/permission/access/external/KnownPackages.kt deleted file mode 100644 index 1239450c0963d..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/KnownPackages.kt +++ /dev/null @@ -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 - } -} diff --git a/services/permission/java/com/android/server/permission/access/external/PackageInfoUtils.kt b/services/permission/java/com/android/server/permission/access/external/PackageInfoUtils.kt deleted file mode 100644 index 24b28bd49fc99..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/PackageInfoUtils.kt +++ /dev/null @@ -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() - } -} diff --git a/services/permission/java/com/android/server/permission/access/external/PackageState.kt b/services/permission/java/com/android/server/permission/access/external/PackageState.kt deleted file mode 100644 index b81d7946f2e9a..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/PackageState.kt +++ /dev/null @@ -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 - 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 - val permissions: List - val permissionGroups: List - val requestedPermissions: List - val implicitPermissions: List -} - -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 -} diff --git a/services/permission/java/com/android/server/permission/access/external/RoSystemProperties.kt b/services/permission/java/com/android/server/permission/access/external/RoSystemProperties.kt deleted file mode 100644 index 528680e77879e..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/RoSystemProperties.kt +++ /dev/null @@ -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 - } -} diff --git a/services/permission/java/com/android/server/permission/access/external/SigningDetails.kt b/services/permission/java/com/android/server/permission/access/external/SigningDetails.kt deleted file mode 100644 index 25917f993d4db..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/SigningDetails.kt +++ /dev/null @@ -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): Boolean { - throw NotImplementedError() - } - - class CertCapabilities { - companion object { - /** grant SIGNATURE permissions to pkgs with this cert */ - var PERMISSION = 4 - } - } -} diff --git a/services/permission/java/com/android/server/permission/access/external/UserHandle.kt b/services/permission/java/com/android/server/permission/access/external/UserHandle.kt deleted file mode 100644 index e1072a760dc22..0000000000000 --- a/services/permission/java/com/android/server/permission/access/external/UserHandle.kt +++ /dev/null @@ -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() - } -} diff --git a/services/permission/java/com/android/server/permission/access/data/Permission.kt b/services/permission/java/com/android/server/permission/access/permission/Permission.kt similarity index 98% rename from services/permission/java/com/android/server/permission/access/data/Permission.kt rename to services/permission/java/com/android/server/permission/access/permission/Permission.kt index 877f23b0e825f..efa5bf3118d6d 100644 --- a/services/permission/java/com/android/server/permission/access/data/Permission.kt +++ b/services/permission/java/com/android/server/permission/access/permission/Permission.kt @@ -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 diff --git a/services/permission/java/com/android/server/permission/access/permission/ModernPermissionManagerServiceImpl.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt similarity index 84% rename from services/permission/java/com/android/server/permission/access/permission/ModernPermissionManagerServiceImpl.kt rename to services/permission/java/com/android/server/permission/access/permission/PermissionService.kt index cc51866b46954..1e6996b02721b 100644 --- a/services/permission/java/com/android/server/permission/access/permission/ModernPermissionManagerServiceImpl.kt +++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt @@ -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() + + fun initialize() { + packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java) + packageManagerLocal = + LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) + userManagerService = UserManagerService.getInstance() + } override fun getAllPermissionGroups(flags: Int): List { 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, + sharedUserPkgs: List, 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) + } } /** diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt index 3489061c5bae1..061933a13fb44 100644 --- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt +++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt @@ -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 diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt index e08192444d676..74e4f21e926a2 100644 --- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt @@ -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 @@ -35,16 +37,13 @@ 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.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() @@ -75,7 +74,7 @@ class UidPermissionPolicy : SchemePolicy() { } override fun MutateStateScope.onUserAdded(userId: Int) { - newState.systemState.packageStates.forEachValueIndexed { _, packageState -> + newState.systemState.packageStates.forEach { (_, packageState) -> evaluateAllPermissionStatesForPackageAndUser(packageState, null, userId) grantImplicitPermissions(packageState, userId) } @@ -179,7 +178,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,7 +210,7 @@ class UidPermissionPolicy : SchemePolicy() { // } val newPermissionInfo = PackageInfoUtils.generatePermissionInfo( parsedPermission, PackageManager.GET_META_DATA.toLong() - ) + )!! // TODO: newPermissionInfo.flags |= PermissionInfo.FLAG_INSTALLED val permissionName = newPermissionInfo.name val oldPermission = if (parsedPermission.isTree) { @@ -573,23 +572,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 +629,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 +660,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 +747,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,7 +846,7 @@ class UidPermissionPolicy : SchemePolicy() { return uid == ownerUid } - override fun MutateStateScope.onPackageRemoved(packageState: PackageState) { + override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) { // TODO }