Now they are all aligned. Bug: 321861088 Flag: EXEMPT bug fix Test: unit test Change-Id: I1981fd32fd24de7c9eff93e0cd638e862f01b9b9
162 lines
6.1 KiB
Kotlin
162 lines
6.1 KiB
Kotlin
/*
|
|
* Copyright (C) 2024 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.datausage
|
|
|
|
import android.content.Context
|
|
import android.net.NetworkPolicy
|
|
import android.net.NetworkTemplate
|
|
import android.text.TextUtils
|
|
import android.util.Log
|
|
import androidx.lifecycle.LifecycleOwner
|
|
import androidx.preference.PreferenceScreen
|
|
import com.android.settings.R
|
|
import com.android.settings.datausage.lib.DataUsageFormatter
|
|
import com.android.settings.datausage.lib.DataUsageLib.getMobileTemplate
|
|
import com.android.settings.datausage.lib.INetworkCycleDataRepository
|
|
import com.android.settings.datausage.lib.NetworkCycleDataRepository
|
|
import com.android.settings.network.ProxySubscriptionManager
|
|
import com.android.settings.network.policy.NetworkPolicyRepository
|
|
import com.android.settings.network.telephony.TelephonyBasePreferenceController
|
|
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
|
import kotlin.math.max
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.withContext
|
|
|
|
/**
|
|
* This is the controller for a data usage header that retrieves carrier data from the new
|
|
* subscriptions framework API if available. The controller reads subscription information from the
|
|
* framework and falls back to legacy usage data if none are available.
|
|
*/
|
|
open class DataUsageSummaryPreferenceController @JvmOverloads constructor(
|
|
context: Context,
|
|
subId: Int,
|
|
private val proxySubscriptionManager: ProxySubscriptionManager =
|
|
ProxySubscriptionManager.getInstance(context),
|
|
private val networkPolicyRepository: NetworkPolicyRepository = NetworkPolicyRepository(context),
|
|
private val networkCycleDataRepositoryFactory: (
|
|
template: NetworkTemplate,
|
|
) -> INetworkCycleDataRepository = { NetworkCycleDataRepository(context, it) },
|
|
private val dataPlanRepositoryFactory: (
|
|
networkCycleDataRepository: INetworkCycleDataRepository,
|
|
) -> DataPlanRepository = { DataPlanRepositoryImpl(it) }
|
|
) : TelephonyBasePreferenceController(context, KEY) {
|
|
|
|
init {
|
|
mSubId = subId
|
|
}
|
|
|
|
private val subInfo by lazy {
|
|
if (DataUsageUtils.hasMobileData(mContext)) {
|
|
proxySubscriptionManager.getAccessibleSubscriptionInfo(mSubId)
|
|
} else null
|
|
}
|
|
|
|
private val networkTemplate by lazy { getMobileTemplate(mContext, mSubId) }
|
|
|
|
private val networkCycleDataRepository by lazy {
|
|
networkCycleDataRepositoryFactory(networkTemplate)
|
|
}
|
|
|
|
private lateinit var preference: DataUsageSummaryPreference
|
|
|
|
private val dataUsageFormatter = DataUsageFormatter(mContext)
|
|
|
|
override fun getAvailabilityStatus(subId: Int) =
|
|
if (subInfo != null) AVAILABLE else CONDITIONALLY_UNAVAILABLE
|
|
|
|
override fun displayPreference(screen: PreferenceScreen) {
|
|
super.displayPreference(screen)
|
|
preference = screen.findPreference(preferenceKey)!!
|
|
}
|
|
|
|
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
|
networkPolicyRepository.networkPolicyFlow(networkTemplate)
|
|
.collectLatestWithLifecycle(viewLifecycleOwner) { policy ->
|
|
preference.isVisible = subInfo != null && policy != null
|
|
if (policy != null) update(policy)
|
|
}
|
|
}
|
|
|
|
private suspend fun update(policy: NetworkPolicy) {
|
|
preference.setLimitInfo(policy.getLimitInfo())
|
|
val dataBarSize = max(policy.limitBytes, policy.warningBytes)
|
|
if (dataBarSize > NetworkPolicy.WARNING_DISABLED) {
|
|
setDataBarSize(dataBarSize)
|
|
}
|
|
val dataPlanInfo = withContext(Dispatchers.Default) {
|
|
dataPlanRepositoryFactory(networkCycleDataRepository).getDataPlanInfo(
|
|
policy = policy,
|
|
plans = proxySubscriptionManager.get().getSubscriptionPlans(mSubId),
|
|
)
|
|
}
|
|
Log.d(TAG, "dataPlanInfo: $dataPlanInfo")
|
|
preference.setUsageNumbers(dataPlanInfo.dataPlanUse, dataPlanInfo.dataPlanSize)
|
|
if (dataPlanInfo.dataBarSize > 0) {
|
|
preference.setChartEnabled(true)
|
|
setDataBarSize(dataPlanInfo.dataBarSize)
|
|
preference.setProgress(dataPlanInfo.dataPlanUse / dataPlanInfo.dataBarSize.toFloat())
|
|
} else {
|
|
preference.setChartEnabled(false)
|
|
}
|
|
|
|
preference.setUsageInfo(
|
|
dataPlanInfo.cycleEnd,
|
|
dataPlanInfo.snapshotTime,
|
|
subInfo?.carrierName,
|
|
dataPlanInfo.dataPlanCount,
|
|
)
|
|
}
|
|
|
|
private fun setDataBarSize(dataBarSize: Long) {
|
|
preference.setLabels(
|
|
dataUsageFormatter.formatDataUsage(/* byteValue = */ 0),
|
|
dataUsageFormatter.formatDataUsage(dataBarSize)
|
|
)
|
|
}
|
|
|
|
private fun NetworkPolicy.getLimitInfo(): CharSequence? = when {
|
|
warningBytes > 0 && limitBytes > 0 -> {
|
|
TextUtils.expandTemplate(
|
|
mContext.getText(R.string.cell_data_warning_and_limit),
|
|
dataUsageFormatter.formatDataUsage(warningBytes),
|
|
dataUsageFormatter.formatDataUsage(limitBytes),
|
|
)
|
|
}
|
|
|
|
warningBytes > 0 -> {
|
|
TextUtils.expandTemplate(
|
|
mContext.getText(R.string.cell_data_warning),
|
|
dataUsageFormatter.formatDataUsage(warningBytes),
|
|
)
|
|
}
|
|
|
|
limitBytes > 0 -> {
|
|
TextUtils.expandTemplate(
|
|
mContext.getText(R.string.cell_data_limit),
|
|
dataUsageFormatter.formatDataUsage(limitBytes),
|
|
)
|
|
}
|
|
|
|
else -> null
|
|
}
|
|
|
|
companion object {
|
|
private const val TAG = "DataUsageSummaryPC"
|
|
private const val KEY = "status_header"
|
|
}
|
|
}
|