Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 658bc03d authored by mxyyiyi's avatar mxyyiyi
Browse files

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
parent f437bec1
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -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(
+23 −4
Original line number Diff line number Diff line
@@ -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<Long> mTimestamps;
        private final List<Integer> mLevels;
        private final boolean mIsStartTimestamp;

        public PeriodBatteryLevelData(
                @NonNull Map<Long, Integer> batteryLevelMap, @NonNull List<Long> timestamps) {
                @NonNull Map<Long, Integer> batteryLevelMap,
                @NonNull List<Long> 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<Long> 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<Long> dailyTimestamps = getDailyTimestamps(timestampList);
        final List<List<Long>> hourlyTimestamps = getHourlyTimestamps(dailyTimestamps);

        mDailyBatteryLevels = new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps);
        mDailyBatteryLevels =
                new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps, isStartTimestamp);
        mHourlyBatteryLevelsPerDay = new ArrayList<>(hourlyTimestamps.size());
        for (List<Long> hourlyTimestampsPerDay : hourlyTimestamps) {
        for (int i = 0; i < hourlyTimestamps.size(); i++) {
            final List<Long> hourlyTimestampsPerDay = hourlyTimestamps.get(i);
            mHourlyBatteryLevelsPerDay.add(
                    new PeriodBatteryLevelData(batteryLevelMap, hourlyTimestampsPerDay));
                    new PeriodBatteryLevelData(
                            batteryLevelMap, hourlyTimestampsPerDay, isStartTimestamp && i == 0));
        }
    }

+65 −19
Original line number Diff line number Diff line
@@ -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<Long, Integer> 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);
    }
+4 −2
Original line number Diff line number Diff line
@@ -170,7 +170,8 @@ public final class DataProcessManagerTest {
        final Map<Long, Integer> 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<Long, Integer> 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);
+8 −4
Original line number Diff line number Diff line
@@ -209,7 +209,8 @@ public final class DataProcessorTest {
        final Map<Long, Integer> 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<Long, Integer> 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<AppUsageEvent> appUsageEventList = new ArrayList<>();
        // Adds some events before the start timestamp.
        appUsageEventList.add(
@@ -365,7 +367,8 @@ public final class DataProcessorTest {
        final List<BatteryLevelData.PeriodBatteryLevelData> 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(