Update battery usage data clear mechanism while time change.

- Accept time updated in the last job schedule range:
  [ max (last-full-charge / last-even-hours) , next-even-hours ]

Bug: 308714066
Fix: 308714066
Test: manual
Change-Id: Id92fffddb7666d63fce66fee696a27d957c8b537
diff --git a/protos/fuelgauge_log.proto b/protos/fuelgauge_log.proto
index e75ca48..36126a5 100644
--- a/protos/fuelgauge_log.proto
+++ b/protos/fuelgauge_log.proto
@@ -43,6 +43,7 @@
     RECHECK_JOB = 3;
     FETCH_USAGE_DATA = 4;
     INSERT_USAGE_DATA = 5;
+    TIME_UPDATED = 6;
   }
 
   optional int64 timestamp = 1;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
index ebf1543..dc8dfb6 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
@@ -70,8 +70,7 @@
                 break;
             case Intent.ACTION_TIME_CHANGED:
                 Log.d(TAG, "refresh job and clear all data from action=" + action);
-                DatabaseUtils.clearAll(context);
-                PeriodicJobManager.getInstance(context).refreshJob(/*fromBoot=*/ false);
+                DatabaseUtils.clearDataAfterTimeChangedIfNeeded(context);
                 break;
             default:
                 Log.w(TAG, "receive unsupported action=" + action);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
index 1a226fd..c298afa 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
@@ -72,8 +72,6 @@
     private static final String TAG = "DataProcessManager";
     private static final List<BatteryEventType> POWER_CONNECTION_EVENTS =
             List.of(BatteryEventType.POWER_CONNECTED, BatteryEventType.POWER_DISCONNECTED);
-    private static final List<BatteryEventType> BATTERY_LEVEL_RECORD_EVENTS =
-            List.of(BatteryEventType.FULL_CHARGED, BatteryEventType.EVEN_HOUR);
 
     // For testing only.
     @VisibleForTesting
@@ -575,7 +573,7 @@
         final List<BatteryEvent> batteryLevelRecordEvents =
                 DatabaseUtils.getBatteryEvents(
                         context, Calendar.getInstance(), lastFullChargeTime,
-                        BATTERY_LEVEL_RECORD_EVENTS);
+                        DatabaseUtils.BATTERY_LEVEL_RECORD_EVENTS);
         final long startTimestamp = batteryLevelRecordEvents.isEmpty()
                 ? lastFullChargeTime : batteryLevelRecordEvents.get(0).getTimestamp();
         final BatteryLevelData batteryLevelData = getPeriodBatteryLevelData(context, handler,
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index e78d25c..d099843 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -53,6 +53,7 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
@@ -133,6 +134,9 @@
                     .authority(AUTHORITY)
                     .appendPath(BATTERY_USAGE_SLOT_TABLE)
                     .build();
+    /** A list of level record event types to access battery usage data. */
+    public static final List<BatteryEventType> BATTERY_LEVEL_RECORD_EVENTS =
+            List.of(BatteryEventType.FULL_CHARGED, BatteryEventType.EVEN_HOUR);
 
     // For testing only.
     @VisibleForTesting
@@ -408,6 +412,35 @@
         });
     }
 
+    /** Clears all data and jobs if current timestamp is out of the range of last recorded job. */
+    public static void clearDataAfterTimeChangedIfNeeded(Context context) {
+        AsyncTask.execute(() -> {
+            try {
+                final List<BatteryEvent> batteryLevelRecordEvents =
+                        DatabaseUtils.getBatteryEvents(context, Calendar.getInstance(),
+                                getLastFullChargeTime(context), BATTERY_LEVEL_RECORD_EVENTS);
+                final long lastRecordTimestamp = batteryLevelRecordEvents.isEmpty()
+                        ? INVALID_TIMESTAMP : batteryLevelRecordEvents.get(0).getTimestamp();
+                final long nextRecordTimestamp =
+                        TimestampUtils.getNextEvenHourTimestamp(lastRecordTimestamp);
+                final long currentTime = System.currentTimeMillis();
+                final boolean isOutOfTimeRange = lastRecordTimestamp == INVALID_TIMESTAMP
+                        || currentTime < lastRecordTimestamp || currentTime > nextRecordTimestamp;
+                final String logInfo = String.format(Locale.ENGLISH,
+                        "clear database = %b, current time = %d, last record time = %d",
+                        isOutOfTimeRange, currentTime, lastRecordTimestamp);
+                Log.d(TAG, logInfo);
+                BatteryUsageLogUtils.writeLog(context, Action.TIME_UPDATED, logInfo);
+                if (isOutOfTimeRange) {
+                    DatabaseUtils.clearAll(context);
+                    PeriodicJobManager.getInstance(context).refreshJob(/* fromBoot= */ false);
+                }
+            } catch (RuntimeException e) {
+                Log.e(TAG, "refreshDataAndJobIfNeededAfterTimeChanged() failed", e);
+            }
+        });
+    }
+
     /** Returns the timestamp for 00:00 6 days before the calendar date. */
     public static long getTimestampSixDaysAgo(Calendar calendar) {
         Calendar startCalendar =