diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ad815516c61..e085be86407 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3343,6 +3343,7 @@ + diff --git a/protos/fuelgauge_log.proto b/protos/fuelgauge_log.proto index 4bee75ca058..b16958d8e2b 100644 --- a/protos/fuelgauge_log.proto +++ b/protos/fuelgauge_log.proto @@ -45,6 +45,7 @@ message BatteryUsageHistoricalLogEntry { FETCH_USAGE_DATA = 4; INSERT_USAGE_DATA = 5; TIME_UPDATED = 6; + TIMEZONE_UPDATED = 7; } 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 5fa04eb0959..b758df4bd6b 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java @@ -70,6 +70,10 @@ public final class BootBroadcastReceiver extends BroadcastReceiver { Log.d(TAG, "refresh job and clear data from action=" + action); DatabaseUtils.clearDataAfterTimeChangedIfNeeded(context, intent); break; + case Intent.ACTION_TIMEZONE_CHANGED: + Log.d(TAG, "refresh job and clear all data from action=" + action); + DatabaseUtils.clearDataAfterTimeZoneChangedIfNeeded(context); + break; default: Log.w(TAG, "receive unsupported action=" + action); } diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java index b40f71ac16e..5b28abb422f 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java +++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java @@ -57,6 +57,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.TimeZone; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -495,6 +496,22 @@ public final class DatabaseUtils { }); } + /** Clears all data and reset jobs if timezone changed. */ + public static void clearDataAfterTimeZoneChangedIfNeeded(Context context) { + AsyncTask.execute( + () -> { + try { + clearDataAfterTimeZoneChangedIfNeededInternal(context); + } catch (RuntimeException e) { + Log.e(TAG, "clearDataAfterTimeZoneChangedIfNeeded() failed", e); + BatteryUsageLogUtils.writeLog( + context, + Action.TIMEZONE_UPDATED, + "clearDataAfterTimeZoneChangedIfNeeded() failed" + e); + } + }); + } + /** Returns the timestamp for 00:00 6 days before the calendar date. */ public static long getTimestampSixDaysAgo(Calendar calendar) { Calendar startCalendar = @@ -896,6 +913,20 @@ public final class DatabaseUtils { } } + private static void clearDataAfterTimeZoneChangedIfNeededInternal(Context context) { + final String logInfo = + String.format( + Locale.ENGLISH, + "clear database for new time zone = %s", + TimeZone.getDefault().toString()); + BatteryUsageLogUtils.writeLog(context, Action.TIMEZONE_UPDATED, logInfo); + Log.d(TAG, logInfo); + DatabaseUtils.clearAll(context); + PeriodicJobManager.getInstance(context).refreshJob(/* fromBoot= */ false); + // Take a snapshot of battery usage data immediately + BatteryUsageDataLoader.enqueueWork(context, /* isFullChargeStart= */ true); + } + private static long loadLongFromContentProvider( Context context, Uri uri, final long defaultValue) { return loadFromContentProvider( diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java index 3e53b036edd..545f7733f41 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java @@ -173,6 +173,20 @@ public final class BootBroadcastReceiverTest { assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNull(); } + @Test + public void onReceive_withTimeZoneChangedIntent_clearAllDataAndRefreshesJob() + throws InterruptedException { + BatteryTestUtils.insertDataToBatteryStateTable( + mContext, Clock.systemUTC().millis(), "com.android.systemui"); + assertThat(mDao.getAllAfter(0).size()).isEqualTo(1); + + mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIMEZONE_CHANGED)); + + TimeUnit.MILLISECONDS.sleep(100); + assertThat(mDao.getAllAfter(0)).isEmpty(); + assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull(); + } + @Test public void invokeJobRecheck_broadcastsIntent() { BootBroadcastReceiver.invokeJobRecheck(mContext);