Switch Utils.formatElapsedTime to use ICU's MeasureFormat
Previously, localizable strings were used instead, causing various
difficulties and inconsistencies.
Now we use ICU's MeasureFormat. The results for English are almost
identical to the previous results (see below), and we also get higher
quality and better-vetted results for other locales.
Note: This also makes formatted strings shorter by eliminating zeros.
For example, what was previously shown as "2d 0h 15m" is now shown as
"2d 15m".
Bug: 36994779
Bug: 37701311
Test: make -j RunSettingsRoboTests
Change-Id: I78fd09e4e7f63f41ef88d3d3fc4ba2be15e1d812
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 15e4eb3..d1deaaf 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -51,6 +51,9 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.fingerprint.FingerprintManager;
+import android.icu.text.MeasureFormat;
+import android.icu.util.Measure;
+import android.icu.util.MeasureUnit;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
@@ -821,33 +824,36 @@
minutes = seconds / SECONDS_PER_MINUTE;
seconds -= minutes * SECONDS_PER_MINUTE;
}
- if (withSeconds) {
- if (days > 0) {
- sb.append(context.getString(R.string.battery_history_days,
- days, hours, minutes, seconds));
- } else if (hours > 0) {
- sb.append(context.getString(R.string.battery_history_hours,
- hours, minutes, seconds));
- } else if (minutes > 0) {
- sb.append(context.getString(R.string.battery_history_minutes, minutes, seconds));
- } else {
- sb.append(context.getString(R.string.battery_history_seconds, seconds));
- }
- } else {
- if (days > 0) {
- sb.append(context.getString(R.string.battery_history_days_no_seconds,
- days, hours, minutes));
- } else if (hours > 0) {
- sb.append(context.getString(R.string.battery_history_hours_no_seconds,
- hours, minutes));
- } else {
- sb.append(context.getString(R.string.battery_history_minutes_no_seconds, minutes));
- // Add ttsSpan if it only have minute value, because it will be read as "meters"
- TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes)
- .setUnit("minute").build();
- sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
+ final ArrayList<Measure> measureList = new ArrayList(4);
+ if (days > 0) {
+ measureList.add(new Measure(days, MeasureUnit.DAY));
+ }
+ if (hours > 0) {
+ measureList.add(new Measure(hours, MeasureUnit.HOUR));
+ }
+ if (minutes > 0) {
+ measureList.add(new Measure(minutes, MeasureUnit.MINUTE));
+ }
+ if (withSeconds && seconds > 0) {
+ measureList.add(new Measure(seconds, MeasureUnit.SECOND));
+ }
+ if (measureList.size() == 0) {
+ // Everything addable was zero, so nothing was added. We add a zero.
+ measureList.add(new Measure(0, withSeconds ? MeasureUnit.SECOND : MeasureUnit.MINUTE));
+ }
+ final Measure[] measureArray = measureList.toArray(new Measure[measureList.size()]);
+
+ final Locale locale = context.getResources().getConfiguration().locale;
+ final MeasureFormat measureFormat = MeasureFormat.getInstance(
+ locale, MeasureFormat.FormatWidth.NARROW);
+ sb.append(measureFormat.formatMeasures(measureArray));
+
+ if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) {
+ // Add ttsSpan if it only have minute value, because it will be read as "meters"
+ final TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes)
+ .setUnit("minute").build();
+ sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return sb;