diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java index 4c0b5166ee2..38f09f46159 100644 --- a/src/com/android/settings/datausage/AppDataUsage.java +++ b/src/com/android/settings/datausage/AppDataUsage.java @@ -261,6 +261,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC return Unit.INSTANCE; }); if (mCycles != null) { + Log.d(TAG, "setInitialCycles: " + mCycles + " " + mSelectedCycle); controller.setInitialCycles(mCycles, mSelectedCycle); } } diff --git a/src/com/android/settings/datausage/AppDataUsageListController.kt b/src/com/android/settings/datausage/AppDataUsageListController.kt index 85a6e920f53..746782a7c12 100644 --- a/src/com/android/settings/datausage/AppDataUsageListController.kt +++ b/src/com/android/settings/datausage/AppDataUsageListController.kt @@ -17,9 +17,7 @@ package com.android.settings.datausage import android.content.Context -import android.util.SparseBooleanArray import androidx.annotation.OpenForTesting -import androidx.core.util.keyIterator import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope @@ -27,8 +25,6 @@ import androidx.lifecycle.repeatOnLifecycle import androidx.preference.PreferenceGroup import androidx.preference.PreferenceScreen import com.android.settings.core.BasePreferenceController -import com.android.settings.datausage.lib.AppDataUsageRepository.Companion.getAppUid -import com.android.settings.datausage.lib.AppDataUsageRepository.Companion.getAppUidList import com.android.settings.datausage.lib.AppPreferenceRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch diff --git a/src/com/android/settings/datausage/DataUsageList.kt b/src/com/android/settings/datausage/DataUsageList.kt index 1eb883cf021..7240150d901 100644 --- a/src/com/android/settings/datausage/DataUsageList.kt +++ b/src/com/android/settings/datausage/DataUsageList.kt @@ -55,9 +55,6 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl @VisibleForTesting var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID - // Spinner will keep the selected cycle even after paused, this only keeps the displayed cycle, - // which need be cleared when resumed. - private var lastDisplayedUsageData: NetworkUsageData? = null private lateinit var usageAmount: Preference private var subscriptionInfoEntity: SubscriptionInfoEntity? = null private lateinit var dataUsageListAppsController: DataUsageListAppsController @@ -77,7 +74,7 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl finish() return } - billingCycleRepository = createBillingCycleRepository(); + billingCycleRepository = createBillingCycleRepository() if (!billingCycleRepository.isBandwidthControlEnabled()) { Log.w(TAG, "No bandwidth control; leaving") finish() @@ -120,7 +117,6 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl override fun onResume() { super.onResume() dataStateListener.start(subId) - lastDisplayedUsageData = null updatePolicy() } @@ -188,11 +184,6 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl * Updates the chart and detail data when initial loaded or selected cycle changed. */ private fun updateSelectedCycle(usageData: NetworkUsageData) { - if (usageData == lastDisplayedUsageData) { - // Avoid duplicate update to avoid page flash. - return - } - lastDisplayedUsageData = usageData Log.d(TAG, "showing cycle $usageData") usageAmount.title = usageData.getDataUsedString(requireContext()) diff --git a/src/com/android/settings/datausage/DataUsageListHeaderController.kt b/src/com/android/settings/datausage/DataUsageListHeaderController.kt index 58fc3b58ef6..ad76ede6773 100644 --- a/src/com/android/settings/datausage/DataUsageListHeaderController.kt +++ b/src/com/android/settings/datausage/DataUsageListHeaderController.kt @@ -45,7 +45,7 @@ open class DataUsageListHeaderController( sourceMetricsCategory: Int, viewLifecycleOwner: LifecycleOwner, private val onCyclesLoad: (usageDataList: List) -> Unit, - private val onItemSelected: (usageData: NetworkUsageData) -> Unit, + private val updateSelectedCycle: (usageData: NetworkUsageData) -> Unit, private val repository: INetworkCycleDataRepository = NetworkCycleDataRepository(header.context, template), ) { @@ -53,6 +53,17 @@ open class DataUsageListHeaderController( private val configureButton: View = header.requireViewById(R.id.filter_settings) private val cycleSpinner: Spinner = header.requireViewById(R.id.filter_spinner) + + private val cycleListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + setSelectedCycle(position) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // ignored + } + } + private val cycleAdapter = CycleAdapter(context, object : SpinnerInterface { override fun setAdapter(cycleAdapter: CycleAdapter) { cycleSpinner.adapter = cycleAdapter @@ -62,21 +73,15 @@ open class DataUsageListHeaderController( override fun setSelection(position: Int) { cycleSpinner.setSelection(position) - } - }) - private var cycles: List = emptyList() - - private val cycleListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - if (0 <= position && position < cycleAdapter.count) { - cycles.getOrNull(position)?.let(onItemSelected) + if (cycleSpinner.onItemSelectedListener == null) { + cycleSpinner.onItemSelectedListener = cycleListener + } else { + setSelectedCycle(position) } } + }) - override fun onNothingSelected(parent: AdapterView<*>?) { - // ignored - } - } + private var cycles: List = emptyList() init { configureButton.setOnClickListener { @@ -114,11 +119,12 @@ open class DataUsageListHeaderController( } private fun updateCycleData() { - cycleSpinner.onItemSelectedListener = cycleListener - // calculate policy cycles based on available data - // generate cycle list based on policy and available history cycleAdapter.updateCycleList(cycles.map { Range(it.startTime, it.endTime) }) cycleSpinner.visibility = View.VISIBLE onCyclesLoad(cycles) } + + private fun setSelectedCycle(position: Int) { + cycles.getOrNull(position)?.let(updateSelectedCycle) + } } diff --git a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt index de9059464a9..930737f2a23 100644 --- a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt +++ b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt @@ -98,7 +98,7 @@ class AppDataUsageRepository( private fun bindStats( buckets: List, - profiles: MutableList, + profiles: List, knownItems: SparseArray, items: ArrayList, ) { diff --git a/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt b/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt index 4e97c6d3946..4256130ce19 100644 --- a/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt +++ b/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt @@ -58,7 +58,7 @@ class NetworkCycleDataRepository( return reverseBucketRange( startTime = timeRange.lower, endTime = timeRange.upper, - bucketSize = DateUtils.WEEK_IN_MILLIS * 4, + step = DateUtils.WEEK_IN_MILLIS * 4, ) } @@ -76,7 +76,7 @@ class NetworkCycleDataRepository( dailyUsage = bucketRange( startTime = startTime, endTime = endTime, - bucketSize = NetworkCycleChartData.BUCKET_DURATION.inWholeMilliseconds, + step = NetworkCycleChartData.BUCKET_DURATION.inWholeMilliseconds, ).queryUsage(), ) } @@ -92,29 +92,10 @@ class NetworkCycleDataRepository( usage = networkStatsRepository.querySummaryForDevice(range.lower, range.upper), ) - private fun bucketRange(startTime: Long, endTime: Long, bucketSize: Long): List> { - val buckets = mutableListOf>() - var currentStart = startTime - while (currentStart < endTime) { - val bucketEnd = currentStart + bucketSize - buckets += Range(currentStart, bucketEnd) - currentStart = bucketEnd - } - return buckets - } + private fun bucketRange(startTime: Long, endTime: Long, step: Long): List> = + (startTime..endTime step step).zipWithNext(::Range) - private fun reverseBucketRange( - startTime: Long, - endTime: Long, - bucketSize: Long, - ): List> { - val buckets = mutableListOf>() - var currentEnd = endTime - while (currentEnd > startTime) { - val bucketStart = currentEnd - bucketSize - buckets += Range(bucketStart, currentEnd) - currentEnd = bucketStart - } - return buckets - } + private fun reverseBucketRange(startTime: Long, endTime: Long, step: Long): List> = + (endTime downTo (startTime - step + 1) step step) + .zipWithNext { bucketEnd, bucketStart -> Range(bucketStart, bucketEnd) } } diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt index 3580e68ad40..6d5be6b2b26 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt @@ -69,7 +69,7 @@ class DataUsageListHeaderControllerTest { sourceMetricsCategory = 0, viewLifecycleOwner = testLifecycleOwner, onCyclesLoad = {}, - onItemSelected = {}, + updateSelectedCycle = {}, repository = repository, )