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/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index b938c72e4b2..5e17f4b4871 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -649,9 +649,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
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 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
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 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@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 231c730a176..d1bf49b6cc5 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.annotation.VisibleForTesting;
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 @@ public final class BatteryLevelData {
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 mTimestamps;
private final List mLevels;
+ private final boolean mIsStartTimestamp;
public PeriodBatteryLevelData(
- @NonNull Map batteryLevelMap, @NonNull List timestamps) {
+ @NonNull Map batteryLevelMap,
+ @NonNull List 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 @@ public final class BatteryLevelData {
return mLevels;
}
+ public boolean isStartTimestamp() {
+ return mIsStartTimestamp;
+ }
+
@Override
public String toString() {
return String.format(
@@ -105,14 +117,21 @@ public final class BatteryLevelData {
final List 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 dailyTimestamps = getDailyTimestamps(timestampList);
final List> hourlyTimestamps = getHourlyTimestamps(dailyTimestamps);
- mDailyBatteryLevels = new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps);
+ mDailyBatteryLevels =
+ new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps, isStartTimestamp);
mHourlyBatteryLevelsPerDay = new ArrayList<>(hourlyTimestamps.size());
- for (List hourlyTimestampsPerDay : hourlyTimestamps) {
+ for (int i = 0; i < hourlyTimestamps.size(); i++) {
+ final List hourlyTimestampsPerDay = hourlyTimestamps.get(i);
mHourlyBatteryLevelsPerDay.add(
- new PeriodBatteryLevelData(batteryLevelMap, hourlyTimestampsPerDay));
+ new PeriodBatteryLevelData(
+ batteryLevelMap, hourlyTimestampsPerDay, isStartTimestamp && i == 0));
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
index e407c636ddf..b758df4bd6b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
@@ -67,9 +67,13 @@ public final class BootBroadcastReceiver extends BroadcastReceiver {
refreshJobs(context);
break;
case Intent.ACTION_TIME_CHANGED:
- Log.d(TAG, "refresh job and clear all data from action=" + action);
+ 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 a41e9bd0388..5b28abb422f 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -16,8 +16,6 @@
package com.android.settings.fuelgauge.batteryusage;
-import static android.content.Intent.FLAG_RECEIVER_REPLACE_PENDING;
-
import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLocalTimeForLogging;
import android.app.usage.IUsageStatsManager;
@@ -59,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;
@@ -436,6 +435,23 @@ public final class DatabaseUtils {
});
}
+ /** Clears data after a specific startTimestamp in the battery usage database. */
+ public static void clearAllAfter(Context context, long startTimestamp) {
+ AsyncTask.execute(
+ () -> {
+ try {
+ final BatteryStateDatabase database =
+ BatteryStateDatabase.getInstance(context.getApplicationContext());
+ database.appUsageEventDao().clearAllAfter(startTimestamp);
+ database.batteryEventDao().clearAllAfter(startTimestamp);
+ database.batteryStateDao().clearAllAfter(startTimestamp);
+ database.batteryUsageSlotDao().clearAllAfter(startTimestamp);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "clearAllAfter() failed", e);
+ }
+ });
+ }
+
/** Clears all out-of-date data in the battery usage database. */
public static void clearExpiredDataIfNeeded(Context context) {
AsyncTask.execute(
@@ -456,14 +472,14 @@ public final class DatabaseUtils {
});
}
- /** Clears all data and jobs if current timestamp is out of the range of last recorded job. */
+ /** Clears data after new updated time and refresh periodic job. */
public static void clearDataAfterTimeChangedIfNeeded(Context context, Intent intent) {
- if ((intent.getFlags() & FLAG_RECEIVER_REPLACE_PENDING) != 0) {
+ if ((intent.hasExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT))) {
BatteryUsageLogUtils.writeLog(
context,
Action.TIME_UPDATED,
- "Database is not cleared because the time change intent is only"
- + " for the existing pending receiver.");
+ "Database is not cleared because the time change intent is"
+ + " for time format change");
return;
}
AsyncTask.execute(
@@ -480,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 =
@@ -861,37 +893,38 @@ public final class DatabaseUtils {
}
private static void clearDataAfterTimeChangedIfNeededInternal(Context context) {
+ final long currentTime = System.currentTimeMillis();
+ final String logInfo =
+ String.format(Locale.ENGLISH, "clear data after current time = %d", currentTime);
+ Log.d(TAG, logInfo);
+ BatteryUsageLogUtils.writeLog(context, Action.TIME_UPDATED, logInfo);
+ DatabaseUtils.clearAllAfter(context, currentTime);
+ PeriodicJobManager.getInstance(context).refreshJob(/* fromBoot= */ false);
+
final List 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;
+ if (batteryLevelRecordEvents.isEmpty()) {
+ // Take a snapshot of battery usage data immediately if there's no battery events.
+ BatteryUsageDataLoader.enqueueWork(context, /* isFullChargeStart= */ true);
+ }
+ }
+
+ private static void clearDataAfterTimeZoneChangedIfNeededInternal(Context context) {
final String logInfo =
String.format(
Locale.ENGLISH,
- "clear database = %b, current time = %d, last record time = %d",
- isOutOfTimeRange,
- currentTime,
- lastRecordTimestamp);
+ "clear database for new time zone = %s",
+ TimeZone.getDefault().toString());
+ BatteryUsageLogUtils.writeLog(context, Action.TIMEZONE_UPDATED, logInfo);
Log.d(TAG, logInfo);
- BatteryUsageLogUtils.writeLog(context, Action.TIME_UPDATED, logInfo);
- if (isOutOfTimeRange) {
- DatabaseUtils.clearAll(context);
- PeriodicJobManager.getInstance(context)
- .refreshJob(/* fromBoot= */ false);
- }
+ 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(
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
index d220b15968f..249780125f2 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
@@ -55,6 +55,10 @@ public interface AppUsageEventDao {
@Query("DELETE FROM AppUsageEventEntity WHERE timestamp <= :timestamp")
void clearAllBefore(long timestamp);
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM AppUsageEventEntity WHERE timestamp >= :timestamp")
+ void clearAllAfter(long timestamp);
+
/** Clears all recorded data in the database. */
@Query("DELETE FROM AppUsageEventEntity")
void clearAll();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
index 8b696fe96c0..19d20438afa 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
@@ -65,6 +65,10 @@ public interface BatteryEventDao {
@Query("DELETE FROM BatteryEventEntity WHERE timestamp <= :timestamp")
void clearAllBefore(long timestamp);
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM BatteryEventEntity WHERE timestamp >= :timestamp")
+ void clearAllAfter(long timestamp);
+
/** Clears all recorded data in the database. */
@Query("DELETE FROM BatteryEventEntity")
void clearAll();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
index 520c6bed484..049251eb718 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
@@ -61,6 +61,10 @@ public interface BatteryStateDao {
@Query("DELETE FROM BatteryState WHERE timestamp <= :timestamp")
void clearAllBefore(long timestamp);
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM BatteryState WHERE timestamp >= :timestamp")
+ void clearAllAfter(long timestamp);
+
/** Clears all recorded data in the database. */
@Query("DELETE FROM BatteryState")
void clearAll();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
index d8cf41d0ce8..d53b0cf2532 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
@@ -52,6 +52,10 @@ public interface BatteryUsageSlotDao {
@Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp <= :timestamp")
void clearAllBefore(long timestamp);
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp")
+ void clearAllAfter(long timestamp);
+
/** Clears all recorded data in the database. */
@Query("DELETE FROM BatteryUsageSlotEntity")
void clearAll();
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 f62fdb8ce6f..44a16f19cca 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 android.widget.TextView;
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.mockito.MockitoAnnotations;
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 @@ public final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
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 final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
}
@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;
@@ -452,9 +473,29 @@ public final class BatteryChartPreferenceControllerTest {
.isEqualTo("Battery level percentage from 100% to 99%");
}
+ @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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
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 @@ public final class BatteryChartPreferenceControllerTest {
@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 @@ public final class BatteryChartPreferenceControllerTest {
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
}
- private static BatteryLevelData createBatteryLevelData(int numOfHours) {
+ private static BatteryLevelData createBatteryLevelData(int numOfHours, int levelOffset) {
Map 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 @@ public final class BatteryChartPreferenceControllerTest {
}
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/BootBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
index df330a36ac5..545f7733f41 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
@@ -35,7 +35,6 @@ import com.android.settings.testutils.BatteryTestUtils;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -64,9 +63,8 @@ public final class BootBroadcastReceiverTest {
// Inserts fake data into database for testing.
final BatteryStateDatabase database = BatteryTestUtils.setUpBatteryStateDatabase(mContext);
- BatteryTestUtils.insertDataToBatteryStateTable(
- mContext, Clock.systemUTC().millis(), "com.android.systemui");
mDao = database.batteryStateDao();
+ mDao.clearAll();
clearSharedPreferences();
}
@@ -129,10 +127,13 @@ public final class BootBroadcastReceiverTest {
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNull();
}
- @Ignore("b/314921894")
@Test
- public void onReceive_withTimeChangedIntent_clearsAllDataAndRefreshesJob()
+ public void onReceive_withTimeChangedIntentSetEarlierTime_refreshesJob()
throws InterruptedException {
+ BatteryTestUtils.insertDataToBatteryStateTable(
+ mContext, Clock.systemUTC().millis() + 60000, "com.android.systemui");
+ assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
+
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIME_CHANGED));
TimeUnit.MILLISECONDS.sleep(100);
@@ -140,6 +141,52 @@ public final class BootBroadcastReceiverTest {
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
}
+ @Test
+ public void onReceive_withTimeChangedIntentSetLaterTime_clearNoDataAndRefreshesJob()
+ throws InterruptedException {
+ BatteryTestUtils.insertDataToBatteryStateTable(
+ mContext, Clock.systemUTC().millis() - 60000, "com.android.systemui");
+ assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
+
+ mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIME_CHANGED));
+
+ TimeUnit.MILLISECONDS.sleep(100);
+ assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
+ assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
+ }
+
+ @Test
+ public void onReceive_withTimeFormatChangedIntent_skipRefreshJob() throws InterruptedException {
+ BatteryTestUtils.insertDataToBatteryStateTable(
+ mContext, Clock.systemUTC().millis() + 60000, "com.android.systemui");
+ assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
+
+ mReceiver.onReceive(
+ mContext,
+ new Intent(Intent.EXTRA_INTENT)
+ .putExtra(
+ Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,
+ Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR));
+
+ TimeUnit.MILLISECONDS.sleep(100);
+ assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
+ 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);
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 7faca0d0960..60428014048 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 @@ public final class DataProcessManagerTest {
final Map 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 @@ public final class DataProcessManagerTest {
final Map 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 28973430ce9..ae4c56d035a 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 @@ public final class DataProcessorTest {
final Map 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 @@ public final class DataProcessorTest {
final Map 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 appUsageEventList = new ArrayList<>();
// Adds some events before the start timestamp.
appUsageEventList.add(
@@ -365,7 +367,8 @@ public final class DataProcessorTest {
final List 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 @@ public final class DataProcessorTest {
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
+ new BatteryLevelData.PeriodBatteryLevelData(
+ new ArrayMap<>(), new ArrayList<>(), /* isStartTimestamp= */ false));
assertThat(
DataProcessor.getBatteryDiffDataMap(