• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.spa.app.storage
18 
19 import android.content.Context
20 import android.content.pm.ApplicationInfo
21 import android.os.Bundle
22 import androidx.annotation.StringRes
23 import androidx.compose.runtime.Composable
24 import androidx.compose.runtime.State
25 import androidx.compose.runtime.getValue
26 import androidx.compose.runtime.remember
27 import androidx.compose.ui.platform.LocalContext
28 import androidx.compose.ui.res.stringResource
29 import com.android.settings.R
30 import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
31 import com.android.settingslib.spa.framework.common.SettingsPageProvider
32 import com.android.settingslib.spa.framework.util.filterItem
33 import com.android.settingslib.spa.framework.util.mapItem
34 import com.android.settingslib.spaprivileged.model.app.AppEntry
35 import com.android.settingslib.spaprivileged.model.app.AppListModel
36 import com.android.settingslib.spaprivileged.model.app.AppRecord
37 import com.android.settingslib.spaprivileged.model.app.AppStorageRepositoryImpl
38 import com.android.settingslib.spaprivileged.template.app.AppList
39 import com.android.settingslib.spaprivileged.template.app.AppListInput
40 import com.android.settingslib.spaprivileged.template.app.AppListItem
41 import com.android.settingslib.spaprivileged.template.app.AppListItemModel
42 import com.android.settingslib.spaprivileged.template.app.AppListPage
43 import com.android.settingslib.spaprivileged.template.app.getStorageSize
44 import kotlinx.coroutines.flow.Flow
45 
46 sealed class StorageAppListPageProvider(private val type: StorageType) : SettingsPageProvider {
47     @Composable
48     override fun Page(arguments: Bundle?) {
49         StorageAppListPage(type)
50     }
51 
52     object Apps : StorageAppListPageProvider(StorageType.Apps) {
53         override val name = "StorageAppList"
54     }
55 
56     object Games : StorageAppListPageProvider(StorageType.Games) {
57         override val name = "GameStorageAppList"
58     }
59 }
60 
61 sealed class StorageType(
62     @StringRes val titleResource: Int,
63     val filter: (AppRecordWithSize) -> Boolean
64 ) {
65     object Apps : StorageType(
66         titleResource = R.string.apps_storage,
<lambda>null67         filter = {
68             (it.app.flags and ApplicationInfo.FLAG_IS_GAME) == 0 &&
69             it.app.category != ApplicationInfo.CATEGORY_GAME
70         }
71     )
72     object Games : StorageType(
73         titleResource = R.string.game_storage_settings,
<lambda>null74         filter = {
75             (it.app.flags and ApplicationInfo.FLAG_IS_GAME) != 0 ||
76                 it.app.category == ApplicationInfo.CATEGORY_GAME
77         }
78     )
79 }
80 
81 @Composable
StorageAppListPagenull82 fun StorageAppListPage(
83     type: StorageType,
84     appList: @Composable AppListInput<AppRecordWithSize>.() -> Unit = { AppList() }
85 ) {
86     val context = LocalContext.current
87     AppListPage(
88         title = stringResource(type.titleResource),
89         listModel = when (type) {
<lambda>null90             StorageType.Apps -> remember(context) { StorageAppListModel(context, type) }
<lambda>null91             StorageType.Games -> remember(context) { StorageAppListModel(context, type) }
92         },
93         showInstantApps = true,
94         matchAnyUserForAdmin = true,
95         appList = appList,
<lambda>null96         moreOptions = {  }, // TODO(b/292165031) Sorting in Options not yet supported
97     )
98 }
99 
100 data class AppRecordWithSize(
101     override val app: ApplicationInfo,
102     val size: Long
103 ) : AppRecord
104 
105 class StorageAppListModel(
106     private val context: Context,
107     private val type: StorageType,
<lambda>null108     private val getStorageSummary: @Composable ApplicationInfo.() -> State<String> = {
109         getStorageSize()
110     }
111 ) : AppListModel<AppRecordWithSize> {
112     private val appStorageRepository = AppStorageRepositoryImpl(context)
113 
transformnull114     override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
115         appListFlow.mapItem { app ->
116             AppRecordWithSize(app, appStorageRepository.calculateSizeBytes(app) ?: 0L)
117         }
118 
filternull119     override fun filter(
120         userIdFlow: Flow<Int>,
121         option: Int,
122         recordListFlow: Flow<List<AppRecordWithSize>>
123     ): Flow<List<AppRecordWithSize>> = recordListFlow.filterItem { type.filter(it) }
124 
125     @Composable
getSummarynull126     override fun getSummary(option: Int, record: AppRecordWithSize): () -> String {
127         val storageSummary by record.app.getStorageSummary()
128         return { storageSummary }
129     }
130 
131     @Composable
AppItemnull132     override fun AppListItemModel<AppRecordWithSize>.AppItem() {
133         AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
134     }
135 
<lambda>null136     override fun getComparator(option: Int) = compareByDescending<AppEntry<AppRecordWithSize>> {
137         it.record.size
138     }.then(super.getComparator(option))
139 }
140