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