Loading services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionStatesTest.kt +2 −3 Original line number Diff line number Diff line Loading @@ -43,8 +43,7 @@ class AppIdPermissionPolicyPermissionStatesTest : BaseAppIdPermissionPolicyTest( @Parameterized.Parameter(0) lateinit var action: Action @Before override fun setUp() { super.setUp() fun setUp() { if (action == Action.ON_USER_ADDED) { createUserState(USER_ID_NEW) } Loading services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt 0 → 100644 +430 −0 Original line number Diff line number Diff line /* * 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.PermissionGroupInfo import android.content.pm.PermissionInfo import com.android.server.permission.access.GetStateScope 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.testutils.mock import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.junit.Test import org.mockito.Mockito.times import org.mockito.Mockito.verify class AppIdPermissionPolicyTest : BaseAppIdPermissionPolicyTest() { @Test fun testOnAppIdRemoved_appIdIsRemoved_permissionFlagsCleared() { val parsedPermission = mockParsedPermission(PERMISSION_NAME_0, PACKAGE_NAME_0) val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage(PACKAGE_NAME_0, permissions = listOf(parsedPermission)) ) val requestingPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(requestingPackageState) addPermission(parsedPermission) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.INSTALL_GRANTED) mutateState { with(appIdPermissionPolicy) { onAppIdRemoved(APP_ID_1) } } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = 0 assertWithMessage( "After onAppIdRemoved() is called for appId $APP_ID_1 that requests a permission" + " owns by appId $APP_ID_0 with existing permission flags. The actual permission" + " flags $actualFlags should be null" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnStorageVolumeMounted_nonSystemAppAfterNonSystemUpdate_remainsRevoked() { val permissionOwnerPackageState = mockPackageState(APP_ID_0, mockSimpleAndroidPackage()) val installedPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(installedPackageState) addPermission(defaultPermission) val oldFlags = PermissionFlags.INSTALL_REVOKED setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags) mutateState { with(appIdPermissionPolicy) { onStorageVolumeMounted(null, listOf(installedPackageState.packageName), false) } } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onStorageVolumeMounted() is called for a non-system app that requests a normal" + " permission with existing INSTALL_REVOKED flag after a non-system-update" + " (such as an OTA update), the actual permission flags should remain revoked." + " The actual permission flags $actualFlags should match the expected flags" + " $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageRemoved_packageIsRemoved_permissionDefinitionsAndStatesAreUpdated() { val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage( PACKAGE_NAME_0, requestedPermissions = setOf(PERMISSION_NAME_0), permissions = listOf(defaultPermission) ) ) val requestingPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(requestingPackageState) addPermission(defaultPermission) val oldFlags = PermissionFlags.INSTALL_GRANTED setPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0, oldFlags) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags) mutateState { removePackageState(permissionOwnerPackageState) with(appIdPermissionPolicy) { onPackageRemoved(PACKAGE_NAME_0, APP_ID_0) } } assertWithMessage( "After onPackageRemoved() is called for a permission owner, the permission" + " definitions owned by this package should be removed" ) .that(getPermission(PERMISSION_NAME_0)) .isNull() val app0ActualFlags = getPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0) val app0ExpectedNewFlags = 0 assertWithMessage( "After onPackageRemoved() is called for a permission owner, the permission states of" + " this app should be trimmed. The actual permission flags $app0ActualFlags should" + " match the expected flags $app0ExpectedNewFlags" ) .that(app0ActualFlags) .isEqualTo(app0ExpectedNewFlags) val app1ActualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val app1ExpectedNewFlags = PermissionFlags.INSTALL_REVOKED assertWithMessage( "After onPackageRemoved() is called for a permission owner, the permission states of" + " the permission requester should remain unchanged. The actual permission flags" + " $app1ActualFlags should match the expected flags $app1ExpectedNewFlags" ) .that(app1ActualFlags) .isEqualTo(app1ExpectedNewFlags) } @Test fun testOnPackageInstalled_nonSystemAppIsInstalled_upgradeExemptFlagIsCleared() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.UPGRADE_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = PermissionFlags.SOFT_RESTRICTED assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " soft restricted permission, UPGRADE_EXEMPT flag should be removed. The actual" + " permission flags $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_systemAppIsInstalled_upgradeExemptFlagIsRetained() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.UPGRADE_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED, isInstalledPackageSystem = true ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onPackageInstalled() is called for a system app that requests a runtime" + " soft restricted permission, UPGRADE_EXEMPT flag should be retained. The actual" + " permission flags $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_requestedPermissionAlsoRequestedBySystemApp_exemptFlagIsRetained() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.UPGRADE_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED ) { val systemAppPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_2, requestedPermissions = setOf(PERMISSION_NAME_0)), isSystem = true ) addPackageState(systemAppPackageState) } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " soft restricted permission, and that permission is also requested by a system" + " app in the same appId, UPGRADE_EXEMPT flag should be retained. The actual" + " permission flags $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_restrictedPermissionsNotExempt_getsRestrictionFlags() { val oldFlags = PermissionFlags.RESTRICTION_REVOKED testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_HARD_RESTRICTED ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " hard restricted permission that is not exempted. The actual permission flags" + " $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_restrictedPermissionsIsExempted_clearsRestrictionFlags() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.INSTALLER_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = PermissionFlags.INSTALLER_EXEMPT assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " soft restricted permission that is exempted. The actual permission flags" + " $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } private fun testOnPackageInstalled( oldFlags: Int, permissionInfoFlags: Int = 0, isInstalledPackageSystem: Boolean = false, additionalSetup: () -> Unit ) { val parsedPermission = mockParsedPermission( PERMISSION_NAME_0, PACKAGE_NAME_0, protectionLevel = PermissionInfo.PROTECTION_DANGEROUS, flags = permissionInfoFlags ) val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage(PACKAGE_NAME_0, permissions = listOf(parsedPermission)) ) addPackageState(permissionOwnerPackageState) addPermission(parsedPermission) additionalSetup() mutateState { val installedPackageState = mockPackageState( APP_ID_1, mockAndroidPackage( PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0), ), isSystem = isInstalledPackageSystem, ) addPackageState(installedPackageState, newState) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags, newState) with(appIdPermissionPolicy) { onPackageInstalled(installedPackageState, USER_ID_0) } } } @Test fun testOnStateMutated_notEmpty_isCalledForEachListener() { val mockListener = mock<AppIdPermissionPolicy.OnPermissionFlagsChangedListener> {} appIdPermissionPolicy.addOnPermissionFlagsChangedListener(mockListener) GetStateScope(oldState).apply { with(appIdPermissionPolicy) { onStateMutated() } } verify(mockListener, times(1)).onStateMutated() } @Test fun testGetPermissionTrees() { val permissionTrees: IndexedMap<String, Permission> GetStateScope(oldState).apply { with(appIdPermissionPolicy) { permissionTrees = getPermissionTrees() } } assertThat(oldState.systemState.permissionTrees).isEqualTo(permissionTrees) } @Test fun testFindPermissionTree() { val permissionTree = createSimplePermission(isTree = true) val actualPermissionTree: Permission? oldState.mutateSystemState().mutatePermissionTrees()[PERMISSION_TREE_NAME] = permissionTree GetStateScope(oldState).apply { with(appIdPermissionPolicy) { actualPermissionTree = findPermissionTree(PERMISSION_BELONGS_TO_A_TREE) } } assertThat(actualPermissionTree).isEqualTo(permissionTree) } @Test fun testAddPermissionTree() { val permissionTree = createSimplePermission(isTree = true) mutateState { with(appIdPermissionPolicy) { addPermissionTree(permissionTree) } } assertThat(newState.systemState.permissionTrees[PERMISSION_TREE_NAME]) .isEqualTo(permissionTree) } @Test fun testGetPermissionGroups() { val permissionGroups: IndexedMap<String, PermissionGroupInfo> GetStateScope(oldState).apply { with(appIdPermissionPolicy) { permissionGroups = getPermissionGroups() } } assertThat(oldState.systemState.permissionGroups).isEqualTo(permissionGroups) } @Test fun testGetPermissions() { val permissions: IndexedMap<String, Permission> GetStateScope(oldState).apply { with(appIdPermissionPolicy) { permissions = getPermissions() } } assertThat(oldState.systemState.permissions).isEqualTo(permissions) } @Test fun testAddPermission() { val permission = createSimplePermission() mutateState { with(appIdPermissionPolicy) { addPermission(permission) } } assertThat(newState.systemState.permissions[PERMISSION_NAME_0]).isEqualTo(permission) } @Test fun testRemovePermission() { val permission = createSimplePermission() mutateState { with(appIdPermissionPolicy) { addPermission(permission) removePermission(permission) } } assertThat(newState.systemState.permissions[PERMISSION_NAME_0]).isNull() } @Test fun testGetUidPermissionFlags() { val uidPermissionFlags: IndexedMap<String, Int>? GetStateScope(oldState).apply { with(appIdPermissionPolicy) { uidPermissionFlags = getUidPermissionFlags(APP_ID_0, USER_ID_0) } } assertThat(oldState.userStates[USER_ID_0]!!.appIdPermissionFlags[APP_ID_0]) .isEqualTo(uidPermissionFlags) } @Test fun testUpdateAndGetPermissionFlags() { val flags = PermissionFlags.INSTALL_GRANTED var actualFlags = 0 mutateState { with(appIdPermissionPolicy) { updatePermissionFlags( APP_ID_0, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.MASK_ALL, flags ) actualFlags = getPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0) } } assertThat(actualFlags).isEqualTo(flags) } } services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BaseAppIdPermissionPolicyTest.kt +26 −80 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ 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.permission.access.util.hasBits import com.android.server.pm.parsing.PackageInfoUtils import com.android.server.pm.pkg.AndroidPackage Loading @@ -45,10 +44,8 @@ import com.android.server.pm.pkg.component.ParsedPermissionGroup import com.android.server.testutils.any 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 import org.mockito.ArgumentMatchers.anyLong Loading @@ -56,7 +53,7 @@ import org.mockito.ArgumentMatchers.anyLong * Mocking unit test for AppIdPermissionPolicy. */ @RunWith(AndroidJUnit4::class) open class BaseAppIdPermissionPolicyTest { abstract class BaseAppIdPermissionPolicyTest { protected lateinit var oldState: MutableAccessState protected lateinit var newState: MutableAccessState Loading @@ -80,7 +77,7 @@ open class BaseAppIdPermissionPolicyTest { .build() @Before open fun setUp() { fun baseSetUp() { oldState = MutableAccessState() createUserState(USER_ID_0) oldState.mutateExternalState().setPackageStates(ArrayMap()) Loading Loading @@ -139,78 +136,6 @@ open class BaseAppIdPermissionPolicyTest { } } @Test fun testOnAppIdRemoved_appIdIsRemoved_permissionFlagsCleared() { val parsedPermission = mockParsedPermission(PERMISSION_NAME_0, PACKAGE_NAME_0) val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage(PACKAGE_NAME_0, permissions = listOf(parsedPermission)) ) val requestingPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(requestingPackageState) addPermission(parsedPermission) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.INSTALL_GRANTED) mutateState { with(appIdPermissionPolicy) { onAppIdRemoved(APP_ID_1) } } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = 0 assertWithMessage( "After onAppIdRemoved() is called for appId $APP_ID_1 that requests a permission" + " owns by appId $APP_ID_0 with existing permission flags. The actual permission" + " flags $actualFlags should be null" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageRemoved_packageIsRemoved_permissionsAreTrimmedAndStatesAreEvaluated() { // TODO // shouldn't reuse test cases because it's really different despite it's also for // trim permission states. It's different because it's package removal } @Test fun testOnPackageInstalled_nonSystemAppIsInstalled_upgradeExemptFlagIsCleared() { // TODO // should be fine for it to be its own test cases and not to re-use // clearRestrictedPermissionImplicitExemption } @Test fun testOnPackageInstalled_systemAppIsInstalled_upgradeExemptFlagIsRetained() { // TODO } @Test fun testOnPackageInstalled_requestedPermissionAlsoRequestedBySystemApp_exemptFlagIsRetained() { // TODO } @Test fun testOnPackageInstalled_restrictedPermissionsNotExempt_getsRestrictionFlags() { // TODO } @Test fun testOnPackageInstalled_restrictedPermissionsIsExempted_clearsRestrictionFlags() { // TODO } @Test fun testOnStateMutated_notEmpty_isCalledForEachListener() { // TODO } /** * Mock an AndroidPackage with PACKAGE_NAME_0, PERMISSION_NAME_0 and PERMISSION_GROUP_NAME_0 */ Loading @@ -221,6 +146,15 @@ open class BaseAppIdPermissionPolicyTest { permissions = listOf(defaultPermissionTree, defaultPermission) ) protected fun createSimplePermission(isTree: Boolean = false): Permission { val parsedPermission = if (isTree) { defaultPermissionTree } else { defaultPermission } val permissionInfo = PackageInfoUtils.generatePermissionInfo( parsedPermission, PackageManager.GET_META_DATA.toLong() )!! return Permission(permissionInfo, true, Permission.TYPE_MANIFEST, APP_ID_0) } protected inline fun mutateState(action: MutateStateScope.() -> Unit) { newState = oldState.toMutable() MutateStateScope(oldState, newState).action() Loading Loading @@ -330,15 +264,26 @@ open class BaseAppIdPermissionPolicyTest { ) { state.mutateExternalState().apply { setPackageStates( packageStates.toMutableMap().apply { put(packageState.packageName, packageState) } packageStates.toMutableMap().apply { put(packageState.packageName, packageState) } ) mutateAppIdPackageNames().mutateOrPut(packageState.appId) { MutableIndexedListSet() } .add(packageState.packageName) } } protected fun removePackageState( packageState: PackageState, state: MutableAccessState = oldState ) { state.mutateExternalState().apply { setPackageStates( packageStates.toMutableMap().apply { remove(packageState.packageName) } ) mutateAppIdPackageNames().mutateOrPut(packageState.appId) { MutableIndexedListSet() } .remove(packageState.packageName) } } protected fun addDisabledSystemPackageState( packageState: PackageState, state: MutableAccessState = oldState Loading Loading @@ -429,6 +374,7 @@ open class BaseAppIdPermissionPolicyTest { @JvmStatic protected val PERMISSION_NAME_0 = "permissionName0" @JvmStatic protected val PERMISSION_NAME_1 = "permissionName1" @JvmStatic protected val PERMISSION_NAME_2 = "permissionName2" @JvmStatic protected val PERMISSION_BELONGS_TO_A_TREE = "permissionTree.permission" @JvmStatic protected val PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE @JvmStatic protected val PERMISSION_POST_NOTIFICATIONS = Loading services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionResetTest.kt +1 −1 File changed.Contains only whitespace changes. Show changes Loading
services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionStatesTest.kt +2 −3 Original line number Diff line number Diff line Loading @@ -43,8 +43,7 @@ class AppIdPermissionPolicyPermissionStatesTest : BaseAppIdPermissionPolicyTest( @Parameterized.Parameter(0) lateinit var action: Action @Before override fun setUp() { super.setUp() fun setUp() { if (action == Action.ON_USER_ADDED) { createUserState(USER_ID_NEW) } Loading
services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt 0 → 100644 +430 −0 Original line number Diff line number Diff line /* * 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.PermissionGroupInfo import android.content.pm.PermissionInfo import com.android.server.permission.access.GetStateScope 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.testutils.mock import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.junit.Test import org.mockito.Mockito.times import org.mockito.Mockito.verify class AppIdPermissionPolicyTest : BaseAppIdPermissionPolicyTest() { @Test fun testOnAppIdRemoved_appIdIsRemoved_permissionFlagsCleared() { val parsedPermission = mockParsedPermission(PERMISSION_NAME_0, PACKAGE_NAME_0) val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage(PACKAGE_NAME_0, permissions = listOf(parsedPermission)) ) val requestingPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(requestingPackageState) addPermission(parsedPermission) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.INSTALL_GRANTED) mutateState { with(appIdPermissionPolicy) { onAppIdRemoved(APP_ID_1) } } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = 0 assertWithMessage( "After onAppIdRemoved() is called for appId $APP_ID_1 that requests a permission" + " owns by appId $APP_ID_0 with existing permission flags. The actual permission" + " flags $actualFlags should be null" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnStorageVolumeMounted_nonSystemAppAfterNonSystemUpdate_remainsRevoked() { val permissionOwnerPackageState = mockPackageState(APP_ID_0, mockSimpleAndroidPackage()) val installedPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(installedPackageState) addPermission(defaultPermission) val oldFlags = PermissionFlags.INSTALL_REVOKED setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags) mutateState { with(appIdPermissionPolicy) { onStorageVolumeMounted(null, listOf(installedPackageState.packageName), false) } } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onStorageVolumeMounted() is called for a non-system app that requests a normal" + " permission with existing INSTALL_REVOKED flag after a non-system-update" + " (such as an OTA update), the actual permission flags should remain revoked." + " The actual permission flags $actualFlags should match the expected flags" + " $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageRemoved_packageIsRemoved_permissionDefinitionsAndStatesAreUpdated() { val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage( PACKAGE_NAME_0, requestedPermissions = setOf(PERMISSION_NAME_0), permissions = listOf(defaultPermission) ) ) val requestingPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(requestingPackageState) addPermission(defaultPermission) val oldFlags = PermissionFlags.INSTALL_GRANTED setPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0, oldFlags) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags) mutateState { removePackageState(permissionOwnerPackageState) with(appIdPermissionPolicy) { onPackageRemoved(PACKAGE_NAME_0, APP_ID_0) } } assertWithMessage( "After onPackageRemoved() is called for a permission owner, the permission" + " definitions owned by this package should be removed" ) .that(getPermission(PERMISSION_NAME_0)) .isNull() val app0ActualFlags = getPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0) val app0ExpectedNewFlags = 0 assertWithMessage( "After onPackageRemoved() is called for a permission owner, the permission states of" + " this app should be trimmed. The actual permission flags $app0ActualFlags should" + " match the expected flags $app0ExpectedNewFlags" ) .that(app0ActualFlags) .isEqualTo(app0ExpectedNewFlags) val app1ActualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val app1ExpectedNewFlags = PermissionFlags.INSTALL_REVOKED assertWithMessage( "After onPackageRemoved() is called for a permission owner, the permission states of" + " the permission requester should remain unchanged. The actual permission flags" + " $app1ActualFlags should match the expected flags $app1ExpectedNewFlags" ) .that(app1ActualFlags) .isEqualTo(app1ExpectedNewFlags) } @Test fun testOnPackageInstalled_nonSystemAppIsInstalled_upgradeExemptFlagIsCleared() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.UPGRADE_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = PermissionFlags.SOFT_RESTRICTED assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " soft restricted permission, UPGRADE_EXEMPT flag should be removed. The actual" + " permission flags $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_systemAppIsInstalled_upgradeExemptFlagIsRetained() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.UPGRADE_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED, isInstalledPackageSystem = true ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onPackageInstalled() is called for a system app that requests a runtime" + " soft restricted permission, UPGRADE_EXEMPT flag should be retained. The actual" + " permission flags $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_requestedPermissionAlsoRequestedBySystemApp_exemptFlagIsRetained() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.UPGRADE_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED ) { val systemAppPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_2, requestedPermissions = setOf(PERMISSION_NAME_0)), isSystem = true ) addPackageState(systemAppPackageState) } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " soft restricted permission, and that permission is also requested by a system" + " app in the same appId, UPGRADE_EXEMPT flag should be retained. The actual" + " permission flags $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_restrictedPermissionsNotExempt_getsRestrictionFlags() { val oldFlags = PermissionFlags.RESTRICTION_REVOKED testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_HARD_RESTRICTED ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = oldFlags assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " hard restricted permission that is not exempted. The actual permission flags" + " $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageInstalled_restrictedPermissionsIsExempted_clearsRestrictionFlags() { val oldFlags = PermissionFlags.SOFT_RESTRICTED or PermissionFlags.INSTALLER_EXEMPT testOnPackageInstalled( oldFlags, permissionInfoFlags = PermissionInfo.FLAG_SOFT_RESTRICTED ) {} val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = PermissionFlags.INSTALLER_EXEMPT assertWithMessage( "After onPackageInstalled() is called for a non-system app that requests a runtime" + " soft restricted permission that is exempted. The actual permission flags" + " $actualFlags should match the expected flags $expectedNewFlags" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } private fun testOnPackageInstalled( oldFlags: Int, permissionInfoFlags: Int = 0, isInstalledPackageSystem: Boolean = false, additionalSetup: () -> Unit ) { val parsedPermission = mockParsedPermission( PERMISSION_NAME_0, PACKAGE_NAME_0, protectionLevel = PermissionInfo.PROTECTION_DANGEROUS, flags = permissionInfoFlags ) val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage(PACKAGE_NAME_0, permissions = listOf(parsedPermission)) ) addPackageState(permissionOwnerPackageState) addPermission(parsedPermission) additionalSetup() mutateState { val installedPackageState = mockPackageState( APP_ID_1, mockAndroidPackage( PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0), ), isSystem = isInstalledPackageSystem, ) addPackageState(installedPackageState, newState) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags, newState) with(appIdPermissionPolicy) { onPackageInstalled(installedPackageState, USER_ID_0) } } } @Test fun testOnStateMutated_notEmpty_isCalledForEachListener() { val mockListener = mock<AppIdPermissionPolicy.OnPermissionFlagsChangedListener> {} appIdPermissionPolicy.addOnPermissionFlagsChangedListener(mockListener) GetStateScope(oldState).apply { with(appIdPermissionPolicy) { onStateMutated() } } verify(mockListener, times(1)).onStateMutated() } @Test fun testGetPermissionTrees() { val permissionTrees: IndexedMap<String, Permission> GetStateScope(oldState).apply { with(appIdPermissionPolicy) { permissionTrees = getPermissionTrees() } } assertThat(oldState.systemState.permissionTrees).isEqualTo(permissionTrees) } @Test fun testFindPermissionTree() { val permissionTree = createSimplePermission(isTree = true) val actualPermissionTree: Permission? oldState.mutateSystemState().mutatePermissionTrees()[PERMISSION_TREE_NAME] = permissionTree GetStateScope(oldState).apply { with(appIdPermissionPolicy) { actualPermissionTree = findPermissionTree(PERMISSION_BELONGS_TO_A_TREE) } } assertThat(actualPermissionTree).isEqualTo(permissionTree) } @Test fun testAddPermissionTree() { val permissionTree = createSimplePermission(isTree = true) mutateState { with(appIdPermissionPolicy) { addPermissionTree(permissionTree) } } assertThat(newState.systemState.permissionTrees[PERMISSION_TREE_NAME]) .isEqualTo(permissionTree) } @Test fun testGetPermissionGroups() { val permissionGroups: IndexedMap<String, PermissionGroupInfo> GetStateScope(oldState).apply { with(appIdPermissionPolicy) { permissionGroups = getPermissionGroups() } } assertThat(oldState.systemState.permissionGroups).isEqualTo(permissionGroups) } @Test fun testGetPermissions() { val permissions: IndexedMap<String, Permission> GetStateScope(oldState).apply { with(appIdPermissionPolicy) { permissions = getPermissions() } } assertThat(oldState.systemState.permissions).isEqualTo(permissions) } @Test fun testAddPermission() { val permission = createSimplePermission() mutateState { with(appIdPermissionPolicy) { addPermission(permission) } } assertThat(newState.systemState.permissions[PERMISSION_NAME_0]).isEqualTo(permission) } @Test fun testRemovePermission() { val permission = createSimplePermission() mutateState { with(appIdPermissionPolicy) { addPermission(permission) removePermission(permission) } } assertThat(newState.systemState.permissions[PERMISSION_NAME_0]).isNull() } @Test fun testGetUidPermissionFlags() { val uidPermissionFlags: IndexedMap<String, Int>? GetStateScope(oldState).apply { with(appIdPermissionPolicy) { uidPermissionFlags = getUidPermissionFlags(APP_ID_0, USER_ID_0) } } assertThat(oldState.userStates[USER_ID_0]!!.appIdPermissionFlags[APP_ID_0]) .isEqualTo(uidPermissionFlags) } @Test fun testUpdateAndGetPermissionFlags() { val flags = PermissionFlags.INSTALL_GRANTED var actualFlags = 0 mutateState { with(appIdPermissionPolicy) { updatePermissionFlags( APP_ID_0, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.MASK_ALL, flags ) actualFlags = getPermissionFlags(APP_ID_0, USER_ID_0, PERMISSION_NAME_0) } } assertThat(actualFlags).isEqualTo(flags) } }
services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BaseAppIdPermissionPolicyTest.kt +26 −80 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ 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.permission.access.util.hasBits import com.android.server.pm.parsing.PackageInfoUtils import com.android.server.pm.pkg.AndroidPackage Loading @@ -45,10 +44,8 @@ import com.android.server.pm.pkg.component.ParsedPermissionGroup import com.android.server.testutils.any 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 import org.mockito.ArgumentMatchers.anyLong Loading @@ -56,7 +53,7 @@ import org.mockito.ArgumentMatchers.anyLong * Mocking unit test for AppIdPermissionPolicy. */ @RunWith(AndroidJUnit4::class) open class BaseAppIdPermissionPolicyTest { abstract class BaseAppIdPermissionPolicyTest { protected lateinit var oldState: MutableAccessState protected lateinit var newState: MutableAccessState Loading @@ -80,7 +77,7 @@ open class BaseAppIdPermissionPolicyTest { .build() @Before open fun setUp() { fun baseSetUp() { oldState = MutableAccessState() createUserState(USER_ID_0) oldState.mutateExternalState().setPackageStates(ArrayMap()) Loading Loading @@ -139,78 +136,6 @@ open class BaseAppIdPermissionPolicyTest { } } @Test fun testOnAppIdRemoved_appIdIsRemoved_permissionFlagsCleared() { val parsedPermission = mockParsedPermission(PERMISSION_NAME_0, PACKAGE_NAME_0) val permissionOwnerPackageState = mockPackageState( APP_ID_0, mockAndroidPackage(PACKAGE_NAME_0, permissions = listOf(parsedPermission)) ) val requestingPackageState = mockPackageState( APP_ID_1, mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)) ) addPackageState(permissionOwnerPackageState) addPackageState(requestingPackageState) addPermission(parsedPermission) setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.INSTALL_GRANTED) mutateState { with(appIdPermissionPolicy) { onAppIdRemoved(APP_ID_1) } } val actualFlags = getPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0) val expectedNewFlags = 0 assertWithMessage( "After onAppIdRemoved() is called for appId $APP_ID_1 that requests a permission" + " owns by appId $APP_ID_0 with existing permission flags. The actual permission" + " flags $actualFlags should be null" ) .that(actualFlags) .isEqualTo(expectedNewFlags) } @Test fun testOnPackageRemoved_packageIsRemoved_permissionsAreTrimmedAndStatesAreEvaluated() { // TODO // shouldn't reuse test cases because it's really different despite it's also for // trim permission states. It's different because it's package removal } @Test fun testOnPackageInstalled_nonSystemAppIsInstalled_upgradeExemptFlagIsCleared() { // TODO // should be fine for it to be its own test cases and not to re-use // clearRestrictedPermissionImplicitExemption } @Test fun testOnPackageInstalled_systemAppIsInstalled_upgradeExemptFlagIsRetained() { // TODO } @Test fun testOnPackageInstalled_requestedPermissionAlsoRequestedBySystemApp_exemptFlagIsRetained() { // TODO } @Test fun testOnPackageInstalled_restrictedPermissionsNotExempt_getsRestrictionFlags() { // TODO } @Test fun testOnPackageInstalled_restrictedPermissionsIsExempted_clearsRestrictionFlags() { // TODO } @Test fun testOnStateMutated_notEmpty_isCalledForEachListener() { // TODO } /** * Mock an AndroidPackage with PACKAGE_NAME_0, PERMISSION_NAME_0 and PERMISSION_GROUP_NAME_0 */ Loading @@ -221,6 +146,15 @@ open class BaseAppIdPermissionPolicyTest { permissions = listOf(defaultPermissionTree, defaultPermission) ) protected fun createSimplePermission(isTree: Boolean = false): Permission { val parsedPermission = if (isTree) { defaultPermissionTree } else { defaultPermission } val permissionInfo = PackageInfoUtils.generatePermissionInfo( parsedPermission, PackageManager.GET_META_DATA.toLong() )!! return Permission(permissionInfo, true, Permission.TYPE_MANIFEST, APP_ID_0) } protected inline fun mutateState(action: MutateStateScope.() -> Unit) { newState = oldState.toMutable() MutateStateScope(oldState, newState).action() Loading Loading @@ -330,15 +264,26 @@ open class BaseAppIdPermissionPolicyTest { ) { state.mutateExternalState().apply { setPackageStates( packageStates.toMutableMap().apply { put(packageState.packageName, packageState) } packageStates.toMutableMap().apply { put(packageState.packageName, packageState) } ) mutateAppIdPackageNames().mutateOrPut(packageState.appId) { MutableIndexedListSet() } .add(packageState.packageName) } } protected fun removePackageState( packageState: PackageState, state: MutableAccessState = oldState ) { state.mutateExternalState().apply { setPackageStates( packageStates.toMutableMap().apply { remove(packageState.packageName) } ) mutateAppIdPackageNames().mutateOrPut(packageState.appId) { MutableIndexedListSet() } .remove(packageState.packageName) } } protected fun addDisabledSystemPackageState( packageState: PackageState, state: MutableAccessState = oldState Loading Loading @@ -429,6 +374,7 @@ open class BaseAppIdPermissionPolicyTest { @JvmStatic protected val PERMISSION_NAME_0 = "permissionName0" @JvmStatic protected val PERMISSION_NAME_1 = "permissionName1" @JvmStatic protected val PERMISSION_NAME_2 = "permissionName2" @JvmStatic protected val PERMISSION_BELONGS_TO_A_TREE = "permissionTree.permission" @JvmStatic protected val PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE @JvmStatic protected val PERMISSION_POST_NOTIFICATIONS = Loading
services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionResetTest.kt +1 −1 File changed.Contains only whitespace changes. Show changes