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.datausage 18 19 import android.app.ActivityManager 20 import android.content.Context 21 import android.net.NetworkTemplate 22 import android.os.Bundle 23 import android.telephony.SubscriptionManager 24 import androidx.annotation.OpenForTesting 25 import androidx.annotation.VisibleForTesting 26 import androidx.lifecycle.LifecycleCoroutineScope 27 import androidx.lifecycle.LifecycleOwner 28 import androidx.lifecycle.lifecycleScope 29 import androidx.preference.PreferenceGroup 30 import androidx.preference.PreferenceScreen 31 import com.android.settings.R 32 import com.android.settings.core.BasePreferenceController 33 import com.android.settings.core.SubSettingLauncher 34 import com.android.settings.datausage.lib.AppDataUsageRepository 35 import com.android.settings.datausage.lib.NetworkUsageData 36 import com.android.settings.network.telephony.requireSubscriptionManager 37 import com.android.settingslib.AppItem 38 import com.android.settingslib.net.UidDetailProvider 39 import kotlinx.coroutines.Dispatchers 40 import kotlinx.coroutines.launch 41 import kotlinx.coroutines.withContext 42 43 @OpenForTesting 44 open class DataUsageListAppsController(context: Context, preferenceKey: String) : 45 BasePreferenceController(context, preferenceKey) { 46 47 private val uidDetailProvider = UidDetailProvider(context) 48 private lateinit var template: NetworkTemplate 49 private lateinit var repository: AppDataUsageRepository 50 private lateinit var preference: PreferenceGroup 51 private lateinit var lifecycleScope: LifecycleCoroutineScope 52 53 private var cycleData: List<NetworkUsageData>? = null 54 55 open fun init(template: NetworkTemplate) { 56 this.template = template 57 repository = AppDataUsageRepository( 58 context = mContext, 59 currentUserId = ActivityManager.getCurrentUser(), 60 template = template, 61 ) { appItem: AppItem -> uidDetailProvider.getUidDetail(appItem.key, true).packageName } 62 } 63 64 override fun getAvailabilityStatus() = AVAILABLE 65 66 override fun displayPreference(screen: PreferenceScreen) { 67 super.displayPreference(screen) 68 preference = screen.findPreference(preferenceKey)!! 69 } 70 71 override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { 72 lifecycleScope = viewLifecycleOwner.lifecycleScope 73 } 74 75 fun updateCycles(cycleData: List<NetworkUsageData>) { 76 this.cycleData = cycleData 77 } 78 79 fun update(subId: Int, startTime: Long, endTime: Long) = lifecycleScope.launch { 80 val apps = withContext(Dispatchers.Default) { 81 val carrierId = if (SubscriptionManager.isValidSubscriptionId(subId)) { 82 mContext.requireSubscriptionManager().getActiveSubscriptionInfo(subId)?.carrierId 83 } else null 84 repository.getAppPercent(carrierId, startTime, endTime).map { (appItem, percent) -> 85 AppDataUsagePreference(mContext, appItem, percent, uidDetailProvider).apply { 86 setOnPreferenceClickListener { 87 startAppDataUsage(appItem, endTime) 88 true 89 } 90 } 91 } 92 } 93 preference.removeAll() 94 for (app in apps) { 95 preference.addPreference(app) 96 } 97 } 98 99 @VisibleForTesting 100 fun startAppDataUsage(item: AppItem, endTime: Long) { 101 val cycleData = cycleData ?: return 102 val args = Bundle().apply { 103 putParcelable(AppDataUsage.ARG_APP_ITEM, item) 104 putParcelable(AppDataUsage.ARG_NETWORK_TEMPLATE, template) 105 val cycles = ArrayList<Long>().apply { 106 for (data in cycleData) { 107 if (isEmpty()) add(data.endTime) 108 add(data.startTime) 109 } 110 } 111 putSerializable(AppDataUsage.ARG_NETWORK_CYCLES, cycles) 112 putLong(AppDataUsage.ARG_SELECTED_CYCLE, endTime) 113 } 114 SubSettingLauncher(mContext).apply { 115 setDestination(AppDataUsage::class.java.name) 116 setTitleRes(R.string.data_usage_app_summary_title) 117 setArguments(args) 118 setSourceMetricsCategory(metricsCategory) 119 }.launch() 120 } 121 } 122