Update time format for the first timestamp on usage chartview.

- If usage data start from the time-change event rather than full-charged event
[Before] https://screenshot.googleplex.com/BokAvKHXmt2Mmwn
[After] https://screenshot.googleplex.com/8thpgVrVt8kqo37

Bug: 336423923
Test: atest SettingsRoboTests:com.android.settings.fuelgauge.batteryusage
Change-Id: I66f8b384938f55852e28bd9f50d1a99c7fc9e41b
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index b938c72..5e17f4b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -649,9 +649,7 @@
 
     private final class HourlyChartLabelTextGenerator extends BaseLabelTextGenerator
             implements BatteryChartViewModel.LabelTextGenerator {
-        private static final int FULL_CHARGE_BATTERY_LEVEL = 100;
-
-        private boolean mIsFromFullCharge;
+        private boolean mIsStartTimestamp;
         private long mFistTimestamp;
         private long mLatestTimestamp;
 
@@ -664,7 +662,7 @@
             long timestamp = timestamps.get(index);
             boolean showMinute = false;
             if (Objects.equal(timestamp, mFistTimestamp)) {
-                if (mIsFromFullCharge) {
+                if (mIsStartTimestamp) {
                     showMinute = true;
                 } else {
                     // starts from 7 days ago
@@ -699,8 +697,7 @@
                 @NonNull final BatteryLevelData batteryLevelData) {
             BatteryLevelData.PeriodBatteryLevelData firstDayLevelData =
                     batteryLevelData.getHourlyBatteryLevelsPerDay().get(0);
-            this.mIsFromFullCharge =
-                    firstDayLevelData.getLevels().get(0) == FULL_CHARGE_BATTERY_LEVEL;
+            this.mIsStartTimestamp = firstDayLevelData.isStartTimestamp();
             this.mFistTimestamp = firstDayLevelData.getTimestamps().get(0);
             this.mLatestTimestamp =
                     getLast(
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelData.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelData.java
index 231c730..d1bf49b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelData.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelData.java
@@ -28,6 +28,7 @@
 import androidx.core.util.Preconditions;
 
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
@@ -39,17 +40,24 @@
     private static final long MIN_SIZE = 2;
     private static final long TIME_SLOT = DateUtils.HOUR_IN_MILLIS * 2;
 
+    // For testing only.
+    @VisibleForTesting @Nullable static Calendar sTestCalendar;
+
     /** A container for the battery timestamp and level data. */
     public static final class PeriodBatteryLevelData {
         // The length of mTimestamps and mLevels must be the same. mLevels[index] might be null when
         // there is no level data for the corresponding timestamp.
         private final List<Long> mTimestamps;
         private final List<Integer> mLevels;
+        private final boolean mIsStartTimestamp;
 
         public PeriodBatteryLevelData(
-                @NonNull Map<Long, Integer> batteryLevelMap, @NonNull List<Long> timestamps) {
+                @NonNull Map<Long, Integer> batteryLevelMap,
+                @NonNull List<Long> timestamps,
+                boolean isStartTimestamp) {
             mTimestamps = timestamps;
             mLevels = new ArrayList<>(timestamps.size());
+            mIsStartTimestamp = isStartTimestamp;
             for (Long timestamp : timestamps) {
                 mLevels.add(
                         batteryLevelMap.containsKey(timestamp)
@@ -66,6 +74,10 @@
             return mLevels;
         }
 
+        public boolean isStartTimestamp() {
+            return mIsStartTimestamp;
+        }
+
         @Override
         public String toString() {
             return String.format(
@@ -105,14 +117,21 @@
 
         final List<Long> timestampList = new ArrayList<>(batteryLevelMap.keySet());
         Collections.sort(timestampList);
+        final long minTimestamp = timestampList.get(0);
+        final long sixDaysAgoTimestamp =
+                DatabaseUtils.getTimestampSixDaysAgo(sTestCalendar != null ? sTestCalendar : null);
+        final boolean isStartTimestamp = minTimestamp > sixDaysAgoTimestamp;
         final List<Long> dailyTimestamps = getDailyTimestamps(timestampList);
         final List<List<Long>> hourlyTimestamps = getHourlyTimestamps(dailyTimestamps);
 
-        mDailyBatteryLevels = new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps);
+        mDailyBatteryLevels =
+                new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps, isStartTimestamp);
         mHourlyBatteryLevelsPerDay = new ArrayList<>(hourlyTimestamps.size());
-        for (List<Long> hourlyTimestampsPerDay : hourlyTimestamps) {
+        for (int i = 0; i < hourlyTimestamps.size(); i++) {
+            final List<Long> hourlyTimestampsPerDay = hourlyTimestamps.get(i);
             mHourlyBatteryLevelsPerDay.add(
-                    new PeriodBatteryLevelData(batteryLevelMap, hourlyTimestampsPerDay));
+                    new PeriodBatteryLevelData(
+                            batteryLevelMap, hourlyTimestampsPerDay, isStartTimestamp && i == 0));
         }
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index f62fdb8..44a16f1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -50,6 +50,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.testutils.FakeFeatureFactory;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -58,6 +59,7 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.Calendar;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -84,10 +86,13 @@
         MockitoAnnotations.initMocks(this);
         Locale.setDefault(new Locale("en_US"));
         org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
-        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+        final TimeZone timeZone = TimeZone.getTimeZone("UTC");
+        TimeZone.setDefault(timeZone);
         DataProcessor.sTestSystemAppsPackageNames = Set.of();
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mContext = spy(RuntimeEnvironment.application);
+        BatteryLevelData.sTestCalendar = Calendar.getInstance();
+        BatteryLevelData.sTestCalendar.setTimeZone(timeZone);
         doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
         doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
@@ -115,6 +120,11 @@
                 new BatteryEntry.NameAndIcon("fakeName", /* icon= */ null, /* iconId= */ 1));
     }
 
+    @After
+    public void tearDown() {
+        BatteryLevelData.sTestCalendar = null;
+    }
+
     @Test
     public void onDestroy_activityIsChanging_clearBatteryEntryCache() {
         doReturn(true).when(mSettingsActivity).isChangingConfigurations();
@@ -141,7 +151,8 @@
         reset(mHourlyChartView);
         setupHourlyChartViewAnimationMock();
 
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
 
         verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
         // Ignore fast refresh ui from the data processor callback.
@@ -178,7 +189,8 @@
                         BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS,
                         mBatteryChartPreferenceController.mDailyChartLabelTextGenerator);
 
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
 
         verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
         verify(mViewPropertyAnimator, atLeastOnce()).alpha(0f);
@@ -283,7 +295,8 @@
     public void onBatteryLevelDataUpdate_oneDay_showHourlyChartOnly() {
         doReturn(View.GONE).when(mHourlyChartView).getVisibility();
 
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
 
         verify(mChartSummaryTextView).setVisibility(View.VISIBLE);
         verify(mDailyChartView).setVisibility(View.GONE);
@@ -295,7 +308,8 @@
         doReturn(View.GONE).when(mHourlyChartView).getVisibility();
 
         mBatteryChartPreferenceController.mDailyChartIndex = SELECTED_INDEX_ALL;
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
 
         verify(mChartSummaryTextView).setVisibility(View.VISIBLE);
         verify(mDailyChartView).setVisibility(View.VISIBLE);
@@ -307,7 +321,8 @@
         doReturn(View.GONE).when(mHourlyChartView).getVisibility();
 
         mBatteryChartPreferenceController.mDailyChartIndex = 0;
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
 
         verify(mChartSummaryTextView).setVisibility(View.VISIBLE);
         verify(mDailyChartView).setVisibility(View.VISIBLE);
@@ -379,7 +394,8 @@
 
     @Test
     public void selectedSlotText_selectAllDaysAllHours_returnNull() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = SELECTED_INDEX_ALL;
         mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
 
@@ -390,7 +406,8 @@
 
     @Test
     public void selectedSlotText_onlyOneDayDataSelectAllHours_returnNull() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 0;
         mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
 
@@ -401,7 +418,8 @@
 
     @Test
     public void selectedSlotText_selectADayAllHours_onlyDayText() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 1;
         mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
 
@@ -412,7 +430,8 @@
 
     @Test
     public void selectedSlotText_onlyOneDayDataSelectAnHour_onlyHourText() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 0;
         mBatteryChartPreferenceController.mHourlyChartIndex = 2;
 
@@ -426,7 +445,8 @@
 
     @Test
     public void selectedSlotText_SelectADayAnHour_dayAndHourText() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 1;
         mBatteryChartPreferenceController.mHourlyChartIndex = 8;
 
@@ -439,8 +459,9 @@
     }
 
     @Test
-    public void selectedSlotText_selectFirstSlot_withMinuteText() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+    public void selectedSlotText_selectFirstSlotAfterFullCharged_withMinuteText() {
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 0;
         mBatteryChartPreferenceController.mHourlyChartIndex = 0;
 
@@ -453,8 +474,28 @@
     }
 
     @Test
+    public void selectedSlotText_selectFirstSlotAfterTimeUpdated_withMinuteText() {
+        BatteryLevelData batteryLevelData =
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 10);
+        assertThat(batteryLevelData.getHourlyBatteryLevelsPerDay().get(0).isStartTimestamp())
+                .isTrue();
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 10));
+        mBatteryChartPreferenceController.mDailyChartIndex = 0;
+        mBatteryChartPreferenceController.mHourlyChartIndex = 0;
+
+        assertThat(mBatteryChartPreferenceController.getSlotInformation(false))
+                .isEqualTo("7:01 AM - 8 AM");
+        assertThat(mBatteryChartPreferenceController.getSlotInformation(true))
+                .isEqualTo("7:01 AM to 8 AM");
+        assertThat(mBatteryChartPreferenceController.getBatteryLevelPercentageInfo())
+                .isEqualTo("Battery level percentage from 90% to 89%");
+    }
+
+    @Test
     public void selectedSlotText_selectLastSlot_withNowText() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 0;
         mBatteryChartPreferenceController.mHourlyChartIndex = 3;
 
@@ -468,7 +509,8 @@
 
     @Test
     public void selectedSlotText_selectOnlySlot_withMinuteAndNowText() {
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(1));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 1, /* levelOffset= */ 0));
         mBatteryChartPreferenceController.mDailyChartIndex = 0;
         mBatteryChartPreferenceController.mHourlyChartIndex = 0;
 
@@ -493,7 +535,8 @@
         mBatteryChartPreferenceController.mHourlyChartIndex = -1;
 
         mBatteryChartPreferenceController.onCreate(bundle);
-        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(25));
+        mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
+                createBatteryLevelData(/* numOfHours= */ 25, /* levelOffset= */ 0));
 
         assertThat(mBatteryChartPreferenceController.mDailyChartIndex)
                 .isEqualTo(expectedDailyIndex);
@@ -503,7 +546,8 @@
 
     @Test
     public void getTotalHours_getExpectedResult() {
-        BatteryLevelData batteryLevelData = createBatteryLevelData(60);
+        BatteryLevelData batteryLevelData =
+                createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0);
 
         final int totalHour = BatteryChartPreferenceController.getTotalHours(batteryLevelData);
 
@@ -516,10 +560,10 @@
         return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
     }
 
-    private static BatteryLevelData createBatteryLevelData(int numOfHours) {
+    private static BatteryLevelData createBatteryLevelData(int numOfHours, int levelOffset) {
         Map<Long, Integer> batteryLevelMap = new ArrayMap<>();
         for (int index = 0; index < numOfHours; index += 2) {
-            final Integer level = 100 - index;
+            final Integer level = 100 - index - levelOffset;
             Long timestamp = generateTimestamp(index);
             if (index == 0) {
                 timestamp += DateUtils.MINUTE_IN_MILLIS;
@@ -529,6 +573,8 @@
         }
         long current = generateTimestamp(numOfHours - 1) + DateUtils.MINUTE_IN_MILLIS * 2;
         batteryLevelMap.put(current, 66);
+
+        BatteryLevelData.sTestCalendar.setTimeInMillis(current);
         DataProcessor.sTestCurrentTimeMillis = current;
         return new BatteryLevelData(batteryLevelMap);
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
index 7faca0d..6042801 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
@@ -170,7 +170,8 @@
         final Map<Long, Integer> batteryLevelMap1 =
                 Map.of(timestamps1.get(0), 100, timestamps1.get(1), 100, timestamps1.get(2), 100);
         hourlyBatteryLevelsPerDay.add(
-                new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap1, timestamps1));
+                new BatteryLevelData.PeriodBatteryLevelData(
+                        batteryLevelMap1, timestamps1, /* isStartTimestamp= */ false));
         // Adds the day 2 data.
         hourlyBatteryLevelsPerDay.add(null);
         // Adds the day 3 data.
@@ -178,7 +179,8 @@
         final Map<Long, Integer> batteryLevelMap2 =
                 Map.of(timestamps2.get(0), 100, timestamps2.get(1), 100);
         hourlyBatteryLevelsPerDay.add(
-                new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap2, timestamps2));
+                new BatteryLevelData.PeriodBatteryLevelData(
+                        batteryLevelMap2, timestamps2, /* isStartTimestamp= */ false));
         // Fake current usage data.
         final UsageEvents.Event event1 =
                 getUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, /* timestamp= */ 1, packageName);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index 2897343..ae4c56d 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -209,7 +209,8 @@
         final Map<Long, Integer> batteryLevelMap1 =
                 Map.of(timestamps1.get(0), 100, timestamps1.get(1), 100, timestamps1.get(2), 100);
         hourlyBatteryLevelsPerDay.add(
-                new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap1, timestamps1));
+                new BatteryLevelData.PeriodBatteryLevelData(
+                        batteryLevelMap1, timestamps1, /* isStartTimestamp= */ false));
         // Adds the day 2 data.
         hourlyBatteryLevelsPerDay.add(null);
         // Adds the day 3 data.
@@ -217,7 +218,8 @@
         final Map<Long, Integer> batteryLevelMap2 =
                 Map.of(timestamps2.get(0), 100, timestamps2.get(1), 100);
         hourlyBatteryLevelsPerDay.add(
-                new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap2, timestamps2));
+                new BatteryLevelData.PeriodBatteryLevelData(
+                        batteryLevelMap2, timestamps2, /* isStartTimestamp= */ false));
         final List<AppUsageEvent> appUsageEventList = new ArrayList<>();
         // Adds some events before the start timestamp.
         appUsageEventList.add(
@@ -365,7 +367,8 @@
         final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
                 new ArrayList<>();
         hourlyBatteryLevelsPerDay.add(
-                new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
+                new BatteryLevelData.PeriodBatteryLevelData(
+                        new ArrayMap<>(), new ArrayList<>(), /* isStartTimestamp= */ false));
         assertThat(
                         DataProcessor.generateAppUsagePeriodMap(
                                 mContext,
@@ -858,7 +861,8 @@
                 new ArrayList<>();
 
         hourlyBatteryLevelsPerDay.add(
-                new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
+                new BatteryLevelData.PeriodBatteryLevelData(
+                        new ArrayMap<>(), new ArrayList<>(), /* isStartTimestamp= */ false));
 
         assertThat(
                         DataProcessor.getBatteryDiffDataMap(