diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt index a618c3d0575b0..ae362c894e6db 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt @@ -74,6 +74,8 @@ interface RestrictionsProvider { fun restrictedModeState(): State } +typealias RestrictionsProviderFactory = (Context, Restrictions) -> RestrictionsProvider + internal class RestrictionsProviderImpl( private val context: Context, private val restrictions: Restrictions, diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt index 8b19c5b0e3195..0b45da67eaf73 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt @@ -16,11 +16,12 @@ package com.android.settingslib.spaprivileged.template.app +import android.content.pm.PackageInfo import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Footer -import com.android.settingslib.spaprivileged.model.app.PackageManagers +import com.android.settingslib.spaprivileged.model.app.IPackageManagers @Composable fun AppInfoPage( @@ -28,18 +29,16 @@ fun AppInfoPage( packageName: String, userId: Int, footerText: String, - content: @Composable () -> Unit, + packageManagers: IPackageManagers, + content: @Composable PackageInfo.() -> Unit, ) { + val packageInfo = remember(packageName, userId) { + packageManagers.getPackageInfoAsUser(packageName, userId) + } ?: return RegularScaffold(title = title) { - val appInfoProvider = remember { - PackageManagers.getPackageInfoAsUser(packageName, userId)?.let { packageInfo -> - AppInfoProvider(packageInfo) - } - } ?: return@RegularScaffold + remember(packageInfo) { AppInfoProvider(packageInfo) }.AppInfo(displayVersion = true) - appInfoProvider.AppInfo(displayVersion = true) - - content() + packageInfo.content() Footer(footerText) } diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt index 8287693c90ee0..5ae5adaff634c 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt @@ -19,6 +19,7 @@ package com.android.settingslib.spaprivileged.template.app import android.content.Context import android.content.pm.ApplicationInfo import android.os.Bundle +import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State @@ -38,23 +39,15 @@ import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import com.android.settingslib.spaprivileged.model.app.AppRecord +import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.PackageManagers import com.android.settingslib.spaprivileged.model.app.toRoute import com.android.settingslib.spaprivileged.model.enterprise.Restrictions +import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory +import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.template.preference.RestrictedSwitchPreference import kotlinx.coroutines.Dispatchers -private const val ENTRY_NAME = "AllowControl" -private const val PERMISSION = "permission" -private const val PACKAGE_NAME = "rt_packageName" -private const val USER_ID = "rt_userId" -private const val PAGE_NAME = "TogglePermissionAppInfoPage" -private val PAGE_PARAMETER = listOf( - navArgument(PERMISSION) { type = NavType.StringType }, - navArgument(PACKAGE_NAME) { type = NavType.StringType }, - navArgument(USER_ID) { type = NavType.IntType }, -) - internal class TogglePermissionAppInfoPageProvider( private val appListTemplate: TogglePermissionAppListTemplate, ) : SettingsPageProvider { @@ -64,11 +57,7 @@ internal class TogglePermissionAppInfoPageProvider( override fun buildEntry(arguments: Bundle?): List { val owner = SettingsPage.create(name, parameter = parameter, arguments = arguments) - val entryList = mutableListOf() - entryList.add( - SettingsEntryBuilder.create(ENTRY_NAME, owner).build() - ) - return entryList + return listOf(SettingsEntryBuilder.create("AllowControl", owner).build()) } @Composable @@ -76,11 +65,22 @@ internal class TogglePermissionAppInfoPageProvider( val permissionType = arguments?.getString(PERMISSION)!! val packageName = arguments.getString(PACKAGE_NAME)!! val userId = arguments.getInt(USER_ID) - val listModel = appListTemplate.rememberModel(permissionType) - TogglePermissionAppInfoPage(listModel, packageName, userId) + appListTemplate.rememberModel(permissionType) + .TogglePermissionAppInfoPage(packageName, userId) } companion object { + private const val PAGE_NAME = "TogglePermissionAppInfoPage" + private const val PERMISSION = "permission" + private const val PACKAGE_NAME = "rt_packageName" + private const val USER_ID = "rt_userId" + + private val PAGE_PARAMETER = listOf( + navArgument(PERMISSION) { type = NavType.StringType }, + navArgument(PACKAGE_NAME) { type = NavType.StringType }, + navArgument(USER_ID) { type = NavType.IntType }, + ) + @Composable fun navigator(permissionType: String, app: ApplicationInfo) = navigator(route = "$PAGE_NAME/$permissionType/${app.toRoute()}") @@ -116,43 +116,36 @@ internal class TogglePermissionAppInfoPageProvider( } } +@VisibleForTesting @Composable -private fun TogglePermissionAppInfoPage( - listModel: TogglePermissionAppListModel, +internal fun TogglePermissionAppListModel.TogglePermissionAppInfoPage( packageName: String, userId: Int, + packageManagers: IPackageManagers = PackageManagers, + restrictionsProviderFactory: RestrictionsProviderFactory = ::RestrictionsProviderImpl, ) { AppInfoPage( - title = stringResource(listModel.pageTitleResId), + title = stringResource(pageTitleResId), packageName = packageName, userId = userId, - footerText = stringResource(listModel.footerResId), + footerText = stringResource(footerResId), + packageManagers = packageManagers, ) { - val model = createSwitchModel(listModel, packageName, userId) ?: return@AppInfoPage - LaunchedEffect(model, Dispatchers.Default) { - model.initState() - } - RestrictedSwitchPreference(model, Restrictions(userId, listModel.switchRestrictionKeys)) + val model = createSwitchModel(applicationInfo) + val restrictions = Restrictions(userId, switchRestrictionKeys) + RestrictedSwitchPreference(model, restrictions, restrictionsProviderFactory) } } @Composable -private fun createSwitchModel( - listModel: TogglePermissionAppListModel, - packageName: String, - userId: Int, -): TogglePermissionSwitchModel? { - val record = remember { - PackageManagers.getApplicationInfoAsUser(packageName, userId)?.let { app -> - listModel.transformItem(app) - } - } ?: return null - +private fun TogglePermissionAppListModel.createSwitchModel( + app: ApplicationInfo, +): TogglePermissionSwitchModel { val context = LocalContext.current - val isAllowed = listModel.isAllowed(record) - return remember { - TogglePermissionSwitchModel(context, listModel, record, isAllowed) - } + val record = remember(app) { transformItem(app) } + val isAllowed = isAllowed(record) + return remember(record) { TogglePermissionSwitchModel(context, this, record, isAllowed) } + .also { model -> LaunchedEffect(model, Dispatchers.IO) { model.initState() } } } private class TogglePermissionSwitchModel( diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt index a003da81e06d2..b08b6dfa67a6d 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt @@ -38,19 +38,14 @@ import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode import com.android.settingslib.spaprivileged.model.enterprise.Restrictions -import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProvider +import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl @Composable -fun RestrictedSwitchPreference(model: SwitchPreferenceModel, restrictions: Restrictions) { - RestrictedSwitchPreferenceImpl(model, restrictions, ::RestrictionsProviderImpl) -} - -@Composable -internal fun RestrictedSwitchPreferenceImpl( +fun RestrictedSwitchPreference( model: SwitchPreferenceModel, restrictions: Restrictions, - restrictionsProviderFactory: (Context, Restrictions) -> RestrictionsProvider, + restrictionsProviderFactory: RestrictionsProviderFactory = ::RestrictionsProviderImpl, ) { if (restrictions.keys.isEmpty()) { SwitchPreference(model) diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt new file mode 100644 index 0000000000000..ecad08a0aca24 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt @@ -0,0 +1,153 @@ +/* + * 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.settingslib.spaprivileged.template.app + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.PackageInfo +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertIsNotEnabled +import androidx.compose.ui.test.assertIsOff +import androidx.compose.ui.test.assertIsOn +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.spaprivileged.model.app.IPackageManagers +import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted +import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider +import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListModel +import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListProvider +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.Mockito.`when` as whenever + +@RunWith(AndroidJUnit4::class) +class TogglePermissionAppInfoPageTest { + @get:Rule + val composeTestRule = createComposeRule() + + @get:Rule + val mockito: MockitoRule = MockitoJUnit.rule() + + private val context: Context = ApplicationProvider.getApplicationContext() + + @Mock + private lateinit var packageManagers: IPackageManagers + + private val fakeRestrictionsProvider = FakeRestrictionsProvider() + + private val appListTemplate = + TogglePermissionAppListTemplate(listOf(TestTogglePermissionAppListProvider)) + + private val appInfoPageProvider = TogglePermissionAppInfoPageProvider(appListTemplate) + + @Before + fun setUp() { + fakeRestrictionsProvider.restrictedMode = NoRestricted + whenever(packageManagers.getPackageInfoAsUser(PACKAGE_NAME, USER_ID)) + .thenReturn(PACKAGE_INFO) + } + + @Test + fun buildEntry() { + val entryList = appInfoPageProvider.buildEntry(null) + + assertThat(entryList).hasSize(1) + assertThat(entryList[0].displayName).isEqualTo("AllowControl") + } + + @Test + fun title_isDisplayed() { + val listModel = TestTogglePermissionAppListModel() + + setTogglePermissionAppInfoPage(listModel) + + composeTestRule.onNodeWithText(context.getString(listModel.pageTitleResId)) + .assertIsDisplayed() + } + + @Test + fun whenAllowed_switchIsOn() { + val listModel = TestTogglePermissionAppListModel(isAllowed = true) + + setTogglePermissionAppInfoPage(listModel) + + composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId)) + .assertIsOn() + } + + @Test + fun whenNotAllowed_switchIsOff() { + val listModel = TestTogglePermissionAppListModel(isAllowed = false) + + setTogglePermissionAppInfoPage(listModel) + + composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId)) + .assertIsOff() + } + + @Test + fun whenNotChangeable_switchNotEnabled() { + val listModel = TestTogglePermissionAppListModel(isAllowed = false, isChangeable = false) + + setTogglePermissionAppInfoPage(listModel) + + composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId)) + .assertIsDisplayed() + .assertIsNotEnabled() + } + + @Test + fun footer_isDisplayed() { + val listModel = TestTogglePermissionAppListModel() + + setTogglePermissionAppInfoPage(listModel) + + composeTestRule.onNodeWithText(context.getString(listModel.footerResId)) + .assertIsDisplayed() + } + + private fun setTogglePermissionAppInfoPage(listModel: TestTogglePermissionAppListModel) { + composeTestRule.setContent { + listModel.TogglePermissionAppInfoPage( + packageName = PACKAGE_NAME, + userId = USER_ID, + packageManagers = packageManagers, + restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider }, + ) + } + } + + private companion object { + const val USER_ID = 0 + const val PACKAGE_NAME = "package.name" + val APP = ApplicationInfo().apply { + packageName = PACKAGE_NAME + } + val PACKAGE_INFO = PackageInfo().apply { + packageName = PACKAGE_NAME + applicationInfo = APP + } + } +} diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListTest.kt index 2d169e0357fe7..1818f2d92f9cd 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListTest.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListTest.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.test.onNodeWithText import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settingslib.spaprivileged.test.R -import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListModel +import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListProvider import com.google.common.truth.Truth.assertThat import org.junit.Rule import org.junit.Test @@ -70,8 +70,3 @@ class TogglePermissionAppListTest { assertThat(createPageProviders.any { it is TogglePermissionAppInfoPageProvider }).isTrue() } } - -private object TestTogglePermissionAppListProvider : TogglePermissionAppListProvider { - override val permissionType = "test.PERMISSION" - override fun createModel(context: Context) = TestTogglePermissionAppListModel() -} diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt index 7f57025c5fe5c..a13c4835b5d5b 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt @@ -142,7 +142,7 @@ class RestrictedSwitchPreferenceTest { private fun setContent(restrictions: Restrictions) { composeTestRule.setContent { - RestrictedSwitchPreferenceImpl(switchPreferenceModel, restrictions) { _, _ -> + RestrictedSwitchPreference(switchPreferenceModel, restrictions) { _, _ -> fakeRestrictionsProvider } } diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt index 64bc11f0bac57..b13fbb3e8e41a 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt @@ -23,7 +23,10 @@ import com.android.settingslib.spaprivileged.test.R import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel import kotlinx.coroutines.flow.Flow -class TestTogglePermissionAppListModel : TogglePermissionAppListModel { +class TestTogglePermissionAppListModel( + private val isAllowed: Boolean? = null, + private val isChangeable: Boolean = false, +) : TogglePermissionAppListModel { override val pageTitleResId = R.string.test_permission_title override val switchTitleResId = R.string.test_permission_switch_title override val footerResId = R.string.test_permission_footer @@ -34,9 +37,9 @@ class TestTogglePermissionAppListModel : TogglePermissionAppListModel