1 /* <lambda>null2 * Copyright (C) 2022 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.appinfo 18 19 import android.content.Context 20 import android.content.pm.ApplicationInfo 21 import android.net.NetworkTemplate 22 import androidx.compose.runtime.Composable 23 import androidx.compose.runtime.getValue 24 import androidx.compose.runtime.remember 25 import androidx.compose.runtime.rememberCoroutineScope 26 import androidx.compose.ui.platform.LocalContext 27 import androidx.compose.ui.res.stringResource 28 import androidx.lifecycle.compose.collectAsStateWithLifecycle 29 import com.android.settings.R 30 import com.android.settings.Utils 31 import com.android.settings.applications.appinfo.AppInfoDashboardFragment 32 import com.android.settings.datausage.AppDataUsage 33 import com.android.settings.datausage.lib.AppDataUsageSummaryRepository 34 import com.android.settings.datausage.lib.IAppDataUsageSummaryRepository 35 import com.android.settings.datausage.lib.INetworkTemplates 36 import com.android.settings.datausage.lib.NetworkTemplates 37 import com.android.settings.datausage.lib.NetworkTemplates.getTitleResId 38 import com.android.settingslib.spa.widget.preference.Preference 39 import com.android.settingslib.spa.widget.preference.PreferenceModel 40 import com.android.settingslib.spaprivileged.model.app.hasFlag 41 import kotlinx.coroutines.CoroutineScope 42 import kotlinx.coroutines.Dispatchers 43 import kotlinx.coroutines.flow.SharingStarted 44 import kotlinx.coroutines.flow.flow 45 import kotlinx.coroutines.flow.map 46 import kotlinx.coroutines.flow.shareIn 47 import kotlinx.coroutines.withContext 48 49 @Composable 50 fun AppDataUsagePreference( 51 app: ApplicationInfo, 52 networkTemplates: INetworkTemplates = NetworkTemplates, 53 repositoryFactory: ( 54 context: Context, 55 networkTemplate: NetworkTemplate, 56 ) -> IAppDataUsageSummaryRepository = { context, networkTemplate -> 57 AppDataUsageSummaryRepository(context, networkTemplate) 58 } 59 ) { 60 val context = LocalContext.current 61 val coroutineScope = rememberCoroutineScope() <lambda>null62 val presenter = remember(app) { 63 AppDataUsagePresenter(context, app, coroutineScope, networkTemplates, repositoryFactory) 64 } 65 if (!presenter.isAvailableFlow.collectAsStateWithLifecycle(initialValue = false).value) return 66 67 val summary by presenter.summaryFlow.collectAsStateWithLifecycle( 68 initialValue = stringResource(R.string.computing_size), 69 ) 70 Preference(object : PreferenceModel { 71 override val title = stringResource( 72 presenter.titleResIdFlow.collectAsStateWithLifecycle( 73 initialValue = R.string.summary_placeholder, 74 ).value 75 ) <lambda>null76 override val summary = { summary } <lambda>null77 override val enabled = { presenter.isEnabled() } 78 override val onClick = presenter::startActivity 79 }) 80 } 81 82 private class AppDataUsagePresenter( 83 private val context: Context, 84 private val app: ApplicationInfo, 85 coroutineScope: CoroutineScope, 86 networkTemplates: INetworkTemplates, 87 private val repositoryFactory: ( 88 context: Context, 89 networkTemplate: NetworkTemplate, 90 ) -> IAppDataUsageSummaryRepository, 91 ) { <lambda>null92 val isAvailableFlow = flow { emit(isAvailable()) } 93 <lambda>null94 private suspend fun isAvailable(): Boolean = withContext(Dispatchers.IO) { 95 Utils.isBandwidthControlEnabled() 96 } 97 isEnablednull98 fun isEnabled() = app.hasFlag(ApplicationInfo.FLAG_INSTALLED) 99 100 private val templateFlow = flow { 101 emit(withContext(Dispatchers.IO) { 102 networkTemplates.getDefaultTemplate(context) 103 }) 104 }.shareIn(coroutineScope, SharingStarted.WhileSubscribed(), 1) 105 <lambda>null106 val titleResIdFlow = templateFlow.map { it.getTitleResId() } <lambda>null107 val summaryFlow = templateFlow.map { getSummary(it) } 108 <lambda>null109 private suspend fun getSummary(template: NetworkTemplate) = withContext(Dispatchers.IO) { 110 val appUsageData = repositoryFactory(context, template).querySummary(app.uid) 111 if (appUsageData == null || appUsageData.usage == 0L) { 112 context.getString(R.string.no_data_usage) 113 } else { 114 context.getString( 115 R.string.data_summary_format, 116 appUsageData.formatUsage(context).displayText, 117 appUsageData.formatStartDate(context), 118 ) 119 } 120 } 121 startActivitynull122 fun startActivity() { 123 AppInfoDashboardFragment.startAppInfoFragment( 124 AppDataUsage::class.java, 125 app, 126 context, 127 AppInfoSettingsProvider.METRICS_CATEGORY, 128 ) 129 } 130 } 131