Use BytesFormatter for data usage
Change "480 B" to "480 byte". And no longer use FormattedDataUsage. Bug: 321861088 Flag: EXEMPT bug fix Test: manual - App data usage Test: unit test Change-Id: I9ed220e2d5b8fc512d7d28f6fa7faebb37beab83
This commit is contained in:
@@ -37,8 +37,7 @@ class AppDataUsageSummaryController(context: Context, preferenceKey: String) :
|
|||||||
|
|
||||||
private val dataFlow = MutableStateFlow(NetworkUsageDetailsData.AllZero)
|
private val dataFlow = MutableStateFlow(NetworkUsageDetailsData.AllZero)
|
||||||
private val dataUsageFormatter = DataUsageFormatter(context)
|
private val dataUsageFormatter = DataUsageFormatter(context)
|
||||||
private val emptyDataUsage =
|
private val emptyDataUsage = context.getPlaceholder()
|
||||||
DataUsageFormatter.FormattedDataUsage(context.getPlaceholder(), context.getPlaceholder())
|
|
||||||
|
|
||||||
private val totalUsageFlow = dataFlow.map {
|
private val totalUsageFlow = dataFlow.map {
|
||||||
dataUsageFormatter.formatDataUsage(it.totalUsage)
|
dataUsageFormatter.formatDataUsage(it.totalUsage)
|
||||||
@@ -66,18 +65,15 @@ class AppDataUsageSummaryController(context: Context, preferenceKey: String) :
|
|||||||
val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(emptyDataUsage)
|
val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(emptyDataUsage)
|
||||||
Preference(object : PreferenceModel {
|
Preference(object : PreferenceModel {
|
||||||
override val title = stringResource(R.string.total_size_label)
|
override val title = stringResource(R.string.total_size_label)
|
||||||
override val summary = { totalUsage.displayText }
|
override val summary = { totalUsage }
|
||||||
override val summaryContentDescription = { totalUsage.contentDescription }
|
|
||||||
})
|
})
|
||||||
Preference(object : PreferenceModel {
|
Preference(object : PreferenceModel {
|
||||||
override val title = stringResource(R.string.data_usage_label_foreground)
|
override val title = stringResource(R.string.data_usage_label_foreground)
|
||||||
override val summary = { foregroundUsage.displayText }
|
override val summary = { foregroundUsage }
|
||||||
override val summaryContentDescription = { foregroundUsage.contentDescription }
|
|
||||||
})
|
})
|
||||||
Preference(object : PreferenceModel {
|
Preference(object : PreferenceModel {
|
||||||
override val title = stringResource(R.string.data_usage_label_background)
|
override val title = stringResource(R.string.data_usage_label_background)
|
||||||
override val summary = { backgroundUsage.displayText }
|
override val summary = { backgroundUsage }
|
||||||
override val summaryContentDescription = { backgroundUsage.contentDescription }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -172,7 +172,7 @@ open class DataUsageList : DashboardFragment() {
|
|||||||
private fun updateSelectedCycle(usageData: NetworkUsageData) {
|
private fun updateSelectedCycle(usageData: NetworkUsageData) {
|
||||||
Log.d(TAG, "showing cycle $usageData")
|
Log.d(TAG, "showing cycle $usageData")
|
||||||
|
|
||||||
usageAmount?.title = usageData.getDataUsedString(requireContext()).displayText
|
usageAmount?.title = usageData.getDataUsedString(requireContext())
|
||||||
viewModel.selectedCycleFlow.value = usageData
|
viewModel.selectedCycleFlow.value = usageData
|
||||||
|
|
||||||
updateApps(usageData)
|
updateApps(usageData)
|
||||||
|
@@ -16,40 +16,16 @@
|
|||||||
|
|
||||||
package com.android.settings.datausage.lib
|
package com.android.settings.datausage.lib
|
||||||
|
|
||||||
import android.annotation.StringRes
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.icu.text.UnicodeSet
|
|
||||||
import android.icu.text.UnicodeSetSpanner
|
|
||||||
import android.text.BidiFormatter
|
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import com.android.internal.R
|
import com.android.settingslib.spaprivileged.framework.common.BytesFormatter
|
||||||
|
|
||||||
class DataUsageFormatter(private val context: Context) {
|
class DataUsageFormatter(private val context: Context) {
|
||||||
|
|
||||||
data class FormattedDataUsage(
|
|
||||||
val displayText: String,
|
|
||||||
val contentDescription: String,
|
|
||||||
) {
|
|
||||||
fun format(context: Context, @StringRes resId: Int, vararg formatArgs: Any?) =
|
|
||||||
FormattedDataUsage(
|
|
||||||
displayText = context.getString(resId, displayText, *formatArgs),
|
|
||||||
contentDescription = context.getString(resId, contentDescription, *formatArgs),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats the data usage. */
|
/** Formats the data usage. */
|
||||||
fun formatDataUsage(sizeBytes: Long): FormattedDataUsage {
|
fun formatDataUsage(sizeBytes: Long): String =
|
||||||
val result = Formatter.formatBytes(context.resources, sizeBytes, Formatter.FLAG_IEC_UNITS)
|
BytesFormatter(context).format(sizeBytes, BytesFormatter.UseCase.DataUsage)
|
||||||
return FormattedDataUsage(
|
|
||||||
displayText = BidiFormatter.getInstance().unicodeWrap(
|
|
||||||
context.getString(R.string.fileSizeSuffix, result.value, result.units)
|
|
||||||
),
|
|
||||||
contentDescription = context.getString(
|
|
||||||
R.string.fileSizeSuffix, result.value, result.unitsContentDescription
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
|
@@ -20,7 +20,6 @@ import android.content.Context
|
|||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import android.util.Range
|
import android.util.Range
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.datausage.lib.DataUsageFormatter.FormattedDataUsage
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base data structure representing usage data in a period.
|
* Base data structure representing usage data in a period.
|
||||||
@@ -38,11 +37,11 @@ data class NetworkUsageData(
|
|||||||
fun formatDateRange(context: Context): String =
|
fun formatDateRange(context: Context): String =
|
||||||
DateUtils.formatDateRange(context, startTime, endTime, DATE_FORMAT)
|
DateUtils.formatDateRange(context, startTime, endTime, DATE_FORMAT)
|
||||||
|
|
||||||
fun formatUsage(context: Context): FormattedDataUsage =
|
fun formatUsage(context: Context): String =
|
||||||
DataUsageFormatter(context).formatDataUsage(usage)
|
DataUsageFormatter(context).formatDataUsage(usage)
|
||||||
|
|
||||||
fun getDataUsedString(context: Context): FormattedDataUsage =
|
fun getDataUsedString(context: Context): String =
|
||||||
formatUsage(context).format(context, R.string.data_used_template)
|
context.getString(R.string.data_used_template, formatUsage(context))
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val AllZero = NetworkUsageData(
|
val AllZero = NetworkUsageData(
|
||||||
|
@@ -31,7 +31,6 @@ import androidx.preference.PreferenceScreen
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.core.BasePreferenceController
|
import com.android.settings.core.BasePreferenceController
|
||||||
import com.android.settings.datausage.DataUsageUtils
|
import com.android.settings.datausage.DataUsageUtils
|
||||||
import com.android.settings.datausage.lib.DataUsageFormatter.FormattedDataUsage
|
|
||||||
import com.android.settings.datausage.lib.DataUsageLib
|
import com.android.settings.datausage.lib.DataUsageLib
|
||||||
import com.android.settings.datausage.lib.NetworkCycleDataRepository
|
import com.android.settings.datausage.lib.NetworkCycleDataRepository
|
||||||
import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.AllTimeRange
|
import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.AllTimeRange
|
||||||
@@ -88,7 +87,7 @@ class DataUsagePreferenceController(context: Context, key: String) :
|
|||||||
getDataUsageSummaryAndEnabled()
|
getDataUsageSummaryAndEnabled()
|
||||||
}
|
}
|
||||||
preference.isEnabled = enabled
|
preference.isEnabled = enabled
|
||||||
preference.summary = summary?.displayText
|
preference.summary = summary
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getNetworkTemplate(): NetworkTemplate? =
|
private fun getNetworkTemplate(): NetworkTemplate? =
|
||||||
@@ -100,12 +99,16 @@ class DataUsagePreferenceController(context: Context, key: String) :
|
|||||||
fun createNetworkCycleDataRepository(): NetworkCycleDataRepository? =
|
fun createNetworkCycleDataRepository(): NetworkCycleDataRepository? =
|
||||||
networkTemplate?.let { NetworkCycleDataRepository(mContext, it) }
|
networkTemplate?.let { NetworkCycleDataRepository(mContext, it) }
|
||||||
|
|
||||||
private fun getDataUsageSummaryAndEnabled(): Pair<FormattedDataUsage?, Boolean> {
|
private fun getDataUsageSummaryAndEnabled(): Pair<String?, Boolean> {
|
||||||
val repository = createNetworkCycleDataRepository() ?: return null to false
|
val repository = createNetworkCycleDataRepository() ?: return null to false
|
||||||
|
|
||||||
repository.loadFirstCycle()?.let { usageData ->
|
repository.loadFirstCycle()?.let { usageData ->
|
||||||
val formattedDataUsage = usageData.formatUsage(mContext)
|
val formattedDataUsage =
|
||||||
.format(mContext, R.string.data_usage_template, usageData.formatDateRange(mContext))
|
mContext.getString(
|
||||||
|
R.string.data_usage_template,
|
||||||
|
usageData.formatUsage(mContext),
|
||||||
|
usageData.formatDateRange(mContext),
|
||||||
|
)
|
||||||
val hasUsage = usageData.usage > 0 || repository.queryUsage(AllTimeRange).usage > 0
|
val hasUsage = usageData.usage > 0 || repository.queryUsage(AllTimeRange).usage > 0
|
||||||
return formattedDataUsage to hasUsage
|
return formattedDataUsage to hasUsage
|
||||||
}
|
}
|
||||||
|
@@ -113,7 +113,7 @@ private class AppDataUsagePresenter(
|
|||||||
} else {
|
} else {
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.data_summary_format,
|
R.string.data_summary_format,
|
||||||
appUsageData.formatUsage(context).displayText,
|
appUsageData.formatUsage(context),
|
||||||
appUsageData.formatStartDate(context),
|
appUsageData.formatStartDate(context),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -56,13 +56,10 @@ class AppDataUsageSummaryControllerTest {
|
|||||||
composeTestRule.onNode(hasTextExactly("Total", "6.75 kB")).assertIsDisplayed()
|
composeTestRule.onNode(hasTextExactly("Total", "6.75 kB")).assertIsDisplayed()
|
||||||
composeTestRule.onNode(hasTextExactly("Foreground", "5.54 kB")).assertIsDisplayed()
|
composeTestRule.onNode(hasTextExactly("Foreground", "5.54 kB")).assertIsDisplayed()
|
||||||
composeTestRule.onNode(hasTextExactly("Background", "1.21 kB")).assertIsDisplayed()
|
composeTestRule.onNode(hasTextExactly("Background", "1.21 kB")).assertIsDisplayed()
|
||||||
composeTestRule.onNodeWithContentDescription("6.75 kB").assertIsDisplayed()
|
|
||||||
composeTestRule.onNodeWithContentDescription("5.54 kB").assertIsDisplayed()
|
|
||||||
composeTestRule.onNodeWithContentDescription("1.21 kB").assertIsDisplayed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun summary_zero() {
|
fun summary_smallByte() {
|
||||||
val appUsage = NetworkUsageDetailsData(
|
val appUsage = NetworkUsageDetailsData(
|
||||||
range = Range(1L, 2L),
|
range = Range(1L, 2L),
|
||||||
totalUsage = 3,
|
totalUsage = 3,
|
||||||
@@ -75,12 +72,9 @@ class AppDataUsageSummaryControllerTest {
|
|||||||
controller.Content()
|
controller.Content()
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule.onNode(hasTextExactly("Total", "3 B")).assertIsDisplayed()
|
composeTestRule.onNode(hasTextExactly("Total", "3 byte")).assertIsDisplayed()
|
||||||
composeTestRule.onNode(hasTextExactly("Foreground", "1 B")).assertIsDisplayed()
|
composeTestRule.onNode(hasTextExactly("Foreground", "1 byte")).assertIsDisplayed()
|
||||||
composeTestRule.onNode(hasTextExactly("Background", "2 B")).assertIsDisplayed()
|
composeTestRule.onNode(hasTextExactly("Background", "2 byte")).assertIsDisplayed()
|
||||||
composeTestRule.onNodeWithContentDescription("3 byte").assertIsDisplayed()
|
|
||||||
composeTestRule.onNodeWithContentDescription("1 byte").assertIsDisplayed()
|
|
||||||
composeTestRule.onNodeWithContentDescription("2 byte").assertIsDisplayed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@@ -21,7 +21,6 @@ import androidx.test.core.app.ApplicationProvider
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.android.settings.datausage.lib.DataUsageFormatter.Companion.getBytesDisplayUnit
|
import com.android.settings.datausage.lib.DataUsageFormatter.Companion.getBytesDisplayUnit
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@@ -33,26 +32,23 @@ class DataUsageFormatterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun formatDataUsage_0() {
|
fun formatDataUsage_0() {
|
||||||
val (displayText, contentDescription) = dataUsageFormatter.formatDataUsage(0)
|
val displayText = dataUsageFormatter.formatDataUsage(0)
|
||||||
|
|
||||||
assertThat(displayText).isEqualTo("0 B")
|
assertThat(displayText).isEqualTo("0 byte")
|
||||||
assertThat(contentDescription).isEqualTo("0 byte")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun formatDataUsage_1000() {
|
fun formatDataUsage_1000() {
|
||||||
val (displayText, contentDescription) = dataUsageFormatter.formatDataUsage(1000)
|
val displayText = dataUsageFormatter.formatDataUsage(1000)
|
||||||
|
|
||||||
assertThat(displayText).isEqualTo("0.98 kB")
|
assertThat(displayText).isEqualTo("0.98 kB")
|
||||||
assertThat(contentDescription).isEqualTo("0.98 kB")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun formatDataUsage_2000000() {
|
fun formatDataUsage_2000000() {
|
||||||
val (displayText, contentDescription) = dataUsageFormatter.formatDataUsage(2000000)
|
val displayText = dataUsageFormatter.formatDataUsage(2000000)
|
||||||
|
|
||||||
assertThat(displayText).isEqualTo("1.91 MB")
|
assertThat(displayText).isEqualTo("1.91 MB")
|
||||||
assertThat(contentDescription).isEqualTo("1.91 MB")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -143,7 +143,7 @@ class DataUsagePreferenceControllerTest {
|
|||||||
controller.onViewCreated(TestLifecycleOwner())
|
controller.onViewCreated(TestLifecycleOwner())
|
||||||
|
|
||||||
waitUntil { preference.isEnabled }
|
waitUntil { preference.isEnabled }
|
||||||
waitUntil { preference.summary?.contains("0 B used") == true }
|
waitUntil { preference.summary?.contains("0 byte used") == true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -159,7 +159,7 @@ class DataUsagePreferenceControllerTest {
|
|||||||
controller.onViewCreated(TestLifecycleOwner())
|
controller.onViewCreated(TestLifecycleOwner())
|
||||||
|
|
||||||
waitUntil { !preference.isEnabled }
|
waitUntil { !preference.isEnabled }
|
||||||
waitUntil { preference.summary?.contains("0 B used") == true }
|
waitUntil { preference.summary?.contains("0 byte used") == true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Reference in New Issue
Block a user