• 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.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