From 658bc03d4ff0efbe0bb8964f7bdd60339a9d916b Mon Sep 17 00:00:00 2001 From: mxyyiyi Date: Wed, 8 May 2024 16:24:01 +0800 Subject: [PATCH] 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 --- .../BatteryChartPreferenceController.java | 9 +- .../batteryusage/BatteryLevelData.java | 27 +++++- .../BatteryChartPreferenceControllerTest.java | 84 ++++++++++++++----- .../batteryusage/DataProcessManagerTest.java | 6 +- .../batteryusage/DataProcessorTest.java | 12 ++- 5 files changed, 103 insertions(+), 35 deletions(-) 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/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/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(