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 }