diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt index dd5cd2d3dd052..5fe17e5de34cf 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt @@ -24,7 +24,6 @@ import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.theme.SettingsTheme -import com.android.settingslib.spa.framework.util.normalize import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.scaffold.RegularScaffold @@ -36,7 +35,7 @@ object ArgumentPageProvider : SettingsPageProvider { override fun buildEntry(arguments: Bundle?): List { if (!ArgumentPageModel.isValidArgument(arguments)) return emptyList() - val owner = SettingsPage(name, parameter.normalize(arguments)) + val owner = SettingsPage.create(name, parameter, arguments) val entryList = mutableListOf() entryList.add( SettingsEntryBuilder.create("string_param", owner) @@ -69,7 +68,7 @@ object ArgumentPageProvider : SettingsPageProvider { private fun buildInjectEntry(arguments: Bundle?): SettingsEntryBuilder? { if (!ArgumentPageModel.isValidArgument(arguments)) return null - return SettingsEntryBuilder.createInject(name, parameter.normalize(arguments)) + return SettingsEntryBuilder.createInject(SettingsPage.create(name, parameter, arguments)) // Set attributes .setIsAllowSearch(false) .setUiLayoutFn { @@ -80,14 +79,8 @@ object ArgumentPageProvider : SettingsPageProvider { fun buildRootPages(): List { return listOf( - SettingsPage( - ArgumentPageModel.name, - ArgumentPageModel.buildArgument("foo") - ), - SettingsPage( - ArgumentPageModel.name, - ArgumentPageModel.buildArgument("bar") - ), + SettingsPage.create(name, parameter, ArgumentPageModel.buildArgument("foo")), + SettingsPage.create(name, parameter, ArgumentPageModel.buildArgument("bar")), ) } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt index a38f5ec1361fa..98734dac648ed 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt @@ -18,6 +18,8 @@ package com.android.settingslib.spa.framework.common import android.os.Bundle import androidx.compose.runtime.Composable +import androidx.navigation.NamedNavArgument +import com.android.settingslib.spa.framework.util.normalize const val INJECT_ENTRY_NAME = "INJECT" const val ROOT_ENTRY_NAME = "ROOT" @@ -35,9 +37,20 @@ data class UiData(val title: String = "") /** * Defines data to identify a Settings page. */ -data class SettingsPage(val name: String = "", val args: Bundle? = null) { +data class SettingsPage(val name: String = "", val arguments: Bundle? = null) { override fun toString(): String { - return name + args?.toString() + val argsStr = arguments?.toString()?.removeRange(0, 6) ?: "" + return name + argsStr + } + + companion object { + fun create( + name: String, + parameter: List = emptyList(), + arguments: Bundle? = null + ): SettingsPage { + return SettingsPage(name, parameter.normalize(arguments)) + } } } @@ -45,9 +58,14 @@ data class SettingsPage(val name: String = "", val args: Bundle? = null) { * Defines data of a Settings entry. */ data class SettingsEntry( - // The unique id of this entry + // The unique id of this entry. + // By default, it is computed by name + owner + fromPage + toPage val id: String, + // The display name of this entry, which is used to be shown in hierarchy. + // By default, it is computed by name + owner + val displayName: String, + val name: String, val owner: SettingsPage, @@ -89,11 +107,7 @@ data class SettingsEntry( val uiLayout: (@Composable () -> Unit) = {}, ) { override fun toString(): String { - return listOf( - name, - owner.toString(), - "(${fromPage?.toString()}-${toPage?.toString()})" - ).joinToString("-") + return displayName + "(${fromPage?.toString()}->${toPage?.toString()})" } } @@ -102,6 +116,7 @@ data class SettingsEntry( */ class SettingsEntryBuilder(private val name: String, private val owner: SettingsPage) { private var uniqueId: String? = null + private var displayName: String? = null private var fromPage: SettingsPage? = null private var toPage: SettingsPage? = null private var isAllowSearch: Boolean? = null @@ -112,6 +127,7 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings fun build(): SettingsEntry { return SettingsEntry( id = computeUniqueId(), + displayName = computeDisplayName(), name = name, owner = owner, @@ -153,7 +169,9 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings } private fun computeUniqueId(): String = - uniqueId ?: name + owner.toString() + fromPage?.toString() + toPage?.toString() + uniqueId ?: "$owner:$name" + fromPage?.toString() + toPage?.toString() + + private fun computeDisplayName(): String = displayName ?: "$owner:$name" private fun computeSearchable(): Boolean = isAllowSearch ?: false @@ -162,33 +180,16 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings return SettingsEntryBuilder(entryName, owner) } - fun create( - entryName: String, - ownerPageName: String, - ownerPageArgs: Bundle? = null - ): SettingsEntryBuilder { - val owner = SettingsPage(ownerPageName, ownerPageArgs) - return create(entryName, owner) + fun createLinkFrom(entryName: String, owner: SettingsPage): SettingsEntryBuilder { + return create(entryName, owner).setLink(fromPage = owner) } fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder { return create(entryName, owner).setLink(toPage = owner) } - fun createLinkTo( - entryName: String, - ownerPageName: String, - ownerPageArgs: Bundle? = null - ): SettingsEntryBuilder { - val owner = SettingsPage(ownerPageName, ownerPageArgs) - return createLinkTo(entryName, owner) - } - - fun createInject( - ownerPageName: String, - ownerPageArgs: Bundle? = null - ): SettingsEntryBuilder { - return createLinkTo(INJECT_ENTRY_NAME, ownerPageName, ownerPageArgs) + fun createInject(owner: SettingsPage): SettingsEntryBuilder { + return createLinkTo(INJECT_ENTRY_NAME, owner) } fun createRoot(page: SettingsPage): SettingsEntryBuilder { diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt index 8eda10d5b8741..e3a55e54c431f 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt @@ -50,7 +50,7 @@ class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) { val page = entry.toPage if (page == null || pageToEntryListMap.containsKey(page.toString())) continue val spp = sppRepository.getProviderOrNull(page.name) ?: continue - val newEntries = spp.buildEntry(page.args) + val newEntries = spp.buildEntry(page.arguments) pageToEntryListMap[page.toString()] = newEntries for (newEntry in newEntries) { if (!entryMap.containsKey(newEntry.id)) { diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt index 834a52e737a3d..4e768eb94e88f 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt @@ -40,18 +40,23 @@ fun List.navLink(arguments: Bundle? = null): String { return argsArray.joinToString("") { arg -> "/$arg" } } -fun List.normalize(arguments: Bundle? = null): Bundle { - if (arguments == null) return Bundle.EMPTY +fun List.normalize(arguments: Bundle? = null): Bundle? { + if (this.isEmpty()) return null val normArgs = Bundle() for (navArg in this) { when (navArg.argument.type) { NavType.StringType -> { - val value = arguments.getString(navArg.name) - if (value != null) normArgs.putString(navArg.name, value) + val value = arguments?.getString(navArg.name) + if (value != null) + normArgs.putString(navArg.name, value) + else + normArgs.putString("unset_" + navArg.name, null) } NavType.IntType -> { - if (arguments.containsKey(navArg.name)) + if (arguments != null && arguments.containsKey(navArg.name)) normArgs.putInt(navArg.name, arguments.getInt(navArg.name)) + else + normArgs.putString("unset_" + navArg.name, null) } } } 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 8282498725595..d4d8ea4567410 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 @@ -26,8 +26,12 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.core.os.bundleOf import androidx.navigation.NavType import androidx.navigation.navArgument +import com.android.settingslib.spa.framework.common.SettingsEntry +import com.android.settingslib.spa.framework.common.SettingsEntryBuilder +import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.widget.preference.SwitchPreference @@ -37,27 +41,37 @@ import com.android.settingslib.spaprivileged.model.app.PackageManagers import com.android.settingslib.spaprivileged.model.app.toRoute import kotlinx.coroutines.Dispatchers -private const val NAME = "TogglePermissionAppInfoPage" +private const val ENTRY_NAME = "AllowControl" private const val PERMISSION = "permission" private const val PACKAGE_NAME = "packageName" private const val USER_ID = "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 { - override val name = NAME + override val name = PAGE_NAME - override val parameter = listOf( - navArgument(PERMISSION) { type = NavType.StringType }, - navArgument(PACKAGE_NAME) { type = NavType.StringType }, - navArgument(USER_ID) { type = NavType.IntType }, - ) + override val parameter = PAGE_PARAMETER + + override fun buildEntry(arguments: Bundle?): List { + val owner = SettingsPage.create(name, parameter, arguments) + val entryList = mutableListOf() + entryList.add( + SettingsEntryBuilder.create(ENTRY_NAME, owner).setIsAllowSearch(false).build() + ) + return entryList + } @Composable override fun Page(arguments: Bundle?) { - checkNotNull(arguments) - val permissionType = checkNotNull(arguments.getString(PERMISSION)) - val packageName = checkNotNull(arguments.getString(PACKAGE_NAME)) + 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) @@ -66,7 +80,12 @@ internal class TogglePermissionAppInfoPageProvider( companion object { @Composable internal fun navigator(permissionType: String, app: ApplicationInfo) = - navigator(route = "$NAME/$permissionType/${app.toRoute()}") + navigator(route = "$PAGE_NAME/$permissionType/${app.toRoute()}") + + internal fun buildPageId(permissionType: String): SettingsPage { + return SettingsPage.create( + PAGE_NAME, PAGE_PARAMETER, bundleOf(PERMISSION to permissionType)) + } } } diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt index 3cc5854b95e40..ef47e95a5a2cb 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt @@ -21,6 +21,7 @@ import android.content.pm.ApplicationInfo import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource +import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.rememberContext import com.android.settingslib.spa.framework.util.asyncMapItem @@ -52,6 +53,10 @@ interface TogglePermissionAppListProvider { fun createModel(context: Context): TogglePermissionAppListModel + fun buildInjectEntry(): SettingsEntryBuilder { + return TogglePermissionAppListPageProvider.buildInjectEntry(permissionType) + } + @Composable fun EntryItem() { val listModel = rememberContext(::createModel) diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt index ca6ba84185ec8..f91a34a131c5e 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt @@ -25,32 +25,54 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.core.os.bundleOf import androidx.navigation.NavType import androidx.navigation.navArgument +import com.android.settingslib.spa.framework.common.SettingsEntry +import com.android.settingslib.spa.framework.common.SettingsEntryBuilder +import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.framework.util.getStringArg import com.android.settingslib.spaprivileged.R import com.android.settingslib.spaprivileged.model.app.AppListModel import com.android.settingslib.spaprivileged.model.app.AppRecord import kotlinx.coroutines.flow.Flow -private const val NAME = "TogglePermissionAppList" +private const val ENTRY_NAME = "AppList" private const val PERMISSION = "permission" +private const val PAGE_NAME = "TogglePermissionAppList" +private val PAGE_PARAMETER = listOf( + navArgument(PERMISSION) { type = NavType.StringType }, +) internal class TogglePermissionAppListPageProvider( private val appListTemplate: TogglePermissionAppListTemplate, ) : SettingsPageProvider { - override val name = NAME + override val name = PAGE_NAME - override val parameter = listOf( - navArgument(PERMISSION) { type = NavType.StringType }, - ) + override val parameter = PAGE_PARAMETER + + override fun buildEntry(arguments: Bundle?): List { + val permissionType = parameter.getStringArg(PERMISSION, arguments)!! + val appListPage = SettingsPage.create(name, parameter, arguments) + val appInfoPage = TogglePermissionAppInfoPageProvider.buildPageId(permissionType) + val entryList = mutableListOf() + // TODO: add more categories, such as personal, work, cloned, etc. + for (category in listOf("personal")) { + entryList.add( + SettingsEntryBuilder.createLinkFrom("${ENTRY_NAME}_$category", appListPage) + .setLink(toPage = appInfoPage) + .setIsAllowSearch(false) + .build() + ) + } + return entryList + } @Composable override fun Page(arguments: Bundle?) { - checkNotNull(arguments) - val permissionType = checkNotNull(arguments.getString(PERMISSION)) - TogglePermissionAppList(permissionType) + TogglePermissionAppList(arguments?.getString(PERMISSION)!!) } @Composable @@ -80,10 +102,16 @@ internal class TogglePermissionAppListPageProvider( * * Expose route to enable enter from non-SPA pages. */ - internal fun getRoute(permissionType: String) = "$NAME/$permissionType" + internal fun getRoute(permissionType: String) = "$PAGE_NAME/$permissionType" @Composable internal fun navigator(permissionType: String) = navigator(route = getRoute(permissionType)) + + internal fun buildInjectEntry(permissionType: String): SettingsEntryBuilder { + val appListPage = SettingsPage.create( + PAGE_NAME, PAGE_PARAMETER, bundleOf(PERMISSION to permissionType)) + return SettingsEntryBuilder.createInject(appListPage).setIsAllowSearch(false) + } } }