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
This commit is contained in:
Chaohui Wang
2022-09-26 16:25:05 +08:00
parent 7144d95e4d
commit 76171b9d79
3 changed files with 113 additions and 0 deletions

View File

@@ -16,6 +16,7 @@
package com.android.settings.spa 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.AppsMainPageProvider
import com.android.settings.spa.app.appsettings.AppSettingsProvider import com.android.settings.spa.app.appsettings.AppSettingsProvider
import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
@@ -53,6 +54,7 @@ object SpaEnvironment {
allPageProviders = listOf( allPageProviders = listOf(
HomePageProvider, HomePageProvider,
AppsMainPageProvider, AppsMainPageProvider,
AllAppListPageProvider,
AppSettingsProvider, AppSettingsProvider,
SpecialAppAccessPageProvider, SpecialAppAccessPageProvider,
NotificationMainPageProvider, NotificationMainPageProvider,

View File

@@ -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<AppRecordWithSize> {
private val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)!!
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
appListFlow.asyncMapItem { app ->
AppRecordWithSize(app)
}
override fun filter(
userIdFlow: Flow<Int>,
option: Int,
recordListFlow: Flow<List<AppRecordWithSize>>,
) = recordListFlow
@Composable
override fun getSummary(option: Int, record: AppRecordWithSize): State<String> =
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
}
}
}

View File

@@ -61,6 +61,7 @@ object AppsMainPageProvider : SettingsPageProvider {
override fun buildEntry(arguments: Bundle?): List<SettingsEntry> { override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
val owner = SettingsPage.create(name, parameter = parameter, arguments = arguments) val owner = SettingsPage.create(name, parameter = parameter, arguments = arguments)
return listOf( return listOf(
AllAppListPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
SpecialAppAccessPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), SpecialAppAccessPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
) )
} }
@@ -69,6 +70,7 @@ object AppsMainPageProvider : SettingsPageProvider {
@Composable @Composable
private fun AppsMain() { private fun AppsMain() {
RegularScaffold(title = stringResource(R.string.apps_dashboard_title)) { RegularScaffold(title = stringResource(R.string.apps_dashboard_title)) {
AllAppListPageProvider.buildInjectEntry().build().UiLayout()
SpecialAppAccessPageProvider.EntryItem() SpecialAppAccessPageProvider.EntryItem()
} }
} }