Always do interpolation for battery level data in daily chart.

Bug: 236101687
Test: make RunSettingsRoboTests
Change-Id: I07ca512ceb7a74da4256f5d6fffed6d2432f89e0
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index a004a51..a51fbec 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -218,7 +218,7 @@
      *
      * The valid result should be composed of 3 parts:
      * 1) start timestamp
-     * 2) every 0am timestamp (default timezone) between the start and end
+     * 2) every 00:00 timestamp (default timezone) between the start and end
      * 3) end timestamp
      * Otherwise, returns an empty list.
      */
@@ -277,18 +277,27 @@
     }
 
     /**
-     * @return Returns the timestamp for 0am 1 day after the given timestamp based on local
+     * @return Returns the timestamp for 00:00 1 day after the given timestamp based on local
      * timezone.
      */
     @VisibleForTesting
     static long getTimestampOfNextDay(long timestamp) {
-        final Calendar nextDayCalendar = Calendar.getInstance();
-        nextDayCalendar.setTimeInMillis(timestamp);
-        nextDayCalendar.add(Calendar.DAY_OF_YEAR, 1);
-        nextDayCalendar.set(Calendar.HOUR_OF_DAY, 0);
-        nextDayCalendar.set(Calendar.MINUTE, 0);
-        nextDayCalendar.set(Calendar.SECOND, 0);
-        return nextDayCalendar.getTimeInMillis();
+        return getTimestampWithDayDiff(timestamp, /*dayDiff=*/ 1);
+    }
+
+    /**
+     *  Returns whether currentSlot will be used in daily chart.
+     */
+    @VisibleForTesting
+    static boolean isForDailyChart(final boolean isStartOrEnd, final long currentSlot) {
+        // The start and end timestamps will always be used in daily chart.
+        if (isStartOrEnd) {
+            return true;
+        }
+
+        // The timestamps for 00:00 will be used in daily chart.
+        final long startOfTheDay = getTimestampWithDayDiff(currentSlot, /*dayDiff=*/ 0);
+        return currentSlot == startOfTheDay;
     }
 
     /**
@@ -350,10 +359,13 @@
             startIndex = 1;
             resultMap.put(expectedStartTimestamp, batteryHistoryMap.get(rawStartTimestamp));
         }
-        for (int index = startIndex; index < expectedTimestampSlots.size(); index++) {
+        final int expectedTimestampSlotsSize = expectedTimestampSlots.size();
+        for (int index = startIndex; index < expectedTimestampSlotsSize; index++) {
             final long currentSlot = expectedTimestampSlots.get(index);
+            final boolean isStartOrEnd = index == 0 || index == expectedTimestampSlotsSize - 1;
             interpolateHistoryForSlot(
-                    context, currentSlot, rawTimestampList, batteryHistoryMap, resultMap);
+                    context, currentSlot, rawTimestampList, batteryHistoryMap, resultMap,
+                    isStartOrEnd);
         }
     }
 
@@ -362,7 +374,8 @@
             final long currentSlot,
             final List<Long> rawTimestampList,
             final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
-            final Map<Long, Map<String, BatteryHistEntry>> resultMap) {
+            final Map<Long, Map<String, BatteryHistEntry>> resultMap,
+            final boolean isStartOrEnd) {
         final long[] nearestTimestamps = findNearestTimestamp(rawTimestampList, currentSlot);
         final long lowerTimestamp = nearestTimestamps[0];
         final long upperTimestamp = nearestTimestamps[1];
@@ -385,7 +398,8 @@
             return;
         }
         interpolateHistoryForSlot(context,
-                currentSlot, lowerTimestamp, upperTimestamp, batteryHistoryMap, resultMap);
+                currentSlot, lowerTimestamp, upperTimestamp, batteryHistoryMap, resultMap,
+                isStartOrEnd);
     }
 
     private static void interpolateHistoryForSlot(
@@ -394,7 +408,8 @@
             final long lowerTimestamp,
             final long upperTimestamp,
             final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
-            final Map<Long, Map<String, BatteryHistEntry>> resultMap) {
+            final Map<Long, Map<String, BatteryHistEntry>> resultMap,
+            final boolean isStartOrEnd) {
         final Map<String, BatteryHistEntry> lowerEntryDataMap =
                 batteryHistoryMap.get(lowerTimestamp);
         final Map<String, BatteryHistEntry> upperEntryDataMap =
@@ -405,7 +420,10 @@
         final long upperEntryDataBootTimestamp =
                 upperEntryDataFirstEntry.mTimestamp - upperEntryDataFirstEntry.mBootTimestamp;
         // Lower data is captured before upper data corresponding device is booting.
-        if (lowerTimestamp < upperEntryDataBootTimestamp) {
+        // Skips the booting-specific logics and always does interpolation for daily chart level
+        // data.
+        if (lowerTimestamp < upperEntryDataBootTimestamp
+                && !isForDailyChart(isStartOrEnd, currentSlot)) {
             // Provides an opportunity to force align the slot directly.
             if ((upperTimestamp - currentSlot) < 10 * DateUtils.MINUTE_IN_MILLIS) {
                 log(context, "force align into the nearest slot", currentSlot, null);
@@ -877,6 +895,16 @@
         return true;
     }
 
+    private static long getTimestampWithDayDiff(final long timestamp, final int dayDiff) {
+        final Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(timestamp);
+        calendar.add(Calendar.DAY_OF_YEAR, dayDiff);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        return calendar.getTimeInMillis();
+    }
+
     private static boolean contains(String target, Set<CharSequence> packageNames) {
         if (target != null && packageNames != null) {
             for (CharSequence packageName : packageNames) {
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 1b1e469..af1030c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -402,6 +402,17 @@
     }
 
     @Test
+    public void isForDailyChart_returnExpectedResult() {
+        assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ true, 0L)).isTrue();
+        // 2022-01-01 00:00:00
+        assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ false, 1640966400000L))
+                .isTrue();
+        // 2022-01-01 01:00:05
+        assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ false, 1640970005000L))
+                .isFalse();
+    }
+
+    @Test
     public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
         final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
                 new ArrayList<>();