Add unit tests for AppIdPermissionPolicy
Bug: 280853174
Test: AppIdPermissionPolicyTest
Change-Id: I67c3c86b2ca4c0a87b05922f3a7fcc3bff04123d
diff --git a/services/permission/Android.bp b/services/permission/Android.bp
index dc9b558..59ca851 100644
--- a/services/permission/Android.bp
+++ b/services/permission/Android.bp
@@ -17,8 +17,8 @@
visibility: ["//frameworks/base/services"],
}
-java_library_static {
- name: "services.permission",
+java_library {
+ name: "services.permission-pre-jarjar",
defaults: ["platform_service_defaults"],
srcs: [":services.permission-sources"],
libs: [
@@ -32,7 +32,6 @@
// Adds reflection-less suppressed exceptions and AutoCloseable.use().
"kotlin-stdlib-jdk7",
],
- jarjar_rules: "jarjar-rules.txt",
kotlincflags: [
"-Xjvm-default=all",
"-Xno-call-assertions",
@@ -40,3 +39,9 @@
"-Xno-receiver-assertions",
],
}
+
+java_library {
+ name: "services.permission",
+ static_libs: ["services.permission-pre-jarjar"],
+ jarjar_rules: "jarjar-rules.txt",
+}
diff --git a/services/tests/PermissionServiceMockingTests/Android.bp b/services/tests/PermissionServiceMockingTests/Android.bp
new file mode 100644
index 0000000..cedfd2c
--- /dev/null
+++ b/services/tests/PermissionServiceMockingTests/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "PermissionServiceMockingTests",
+ defaults: [
+ // This is needed for the ExtendedMockitoRule
+ "modules-utils-testable-device-config-defaults",
+ ],
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "mockingservicestests-utils-mockito",
+ "services.core",
+ "services.permission-pre-jarjar",
+ "servicestests-core-utils",
+ "servicestests-utils",
+ ],
+ platform_apis: true,
+ test_suites: [
+ "device-tests",
+ ],
+}
diff --git a/services/tests/PermissionServiceMockingTests/AndroidManifest.xml b/services/tests/PermissionServiceMockingTests/AndroidManifest.xml
new file mode 100644
index 0000000..32b64ac
--- /dev/null
+++ b/services/tests/PermissionServiceMockingTests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (C) 2023 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.
+-->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.permission.test">
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.mock" android:required="true" />
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.permission.test"
+ android:label="Permission Service Mocking Tests" />
+</manifest>
diff --git a/services/tests/PermissionServiceMockingTests/AndroidTest.xml b/services/tests/PermissionServiceMockingTests/AndroidTest.xml
new file mode 100644
index 0000000..157c4f0
--- /dev/null
+++ b/services/tests/PermissionServiceMockingTests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Configuration for PermissionServiceMockingTests">
+ <option name="test-tag" value="PermissionServiceMockingTests" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="PermissionServiceMockingTests.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.server.permission.test" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
diff --git a/services/tests/PermissionServiceMockingTests/OWNERS b/services/tests/PermissionServiceMockingTests/OWNERS
new file mode 100644
index 0000000..dafdf0f
--- /dev/null
+++ b/services/tests/PermissionServiceMockingTests/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt
new file mode 100644
index 0000000..3ef3a89
--- /dev/null
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2023 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.test
+
+import android.content.pm.PackageManager
+import android.content.pm.PermissionGroupInfo
+import android.content.pm.PermissionInfo
+import android.os.Bundle
+import android.util.ArrayMap
+import android.util.ArraySet
+import android.util.SparseArray
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.android.server.extendedtestutils.wheneverStatic
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutableUserState
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.permission.AppIdPermissionPolicy
+import com.android.server.permission.access.permission.Permission
+import com.android.server.permission.access.permission.PermissionFlags
+import com.android.server.pm.parsing.PackageInfoUtils
+import com.android.server.pm.pkg.AndroidPackage
+import com.android.server.pm.pkg.PackageState
+import com.android.server.pm.pkg.PackageUserState
+import com.android.server.pm.pkg.component.ParsedPermission
+import com.android.server.pm.pkg.component.ParsedPermissionGroup
+import com.android.server.testutils.mock
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Mocking unit test for AppIdPermissionPolicy.
+ */
+@RunWith(AndroidJUnit4::class)
+class AppIdPermissionPolicyTest {
+ private lateinit var oldState: MutableAccessState
+ private lateinit var newState: MutableAccessState
+
+ private lateinit var androidPackage0: AndroidPackage
+ private lateinit var androidPackage1: AndroidPackage
+
+ private lateinit var packageState0: PackageState
+ private lateinit var packageState1: PackageState
+
+ private val appIdPermissionPolicy = AppIdPermissionPolicy()
+
+ @Rule
+ @JvmField
+ val extendedMockitoRule = ExtendedMockitoRule.Builder(this)
+ .spyStatic(PackageInfoUtils::class.java)
+ .build()
+
+ @Before
+ fun init() {
+ oldState = MutableAccessState()
+ createUserState(USER_ID_0)
+ createUserState(USER_ID_1)
+ oldState.mutateExternalState().setPackageStates(ArrayMap())
+
+ androidPackage0 = mockAndroidPackage(
+ PACKAGE_NAME_0,
+ PERMISSION_GROUP_NAME_0,
+ PERMISSION_NAME_0
+ )
+ androidPackage1 = mockAndroidPackage(
+ PACKAGE_NAME_1,
+ PERMISSION_GROUP_NAME_1,
+ PERMISSION_NAME_1
+ )
+
+ packageState0 = mockPackageState(APP_ID_0, androidPackage0)
+ packageState1 = mockPackageState(APP_ID_1, androidPackage1)
+ }
+
+ private fun mockAndroidPackage(
+ packageName: String,
+ permissionGroupName: String,
+ permissionName: String,
+ ): AndroidPackage {
+ val parsedPermissionGroup = mock<ParsedPermissionGroup> {
+ whenever(name).thenReturn(permissionGroupName)
+ whenever(metaData).thenReturn(Bundle())
+ }
+
+ @Suppress("DEPRECATION")
+ val permissionGroupInfo = PermissionGroupInfo().apply {
+ name = permissionGroupName
+ this.packageName = packageName
+ }
+ wheneverStatic {
+ PackageInfoUtils.generatePermissionGroupInfo(
+ parsedPermissionGroup,
+ PackageManager.GET_META_DATA.toLong()
+ )
+ }.thenReturn(permissionGroupInfo)
+
+ val parsedPermission = mock<ParsedPermission> {
+ whenever(name).thenReturn(permissionName)
+ whenever(isTree).thenReturn(false)
+ whenever(metaData).thenReturn(Bundle())
+ }
+
+ @Suppress("DEPRECATION")
+ val permissionInfo = PermissionInfo().apply {
+ name = permissionName
+ this.packageName = packageName
+ }
+ wheneverStatic {
+ PackageInfoUtils.generatePermissionInfo(
+ parsedPermission,
+ PackageManager.GET_META_DATA.toLong()
+ )
+ }.thenReturn(permissionInfo)
+
+ val requestedPermissions = ArraySet<String>()
+ return mock {
+ whenever(this.packageName).thenReturn(packageName)
+ whenever(this.requestedPermissions).thenReturn(requestedPermissions)
+ whenever(permissionGroups).thenReturn(listOf(parsedPermissionGroup))
+ whenever(permissions).thenReturn(listOf(parsedPermission))
+ whenever(signingDetails).thenReturn(mock {})
+ }
+ }
+
+ private fun mockPackageState(
+ appId: Int,
+ androidPackage: AndroidPackage,
+ ): PackageState {
+ val packageName = androidPackage.packageName
+ oldState.mutateExternalState().mutateAppIdPackageNames().mutateOrPut(appId) {
+ MutableIndexedListSet()
+ }.add(packageName)
+
+ val userStates = SparseArray<PackageUserState>().apply {
+ put(USER_ID_0, mock { whenever(isInstantApp).thenReturn(false) })
+ }
+ val mockPackageState: PackageState = mock {
+ whenever(this.packageName).thenReturn(packageName)
+ whenever(this.appId).thenReturn(appId)
+ whenever(this.androidPackage).thenReturn(androidPackage)
+ whenever(isSystem).thenReturn(false)
+ whenever(this.userStates).thenReturn(userStates)
+ }
+ oldState.mutateExternalState().setPackageStates(
+ oldState.mutateExternalState().packageStates.toMutableMap().apply {
+ put(packageName, mockPackageState)
+ }
+ )
+ return mockPackageState
+ }
+
+ private fun createUserState(userId: Int) {
+ oldState.mutateUserStatesNoWrite().put(userId, MutableUserState())
+ }
+
+ @Test
+ fun testResetRuntimePermissions_runtimeGranted_getsRevoked() {
+ val oldFlags = PermissionFlags.RUNTIME_GRANTED
+ val expectedNewFlags = 0
+ testResetRuntimePermissions(oldFlags, expectedNewFlags) {}
+ }
+
+ @Test
+ fun testResetRuntimePermissions_roleGranted_getsGranted() {
+ val oldFlags = PermissionFlags.ROLE
+ val expectedNewFlags = PermissionFlags.ROLE or PermissionFlags.RUNTIME_GRANTED
+ testResetRuntimePermissions(oldFlags, expectedNewFlags) {}
+ }
+
+ @Test
+ fun testResetRuntimePermissions_nullAndroidPackage_remainsUnchanged() {
+ val oldFlags = PermissionFlags.RUNTIME_GRANTED
+ val expectedNewFlags = PermissionFlags.RUNTIME_GRANTED
+ testResetRuntimePermissions(oldFlags, expectedNewFlags) {
+ whenever(packageState0.androidPackage).thenReturn(null)
+ }
+ }
+
+ private inline fun testResetRuntimePermissions(
+ oldFlags: Int,
+ expectedNewFlags: Int,
+ additionalSetup: () -> Unit
+ ) {
+ createSystemStatePermission(
+ APP_ID_0,
+ PACKAGE_NAME_0,
+ PERMISSION_NAME_0,
+ PermissionInfo.PROTECTION_DANGEROUS
+ )
+ androidPackage0.requestedPermissions.add(PERMISSION_NAME_0)
+ oldState.mutateUserState(USER_ID_0)!!.mutateAppIdPermissionFlags().mutateOrPut(APP_ID_0) {
+ MutableIndexedMap()
+ }.put(PERMISSION_NAME_0, oldFlags)
+
+ additionalSetup()
+
+ mutateState {
+ with(appIdPermissionPolicy) {
+ resetRuntimePermissions(PACKAGE_NAME_0, USER_ID_0)
+ }
+ }
+
+ val actualFlags = getPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0)
+ assertWithMessage(
+ "After resetting runtime permissions, permission flags did not match" +
+ " expected values: expectedNewFlags is $expectedNewFlags," +
+ " actualFlags is $actualFlags, while the oldFlags is $oldFlags"
+ )
+ .that(actualFlags)
+ .isEqualTo(expectedNewFlags)
+ }
+
+ @Test
+ fun testOnPackageAdded_permissionsOfMissingSystemApp_getsAdopted() {
+ testOnPackageAdded {
+ adoptPermissionTestSetup()
+ whenever(packageState1.androidPackage).thenReturn(null)
+ }
+
+ val permission0 = newState.systemState.permissions[PERMISSION_NAME_0]
+ assertWithMessage(
+ "After onPackageAdded() is called for a null adopt permission package," +
+ " the permission package name: ${permission0!!.packageName} did not match" +
+ " the expected package name: $PACKAGE_NAME_0"
+ )
+ .that(permission0.packageName)
+ .isEqualTo(PACKAGE_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_permissionsOfExistingSystemApp_notAdopted() {
+ testOnPackageAdded {
+ adoptPermissionTestSetup()
+ }
+
+ val permission0 = newState.systemState.permissions[PERMISSION_NAME_0]
+ assertWithMessage(
+ "After onPackageAdded() is called for a non-null adopt permission" +
+ " package, the permission package name: ${permission0!!.packageName} should" +
+ " not match the package name: $PACKAGE_NAME_0"
+ )
+ .that(permission0.packageName)
+ .isNotEqualTo(PACKAGE_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_permissionsOfNonSystemApp_notAdopted() {
+ testOnPackageAdded {
+ adoptPermissionTestSetup()
+ whenever(packageState1.isSystem).thenReturn(false)
+ }
+
+ val permission0 = newState.systemState.permissions[PERMISSION_NAME_0]
+ assertWithMessage(
+ "After onPackageAdded() is called for a non-system adopt permission" +
+ " package, the permission package name: ${permission0!!.packageName} should" +
+ " not match the package name: $PACKAGE_NAME_0"
+ )
+ .that(permission0.packageName)
+ .isNotEqualTo(PACKAGE_NAME_0)
+ }
+
+ private fun adoptPermissionTestSetup() {
+ createSystemStatePermission(
+ APP_ID_1,
+ PACKAGE_NAME_1,
+ PERMISSION_NAME_0,
+ PermissionInfo.PROTECTION_SIGNATURE
+ )
+ whenever(androidPackage0.adoptPermissions).thenReturn(listOf(PACKAGE_NAME_1))
+ whenever(packageState1.isSystem).thenReturn(true)
+ }
+
+ @Test
+ fun testOnPackageAdded_newPermissionGroup_getsDeclared() {
+ testOnPackageAdded {}
+
+ assertWithMessage(
+ "After onPackageAdded() is called when there is no existing" +
+ " permission groups, the new permission group $PERMISSION_GROUP_NAME_0 is not added"
+ )
+ .that(newState.systemState.permissionGroups[PERMISSION_GROUP_NAME_0]?.name)
+ .isEqualTo(PERMISSION_GROUP_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_systemAppTakingOverPermissionGroupDefinition_getsTakenOver() {
+ testOnPackageAdded {
+ whenever(packageState0.isSystem).thenReturn(true)
+ createSystemStatePermissionGroup(PACKAGE_NAME_1, PERMISSION_GROUP_NAME_0)
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called when $PERMISSION_GROUP_NAME_0 already" +
+ " exists in the system, the system app $PACKAGE_NAME_0 didn't takeover the ownership" +
+ " of this permission group"
+ )
+ .that(newState.systemState.permissionGroups[PERMISSION_GROUP_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_instantApps_remainsUnchanged() {
+ testOnPackageAdded {
+ (packageState0.userStates as SparseArray<PackageUserState>).apply {
+ put(0, mock { whenever(isInstantApp).thenReturn(true) })
+ }
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called for an instant app," +
+ " the new permission group $PERMISSION_GROUP_NAME_0 should not be added"
+ )
+ .that(newState.systemState.permissionGroups[PERMISSION_GROUP_NAME_0])
+ .isNull()
+ }
+
+ @Test
+ fun testOnPackageAdded_nonSystemAppTakingOverPermissionGroupDefinition_remainsUnchanged() {
+ testOnPackageAdded {
+ createSystemStatePermissionGroup(PACKAGE_NAME_1, PERMISSION_GROUP_NAME_0)
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called when $PERMISSION_GROUP_NAME_0 already" +
+ " exists in the system, non-system app $PACKAGE_NAME_0 shouldn't takeover ownership" +
+ " of this permission group"
+ )
+ .that(newState.systemState.permissionGroups[PERMISSION_GROUP_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_1)
+ }
+
+ @Test
+ fun testOnPackageAdded_takingOverPermissionGroupDeclaredBySystemApp_remainsUnchanged() {
+ testOnPackageAdded {
+ whenever(packageState1.isSystem).thenReturn(true)
+ createSystemStatePermissionGroup(PACKAGE_NAME_1, PERMISSION_GROUP_NAME_0)
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called when $PERMISSION_GROUP_NAME_0 already" +
+ " exists in the system and is owned by a system app, app $PACKAGE_NAME_0 shouldn't" +
+ " takeover ownership of this permission group"
+ )
+ .that(newState.systemState.permissionGroups[PERMISSION_GROUP_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_1)
+ }
+
+ @Test
+ fun testOnPackageAdded_newPermission_getsDeclared() {
+ testOnPackageAdded {}
+
+ assertWithMessage(
+ "After onPackageAdded() is called when there is no existing" +
+ " permissions, the new permission $PERMISSION_NAME_0 is not added"
+ )
+ .that(newState.systemState.permissions[PERMISSION_NAME_0]?.name)
+ .isEqualTo(PERMISSION_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_configPermission_getsTakenOver() {
+ testOnPackageAdded {
+ whenever(packageState0.isSystem).thenReturn(true)
+ createSystemStatePermission(
+ APP_ID_0,
+ PACKAGE_NAME_1,
+ PERMISSION_NAME_0,
+ PermissionInfo.PROTECTION_DANGEROUS,
+ Permission.TYPE_CONFIG,
+ false
+ )
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called for a config permission with" +
+ " no owner, the ownership is not taken over by a system app $PACKAGE_NAME_0"
+ )
+ .that(newState.systemState.permissions[PERMISSION_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_systemAppTakingOverPermissionDefinition_getsTakenOver() {
+ testOnPackageAdded {
+ whenever(packageState0.isSystem).thenReturn(true)
+ createSystemStatePermission(
+ APP_ID_1,
+ PACKAGE_NAME_1,
+ PERMISSION_NAME_0,
+ PermissionInfo.PROTECTION_DANGEROUS
+ )
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called when $PERMISSION_NAME_0 already" +
+ " exists in the system, the system app $PACKAGE_NAME_0 didn't takeover the ownership" +
+ " of this permission"
+ )
+ .that(newState.systemState.permissions[PERMISSION_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_0)
+ }
+
+ @Test
+ fun testOnPackageAdded_nonSystemAppTakingOverPermissionDefinition_remainsUnchanged() {
+ testOnPackageAdded {
+ createSystemStatePermission(
+ APP_ID_1,
+ PACKAGE_NAME_1,
+ PERMISSION_NAME_0,
+ PermissionInfo.PROTECTION_DANGEROUS
+ )
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called when $PERMISSION_NAME_0 already" +
+ " exists in the system, the non-system app $PACKAGE_NAME_0 shouldn't takeover" +
+ " ownership of this permission"
+ )
+ .that(newState.systemState.permissions[PERMISSION_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_1)
+ }
+
+ @Test
+ fun testOnPackageAdded_takingOverPermissionDeclaredBySystemApp_remainsUnchanged() {
+ testOnPackageAdded {
+ whenever(packageState1.isSystem).thenReturn(true)
+ createSystemStatePermission(
+ APP_ID_1,
+ PACKAGE_NAME_1,
+ PERMISSION_NAME_0,
+ PermissionInfo.PROTECTION_DANGEROUS
+ )
+ }
+
+ assertWithMessage(
+ "After onPackageAdded() is called when $PERMISSION_NAME_0 already" +
+ " exists in system and is owned by a system app, the app $PACKAGE_NAME_0 shouldn't" +
+ " takeover ownership of this permission"
+ )
+ .that(newState.systemState.permissions[PERMISSION_NAME_0]?.packageName)
+ .isEqualTo(PACKAGE_NAME_1)
+ }
+
+ private inline fun testOnPackageAdded(mockBehaviorOverride: () -> Unit) {
+ mockBehaviorOverride()
+
+ mutateState {
+ with(appIdPermissionPolicy) {
+ onPackageAdded(packageState0)
+ }
+ }
+ }
+
+ private inline fun mutateState(action: MutateStateScope.() -> Unit) {
+ newState = oldState.toMutable()
+ MutateStateScope(oldState, newState).action()
+ }
+
+ private fun createSystemStatePermission(
+ appId: Int,
+ packageName: String,
+ permissionName: String,
+ protectionLevel: Int,
+ type: Int = Permission.TYPE_MANIFEST,
+ isReconciled: Boolean = true,
+ isTree: Boolean = false
+ ) {
+ @Suppress("DEPRECATION")
+ val permissionInfo = PermissionInfo().apply {
+ name = permissionName
+ this.packageName = packageName
+ this.protectionLevel = protectionLevel
+ }
+ val permission = Permission(permissionInfo, isReconciled, type, appId)
+ if (isTree) {
+ oldState.mutateSystemState().mutatePermissionTrees().put(permissionName, permission)
+ } else {
+ oldState.mutateSystemState().mutatePermissions().put(permissionName, permission)
+ }
+ }
+
+ private fun createSystemStatePermissionGroup(packageName: String, permissionGroupName: String) {
+ @Suppress("DEPRECATION")
+ val permissionGroupInfo = PermissionGroupInfo().apply {
+ name = permissionGroupName
+ this.packageName = packageName
+ }
+ oldState.mutateSystemState().mutatePermissionGroups()[permissionGroupName] =
+ permissionGroupInfo
+ }
+
+ fun getPermissionFlags(
+ appId: Int,
+ userId: Int,
+ permissionName: String,
+ state: MutableAccessState = newState
+ ): Int =
+ state.userStates[userId]?.appIdPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
+
+ companion object {
+ private const val PACKAGE_NAME_0 = "packageName0"
+ private const val PACKAGE_NAME_1 = "packageName1"
+
+ private const val APP_ID_0 = 0
+ private const val APP_ID_1 = 1
+
+ private const val PERMISSION_NAME_0 = "permissionName0"
+ private const val PERMISSION_NAME_1 = "permissionName1"
+
+ private const val PERMISSION_GROUP_NAME_0 = "permissionGroupName0"
+ private const val PERMISSION_GROUP_NAME_1 = "permissionGroupName1"
+
+ private const val USER_ID_0 = 0
+ private const val USER_ID_1 = 1
+ }
+}