1 /*
2  * 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.content.Context
20 import android.view.View
21 import android.widget.AdapterView
22 import androidx.lifecycle.Lifecycle
23 import androidx.lifecycle.LifecycleOwner
24 import androidx.lifecycle.lifecycleScope
25 import androidx.lifecycle.repeatOnLifecycle
26 import androidx.preference.PreferenceScreen
27 import com.android.settings.core.BasePreferenceController
28 import com.android.settings.datausage.lib.IAppDataUsageDetailsRepository
29 import com.android.settings.datausage.lib.NetworkUsageDetailsData
30 import kotlinx.coroutines.Dispatchers
31 import kotlinx.coroutines.launch
32 import kotlinx.coroutines.withContext
33 
34 class AppDataUsageCycleController(context: Context, preferenceKey: String) :
35     BasePreferenceController(context, preferenceKey) {
36 
37     private lateinit var repository: IAppDataUsageDetailsRepository
<lambda>null38     private var onUsageDataUpdated: (NetworkUsageDetailsData) -> Unit = {}
39     private lateinit var preference: SpinnerPreference
40     private var cycleAdapter: CycleAdapter? = null
41 
42     private var usageDetailsDataList: List<NetworkUsageDetailsData> = emptyList()
43 
getAvailabilityStatusnull44     override fun getAvailabilityStatus() = AVAILABLE
45 
46     override fun displayPreference(screen: PreferenceScreen) {
47         super.displayPreference(screen)
48         preference = screen.findPreference(preferenceKey)!!
49         if (cycleAdapter == null) {
50             cycleAdapter = CycleAdapter(mContext, preference)
51         }
52     }
53 
initnull54     fun init(
55         repository: IAppDataUsageDetailsRepository,
56         onUsageDataUpdated: (NetworkUsageDetailsData) -> Unit,
57     ) {
58         this.repository = repository
59         this.onUsageDataUpdated = onUsageDataUpdated
60     }
61 
62     /**
63      * Sets the initial cycles.
64      *
65      * If coming from a page like DataUsageList where already has a selected cycle, display that
66      * before loading to reduce flicker.
67      */
setInitialCyclesnull68     fun setInitialCycles(initialCycles: List<Long>, initialSelectedEndTime: Long) {
69         if (initialCycles.isNotEmpty()) {
70             cycleAdapter?.setInitialCycleList(initialCycles, initialSelectedEndTime)
71             preference.setHasCycles(true)
72         }
73     }
74 
onViewCreatednull75     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
76         viewLifecycleOwner.lifecycleScope.launch {
77             viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
78                 update()
79             }
80         }
81     }
82 
updatenull83     private suspend fun update() {
84         usageDetailsDataList = withContext(Dispatchers.Default) {
85             repository.queryDetailsForCycles()
86         }
87         if (usageDetailsDataList.isEmpty()) {
88             preference.setHasCycles(false)
89             onUsageDataUpdated(NetworkUsageDetailsData.AllZero)
90             return
91         }
92 
93         preference.setHasCycles(true)
94         cycleAdapter?.updateCycleList(usageDetailsDataList.map { it.range })
95         preference.setOnItemSelectedListener(cycleListener)
96     }
97 
98     private val cycleListener = object : AdapterView.OnItemSelectedListener {
onItemSelectednull99         override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
100             usageDetailsDataList.getOrNull(position)?.let(onUsageDataUpdated)
101         }
102 
onNothingSelectednull103         override fun onNothingSelected(parent: AdapterView<*>?) {
104             // ignored
105         }
106     }
107 }
108