The unit is chosen to have good information value while only using one unit. So 27 hours
+ * and 50 minutes would be formatted as "28 hr. ago", while 50 hours would be formatted as
+ * "2 days ago".
+ *
+ * @param context the application context
+ * @param millis the elapsed time in milli seconds
+ * @param withSeconds include seconds?
+ * @return the formatted elapsed time
+ */
+ public static CharSequence formatRelativeTime(Context context, double millis,
+ boolean withSeconds) {
+ final int seconds = (int) Math.floor(millis / 1000);
+ final RelativeUnit unit;
+ final int value;
+ if (withSeconds && seconds < 2 * SECONDS_PER_MINUTE) {
+ unit = RelativeUnit.SECONDS;
+ value = seconds;
+ } else if (seconds < 2 * SECONDS_PER_HOUR) {
+ unit = RelativeUnit.MINUTES;
+ value = (seconds + SECONDS_PER_MINUTE / 2) / SECONDS_PER_MINUTE;
+ } else if (seconds < 2 * SECONDS_PER_DAY) {
+ unit = RelativeUnit.HOURS;
+ value = (seconds + SECONDS_PER_HOUR / 2) / SECONDS_PER_HOUR;
+ } else {
+ unit = RelativeUnit.DAYS;
+ value = (seconds + SECONDS_PER_DAY / 2) / SECONDS_PER_DAY;
+ }
+
+ final Locale locale = context.getResources().getConfiguration().locale;
+ final RelativeDateTimeFormatter formatter = RelativeDateTimeFormatter.getInstance(
+ ULocale.forLocale(locale),
+ null /* default NumberFormat */,
+ RelativeDateTimeFormatter.Style.SHORT,
+ android.icu.text.DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE);
+
+ return formatter.format(value, RelativeDateTimeFormatter.Direction.LAST, unit);
+ }
+
/**
* Queries for the UserInfo of a user. Returns null if the user doesn't exist (was removed).
* @param userManager Instance of UserManager
diff --git a/src/com/android/settings/applications/RecentAppsPreferenceController.java b/src/com/android/settings/applications/RecentAppsPreferenceController.java
index d0f7584eaed..69a36f67a53 100644
--- a/src/com/android/settings/applications/RecentAppsPreferenceController.java
+++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java
@@ -235,10 +235,8 @@ public class RecentAppsPreferenceController extends AbstractPreferenceController
pref.setKey(pkgName);
pref.setTitle(appEntry.label);
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
- pref.setSummary(TextUtils.expandTemplate(
- mContext.getResources().getText(R.string.recent_app_summary),
- Utils.formatElapsedTime(mContext,
- System.currentTimeMillis() - stat.getLastTimeUsed(), false)));
+ pref.setSummary(Utils.formatRelativeTime(mContext,
+ System.currentTimeMillis() - stat.getLastTimeUsed(), false));
pref.setOrder(i);
pref.setOnPreferenceClickListener(preference -> {
AppInfoBase.startAppInfoFragment(InstalledAppDetails.class,
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 1596aca70b8..9798749ebad 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -533,7 +533,7 @@ public class PowerUsageSummary extends PowerUsageBase implements
updateScreenPreference();
updateLastFullChargePreference(lastFullChargeTime);
- final CharSequence timeSequence = Utils.formatElapsedTime(context, lastFullChargeTime,
+ final CharSequence timeSequence = Utils.formatRelativeTime(context, lastFullChargeTime,
false);
final int resId = mShowAllApps ? R.string.power_usage_list_summary_device
: R.string.power_usage_list_summary;
@@ -682,10 +682,8 @@ public class PowerUsageSummary extends PowerUsageBase implements
@VisibleForTesting
void updateLastFullChargePreference(long timeMs) {
- final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), timeMs, false);
- mLastFullChargePref.setSubtitle(
- TextUtils.expandTemplate(getText(R.string.power_last_full_charge_summary),
- timeSequence));
+ final CharSequence timeSequence = Utils.formatRelativeTime(getContext(), timeMs, false);
+ mLastFullChargePref.setSubtitle(timeSequence);
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 33ead1fd4d0..19b87a1b1fa 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -173,6 +173,105 @@ public class UtilsTest {
assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_MEASURE);
}
+ @Test
+ public void testFormatRelativeTime_WithSeconds_ShowSeconds() {
+ final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
+ final String expectedTime = "40 sec. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_NoSeconds_DoNotShowSeconds() {
+ final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
+ final String expectedTime = "1 min. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_LessThanTwoMinutes_withSeconds() {
+ final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
+ final String expectedTime = "119 sec. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_LessThanTwoMinutes_NoSeconds() {
+ final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
+ final String expectedTime = "2 min. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_TwoMinutes_withSeconds() {
+ final double testMillis = 2 * DateUtils.MINUTE_IN_MILLIS;
+ final String expectedTime = "2 min. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_LessThanTwoHours_withSeconds() {
+ final double testMillis = 119 * DateUtils.MINUTE_IN_MILLIS;
+ final String expectedTime = "119 min. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_TwoHours_withSeconds() {
+ final double testMillis = 2 * DateUtils.HOUR_IN_MILLIS;
+ final String expectedTime = "2 hr. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_LessThanTwoDays_withSeconds() {
+ final double testMillis = 47 * DateUtils.HOUR_IN_MILLIS;
+ final String expectedTime = "47 hr. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_TwoDays_withSeconds() {
+ final double testMillis = 2 * DateUtils.DAY_IN_MILLIS;
+ final String expectedTime = "2 days ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_FormatZero_WithSeconds() {
+ final double testMillis = 0;
+ final String expectedTime = "0 sec. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatRelativeTime_FormatZero_NoSeconds() {
+ final double testMillis = 0;
+ final String expectedTime = "0 min. ago";
+
+ assertThat(Utils.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
+ expectedTime);
+ }
+
@Test
public void testInitializeVolumeDoesntBreakOnNullVolume() {
VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
diff --git a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
index 2510f201faa..5e85f9b7e48 100644
--- a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
@@ -249,8 +249,6 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
- when(mMockContext.getResources().getText(eq(R.string.recent_app_summary)))
- .thenReturn(mContext.getResources().getText(R.string.recent_app_summary));
final Configuration configuration = new Configuration();
configuration.locale = Locale.US;
when(mMockContext.getResources().getConfiguration()).thenReturn(configuration);
@@ -258,7 +256,7 @@ public class RecentAppsPreferenceControllerTest {
mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
mController.displayPreference(mScreen);
- verify(mCategory).addPreference(argThat(summaryMatches("0m ago")));
+ verify(mCategory).addPreference(argThat(summaryMatches("0 min. ago")));
}
private static ArgumentMatcher