diff --git a/packages/SettingsLib/SpaPrivileged/res/values/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values/strings.xml index b2302a58229cb..25dbe007bac79 100644 --- a/packages/SettingsLib/SpaPrivileged/res/values/strings.xml +++ b/packages/SettingsLib/SpaPrivileged/res/values/strings.xml @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + No apps. @@ -25,4 +25,6 @@ Allowed Not allowed + + version %1$s diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt index 6e1afd94fe294..99a08abad8b7e 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/Apps.kt @@ -22,4 +22,7 @@ import android.os.UserHandle val ApplicationInfo.userId: Int get() = UserHandle.getUserId(uid) +val ApplicationInfo.userHandle: UserHandle + get() = UserHandle.getUserHandleForUid(uid) + fun ApplicationInfo.toRoute() = "$packageName/$userId" diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt index f51d2dbfdeef2..c89ffe560eb72 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt @@ -17,6 +17,8 @@ package com.android.settingslib.spaprivileged.template.app import android.content.pm.ApplicationInfo +import android.content.pm.PackageInfo +import android.text.BidiFormatter import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -25,49 +27,60 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.Divider import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.compose.rememberDrawablePainter import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.widget.ui.SettingsBody import com.android.settingslib.spa.widget.ui.SettingsTitle -import com.android.settingslib.spaprivileged.model.app.PackageManagers +import com.android.settingslib.spaprivileged.R import com.android.settingslib.spaprivileged.model.app.rememberAppRepository -@Composable -fun AppInfo(packageName: String, userId: Int) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding( - horizontal = SettingsDimension.itemPaddingStart, - vertical = SettingsDimension.itemPaddingVertical, - ), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - val packageInfo = - remember { PackageManagers.getPackageInfoAsUser(packageName, userId) } ?: return - Box(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) { - AppIcon(app = packageInfo.applicationInfo, size = SettingsDimension.appIconInfoSize) +class AppInfoProvider(private val packageInfo: PackageInfo) { + @Composable + fun AppInfo(displayVersion: Boolean = false) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = SettingsDimension.itemPaddingStart, + vertical = SettingsDimension.itemPaddingVertical, + ), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Box(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) { + AppIcon(app = packageInfo.applicationInfo, size = SettingsDimension.appIconInfoSize) + } + AppLabel(packageInfo.applicationInfo) + if (displayVersion) AppVersion() + } + } + + @Composable + private fun AppVersion() { + if (packageInfo.versionName == null) return + Spacer(modifier = Modifier.height(4.dp)) + SettingsBody(packageInfo.versionName) + } + + @Composable + fun FooterAppVersion() { + if (packageInfo.versionName == null) return + Divider() + Box(modifier = Modifier.padding(SettingsDimension.itemPadding)) { + val versionName = BidiFormatter.getInstance().unicodeWrap(packageInfo.versionName) + SettingsBody(stringResource(R.string.version_text, versionName)) } - AppLabel(packageInfo.applicationInfo) - AppVersion(packageInfo.versionName) } } @Composable -private fun AppVersion(versionName: String?) { - if (versionName == null) return - Spacer(modifier = Modifier.height(4.dp)) - SettingsBody(versionName) -} - -@Composable -fun AppIcon(app: ApplicationInfo, size: Dp) { +internal fun AppIcon(app: ApplicationInfo, size: Dp) { val appRepository = rememberAppRepository() Image( painter = rememberDrawablePainter(appRepository.produceIcon(app).value), @@ -77,7 +90,7 @@ fun AppIcon(app: ApplicationInfo, size: Dp) { } @Composable -fun AppLabel(app: ApplicationInfo) { +internal fun AppLabel(app: ApplicationInfo) { val appRepository = rememberAppRepository() SettingsTitle(appRepository.produceLabel(app)) } 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 9b45318ffd829..4f88398b95509 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 @@ -17,8 +17,10 @@ package com.android.settingslib.spaprivileged.template.app 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 @Composable fun AppInfoPage( @@ -29,7 +31,12 @@ fun AppInfoPage( content: @Composable () -> Unit, ) { RegularScaffold(title = title) { - AppInfo(packageName, userId) + val appInfoProvider = remember { + val packageInfo = PackageManagers.getPackageInfoAsUser(packageName, userId) + ?: return@RegularScaffold + AppInfoProvider(packageInfo) + } + appInfoProvider.AppInfo(displayVersion = true) content() 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 ae4f8bd1c597c..80b2364ce68d6 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 @@ -34,6 +34,8 @@ 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.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.PackageManagers @@ -80,10 +82,31 @@ internal class TogglePermissionAppInfoPageProvider( companion object { @Composable - internal fun navigator(permissionType: String, app: ApplicationInfo) = + fun navigator(permissionType: String, app: ApplicationInfo) = navigator(route = "$PAGE_NAME/$permissionType/${app.toRoute()}") - internal fun buildPageData(permissionType: String): SettingsPage { + @Composable + fun EntryItem( + permissionType: String, + app: ApplicationInfo, + listModel: TogglePermissionAppListModel, + ) { + val context = LocalContext.current + val internalListModel = remember { + TogglePermissionInternalAppListModel(context, listModel) + } + val record = remember { listModel.transformItem(app) } + if (!remember { listModel.isChangeable(record) }) return + Preference( + object : PreferenceModel { + override val title = stringResource(listModel.pageTitleResId) + override val summary = internalListModel.getSummary(record) + override val onClick = navigator(permissionType, app) + } + ) + } + + fun buildPageData(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 74a50de1da922..5d49d24ecf8e2 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 @@ -20,13 +20,10 @@ import android.content.Context 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 -import com.android.settingslib.spa.widget.preference.Preference -import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.model.app.AppRecord import kotlinx.coroutines.flow.Flow @@ -85,28 +82,22 @@ interface TogglePermissionAppListProvider { fun createModel(context: Context): TogglePermissionAppListModel - fun buildInjectEntry(): SettingsEntryBuilder { - return TogglePermissionAppListPageProvider.buildInjectEntry(permissionType) - } - - @Composable - fun EntryItem() { - val listModel = rememberContext(::createModel) - Preference( - object : PreferenceModel { - override val title = stringResource(listModel.pageTitleResId) - override val onClick = TogglePermissionAppListPageProvider.navigator(permissionType) - } - ) - } + fun buildAppListInjectEntry(): SettingsEntryBuilder = + TogglePermissionAppListPageProvider.buildInjectEntry(permissionType) { createModel(it) } /** * Gets the route to the toggle permission App List page. * * Expose route to enable enter from non-SPA pages. */ - fun getRoute(): String = + fun getAppListRoute(): String = TogglePermissionAppListPageProvider.getRoute(permissionType) + + @Composable + fun InfoPageEntryItem(app: ApplicationInfo) { + val listModel = rememberContext(::createModel) + TogglePermissionAppInfoPageProvider.EntryItem(permissionType, app, listModel) + } } class TogglePermissionAppListTemplate( 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 475e93053e5ac..bd60bd3699c1f 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 @@ -34,7 +34,10 @@ 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.compose.rememberContext import com.android.settingslib.spa.framework.util.getStringArg +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.R import com.android.settingslib.spaprivileged.model.app.AppListModel import com.android.settingslib.spaprivileged.model.app.AppRecord @@ -107,20 +110,29 @@ internal class TogglePermissionAppListPageProvider( * * Expose route to enable enter from non-SPA pages. */ - internal fun getRoute(permissionType: String) = "$PAGE_NAME/$permissionType" + fun getRoute(permissionType: String) = "$PAGE_NAME/$permissionType" - @Composable - internal fun navigator(permissionType: String) = navigator(route = getRoute(permissionType)) - - internal fun buildInjectEntry(permissionType: String): SettingsEntryBuilder { + fun buildInjectEntry( + permissionType: String, + listModelSupplier: (Context) -> TogglePermissionAppListModel, + ): SettingsEntryBuilder { val appListPage = SettingsPage.create( PAGE_NAME, PAGE_PARAMETER, bundleOf(PERMISSION to permissionType)) return SettingsEntryBuilder.createInject(owner = appListPage).setIsAllowSearch(false) + .setUiLayoutFn { + val listModel = rememberContext(listModelSupplier) + Preference( + object : PreferenceModel { + override val title = stringResource(listModel.pageTitleResId) + override val onClick = navigator(route = getRoute(permissionType)) + } + ) + } } } } -private class TogglePermissionInternalAppListModel( +internal class TogglePermissionInternalAppListModel( private val context: Context, private val listModel: TogglePermissionAppListModel, ) : AppListModel { @@ -132,6 +144,11 @@ private class TogglePermissionInternalAppListModel( @Composable override fun getSummary(option: Int, record: T): State { + return getSummary(record) + } + + @Composable + fun getSummary(record: T): State { val restrictionsProvider = remember { val restrictions = Restrictions( userId = record.app.userId,