From 76171b9d79f8fe4af117f3e34a02cea277dec4ab Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Mon, 26 Sep 2022 16:25:05 +0800 Subject: [PATCH] Add All App List for SPA This is the App List under Apps page with storage usage size. Bug: 236346018 Test: Manual with Settings App Change-Id: I8753160fb1abb609dcf2e9539b04ec5d72548d40 --- .../android/settings/spa/SpaEnvironment.kt | 2 + .../android/settings/spa/app/AllAppList.kt | 109 ++++++++++++++++++ src/com/android/settings/spa/app/AppsMain.kt | 2 + 3 files changed, 113 insertions(+) create mode 100644 src/com/android/settings/spa/app/AllAppList.kt diff --git a/src/com/android/settings/spa/SpaEnvironment.kt b/src/com/android/settings/spa/SpaEnvironment.kt index 4d2e3e22d91..1d693424568 100644 --- a/src/com/android/settings/spa/SpaEnvironment.kt +++ b/src/com/android/settings/spa/SpaEnvironment.kt @@ -16,6 +16,7 @@ package com.android.settings.spa +import com.android.settings.spa.app.AllAppListPageProvider import com.android.settings.spa.app.AppsMainPageProvider import com.android.settings.spa.app.appsettings.AppSettingsProvider import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider @@ -53,6 +54,7 @@ object SpaEnvironment { allPageProviders = listOf( HomePageProvider, AppsMainPageProvider, + AllAppListPageProvider, AppSettingsProvider, SpecialAppAccessPageProvider, NotificationMainPageProvider, diff --git a/src/com/android/settings/spa/app/AllAppList.kt b/src/com/android/settings/spa/app/AllAppList.kt new file mode 100644 index 00000000000..c2215d48d76 --- /dev/null +++ b/src/com/android/settings/spa/app/AllAppList.kt @@ -0,0 +1,109 @@ +/* + * 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.settings.spa.app + +import android.app.usage.StorageStatsManager +import android.content.Context +import android.content.pm.ApplicationInfo +import android.os.Bundle +import android.text.format.Formatter +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settings.spa.app.appsettings.AppSettingsProvider +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.compose.toState +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.AppListModel +import com.android.settingslib.spaprivileged.model.app.AppRecord +import com.android.settingslib.spaprivileged.model.app.userHandle +import com.android.settingslib.spaprivileged.template.app.AppListItem +import com.android.settingslib.spaprivileged.template.app.AppListPage +import kotlinx.coroutines.flow.Flow + +object AllAppListPageProvider : SettingsPageProvider { + override val name = "AllAppList" + + @Composable + override fun Page(arguments: Bundle?) { + AllAppListPage() + } + + fun buildInjectEntry() = SettingsEntryBuilder + .createInject(owner = SettingsPage.create(name)) + .setIsAllowSearch(true) + .setUiLayoutFn { + Preference(object : PreferenceModel { + override val title = stringResource(R.string.all_apps) + override val onClick = navigator(name) + }) + } +} + +@Composable +private fun AllAppListPage() { + AppListPage( + title = stringResource(R.string.all_apps), + listModel = rememberContext(::AllAppListModel), + ) { itemModel -> + AppListItem( + itemModel = itemModel, + onClick = AppSettingsProvider.navigator(app = itemModel.record.app), + ) + } +} + +data class AppRecordWithSize( + override val app: ApplicationInfo, + var sizeBytes: Long? = null, +) : AppRecord + +private class AllAppListModel(private val context: Context) : AppListModel { + private val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)!! + + override fun transform(userIdFlow: Flow, appListFlow: Flow>) = + appListFlow.asyncMapItem { app -> + AppRecordWithSize(app) + } + + override fun filter( + userIdFlow: Flow, + option: Int, + recordListFlow: Flow>, + ) = recordListFlow + + @Composable + override fun getSummary(option: Int, record: AppRecordWithSize): State = + Formatter.formatFileSize(context, record.calculateSizeBytes()).toState() + + private fun AppRecordWithSize.calculateSizeBytes(): Long { + sizeBytes?.let { return it } + val stats = storageStatsManager.queryStatsForPackage( + app.storageUuid, app.packageName, app.userHandle + ) + return (stats.codeBytes + stats.dataBytes + stats.cacheBytes).also { + sizeBytes = it + } + } +} diff --git a/src/com/android/settings/spa/app/AppsMain.kt b/src/com/android/settings/spa/app/AppsMain.kt index ad6928f0e48..152ad2b3832 100644 --- a/src/com/android/settings/spa/app/AppsMain.kt +++ b/src/com/android/settings/spa/app/AppsMain.kt @@ -61,6 +61,7 @@ object AppsMainPageProvider : SettingsPageProvider { override fun buildEntry(arguments: Bundle?): List { val owner = SettingsPage.create(name, parameter = parameter, arguments = arguments) return listOf( + AllAppListPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), SpecialAppAccessPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), ) } @@ -69,6 +70,7 @@ object AppsMainPageProvider : SettingsPageProvider { @Composable private fun AppsMain() { RegularScaffold(title = stringResource(R.string.apps_dashboard_title)) { + AllAppListPageProvider.buildInjectEntry().build().UiLayout() SpecialAppAccessPageProvider.EntryItem() } }