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.lib
18 
19 import android.content.Context
20 import android.net.NetworkPolicy
21 import android.net.NetworkPolicyManager
22 import android.net.NetworkTemplate
23 import android.text.format.DateUtils
24 import android.util.Range
25 import com.android.settingslib.NetworkPolicyEditor
26 
27 interface INetworkCycleDataRepository {
28     fun getCycles(): List<Range<Long>>
29     fun getPolicy(): NetworkPolicy?
30     fun queryUsage(range: Range<Long>): NetworkUsageData
31 }
32 
33 class NetworkCycleDataRepository(
34     context: Context,
35     private val networkTemplate: NetworkTemplate,
36     private val networkStatsRepository: NetworkStatsRepository =
37         NetworkStatsRepository(context, networkTemplate),
38 ) : INetworkCycleDataRepository {
39 
40     private val policyManager = context.getSystemService(NetworkPolicyManager::class.java)!!
41 
<lambda>null42     fun loadFirstCycle(): NetworkUsageData? = getCycles().firstOrNull()?.let { queryUsage(it) }
43 
getCyclesnull44     override fun getCycles(): List<Range<Long>> =
45         getPolicy()?.getCycles().orEmpty().ifEmpty { queryCyclesAsFourWeeks() }
46 
queryCyclesAsFourWeeksnull47     private fun queryCyclesAsFourWeeks(): List<Range<Long>> =
48         networkStatsRepository.getTimeRange().asFourWeeks()
49 
50     override fun getPolicy(): NetworkPolicy? =
51         with(NetworkPolicyEditor(policyManager)) {
52             read()
53             getPolicy(networkTemplate)
54         }
55 
queryUsagenull56     override fun queryUsage(range: Range<Long>) = NetworkUsageData(
57         startTime = range.lower,
58         endTime = range.upper,
59         usage = networkStatsRepository.querySummaryForDevice(range.lower, range.upper),
60     )
61 
62     companion object {
63         fun NetworkPolicy.getCycles() = cycleIterator().asSequence().map {
64             Range(it.lower.toInstant().toEpochMilli(), it.upper.toInstant().toEpochMilli())
65         }.toList()
66 
67         fun Range<Long>?.asFourWeeks(): List<Range<Long>> {
68             val timeRange = this ?: return emptyList()
69             return reverseBucketRange(
70                 startTime = timeRange.lower,
71                 endTime = timeRange.upper,
72                 step = DateUtils.WEEK_IN_MILLIS * 4,
73             )
74         }
75 
76         fun bucketRange(startTime: Long, endTime: Long, step: Long): List<Range<Long>> =
77             (startTime..endTime step step).zipWithNext(::Range)
78 
79         fun reverseBucketRange(startTime: Long, endTime: Long, step: Long): List<Range<Long>> =
80             (endTime downTo (startTime - step + 1) step step)
81                 .zipWithNext { bucketEnd, bucketStart -> Range(bucketStart, bucketEnd) }
82     }
83 }
84