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

Commit 8d1c50b4 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support showing app usage list for two battery charts"

parents b6b6ae4e ba6c435e
Loading
Loading
Loading
Loading
+22 −67
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
    private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;

    @VisibleForTesting
    Map<Integer, List<BatteryDiffEntry>> mBatteryIndexedMap;
    Map<Integer, Map<Integer, BatteryDiffData>> mBatteryUsageMap;

    @VisibleForTesting
    Context mPrefContext;
@@ -112,7 +112,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
    private final String mPreferenceKey;
    private final SettingsActivity mActivity;
    private final InstrumentedPreferenceFragment mFragment;
    private final CharSequence[] mNotAllowShowEntryPackages;
    private final CharSequence[] mNotAllowShowSummaryPackages;
    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -120,8 +119,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
    // Preference cache to avoid create new instance each time.
    @VisibleForTesting
    final Map<String, Preference> mPreferenceCache = new HashMap<>();
    @VisibleForTesting
    final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>();

    public BatteryChartPreferenceControllerV2(
            Context context, String preferenceKey,
@@ -134,10 +131,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
        mIs24HourFormat = DateFormat.is24HourFormat(context);
        mMetricsFeatureProvider =
                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
        mNotAllowShowEntryPackages =
                FeatureFactory.getFactory(context)
                        .getPowerUsageFeatureProvider(context)
                        .getHideApplicationEntries(context);
        mNotAllowShowSummaryPackages =
                FeatureFactory.getFactory(context)
                        .getPowerUsageFeatureProvider(context)
@@ -266,9 +259,12 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
            final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
        Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
                : ("size=" + batteryHistoryMap.size())));
        // TODO: implement the callback function.
        final BatteryLevelData batteryLevelData =
                DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap, null);
                DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
                        batteryUsageMap -> {
                            mBatteryUsageMap = batteryUsageMap;
                            refreshUi();
                        });
        Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
        if (batteryLevelData == null) {
            mDailyViewModel = null;
@@ -293,7 +289,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
                    BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
        }
        refreshUi();
        // TODO: Loads item icon and label and build mBatteryIndexedMap.
    }

    void setBatteryChartView(@NonNull final BatteryChartViewV2 dailyChartView,
@@ -335,7 +330,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro

    @VisibleForTesting
    boolean refreshUi() {
        if (mBatteryIndexedMap == null || mDailyChartView == null || mHourlyChartView == null) {
        if (mBatteryUsageMap == null || mDailyChartView == null || mHourlyChartView == null) {
            return false;
        }

@@ -378,45 +373,22 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
    }

    private void addAllPreferences() {
        // TODO: Get the right diff entry according to daily and hourly chart selection.
        final int index = mDailyChartIndex;
        final List<BatteryDiffEntry> entries =
                mBatteryIndexedMap.get(Integer.valueOf(index));
        addFooterPreferenceIfNeeded(entries != null && !entries.isEmpty());
        if (entries == null) {
            Log.w(TAG, "cannot find BatteryDiffEntry for:" + index);
        final BatteryDiffData batteryDiffData =
                mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
        addFooterPreferenceIfNeeded(batteryDiffData != null
                && (!batteryDiffData.getAppDiffEntryList().isEmpty()
                || !batteryDiffData.getSystemDiffEntryList().isEmpty()));
        if (batteryDiffData == null) {
            Log.w(TAG, "cannot find BatteryDiffEntry for daily_index: " + mDailyChartIndex
                    + " hourly_index: " + mHourlyChartIndex);
            return;
        }
        // Separates data into two groups and sort them individually.
        final List<BatteryDiffEntry> appEntries = new ArrayList<>();
        mSystemEntries.clear();
        entries.forEach(entry -> {
            final String packageName = entry.getPackageName();
            if (!isValidToShowEntry(packageName)) {
                Log.w(TAG, "ignore showing item:" + packageName);
                return;
            }
            if (entry.isSystemEntry()) {
                mSystemEntries.add(entry);
            } else {
                appEntries.add(entry);
            }
            // Validates the usage time if users click a specific slot.
            if (index >= 0) {
                validateUsageTime(entry);
            }
        });
        Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
        Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
        Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
                appEntries.size(), mSystemEntries.size()));

        // Adds app entries to the list if it is not empty.
        if (!appEntries.isEmpty()) {
            addPreferenceToScreen(appEntries);
        if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
            addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
        }
        // Adds the expabable divider if we have system entries data.
        if (!mSystemEntries.isEmpty()) {
        if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
            if (mExpandDividerPreference == null) {
                mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
                mExpandDividerPreference.setOnExpandListener(this);
@@ -490,11 +462,13 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
    }

    private void refreshExpandUi() {
        final List<BatteryDiffEntry> systemEntries = mBatteryUsageMap.get(mDailyChartIndex).get(
                mHourlyChartIndex).getSystemDiffEntryList();
        if (mIsExpanded) {
            addPreferenceToScreen(mSystemEntries);
            addPreferenceToScreen(systemEntries);
        } else {
            // Removes and recycles all system entries to hide all of them.
            for (BatteryDiffEntry entry : mSystemEntries) {
            for (BatteryDiffEntry entry : systemEntries) {
                final String prefKey = entry.mBatteryHistEntry.getKey();
                final Preference pref = mAppListPrefGroup.findPreference(prefKey);
                if (pref != null) {
@@ -592,11 +566,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
        return !contains(packageName, mNotAllowShowSummaryPackages);
    }

    @VisibleForTesting
    boolean isValidToShowEntry(String packageName) {
        return !contains(packageName, mNotAllowShowEntryPackages);
    }

    private void addFooterPreferenceIfNeeded(boolean containAppItems) {
        if (mIsFooterPrefAdded || mFooterPreference == null) {
            return;
@@ -643,20 +612,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
        return false;
    }

    @VisibleForTesting
    static boolean validateUsageTime(BatteryDiffEntry entry) {
        final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
        final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
        final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
        if (foregroundUsageTimeInMs > VALID_USAGE_TIME_DURATION
                || backgroundUsageTimeInMs > VALID_USAGE_TIME_DURATION
                || totalUsageTimeInMs > VALID_USAGE_TIME_DURATION) {
            Log.e(TAG, "validateUsageTime() fail for\n" + entry);
            return false;
        }
        return true;
    }

    // TODO: Change this method to fromLastFullCharged.

    /** Used for {@link AppBatteryPreferenceController}. */
+51 −52
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.settings.fuelgauge.batteryusage;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -168,13 +169,10 @@ public final class BatteryChartPreferenceControllerV2Test {

    @Test
    public void setBatteryChartViewModel_6Hours() {
        // TODO: Removes the following line after loading mBatteryIndexedMap is supported.
        mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();

        mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));

        verify(mDailyChartView).setVisibility(View.GONE);
        verify(mHourlyChartView).setVisibility(View.VISIBLE);
        verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
        verify(mHourlyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
        verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
                List.of(100, 97, 95),
                List.of("8 am", "10 am", "12 pm"),
@@ -184,13 +182,10 @@ public final class BatteryChartPreferenceControllerV2Test {

    @Test
    public void setBatteryChartViewModel_60Hours() {
        // TODO: Removes the following line after loading mBatteryIndexedMap is supported.
        mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();

        mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));

        verify(mDailyChartView).setVisibility(View.VISIBLE);
        verify(mHourlyChartView).setVisibility(View.GONE);
        verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
        verify(mHourlyChartView, atLeastOnce()).setVisibility(View.GONE);
        verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
                List.of(100, 83, 59, 41),
                List.of("SAT", "SUN", "MON", "MON"),
@@ -255,6 +250,12 @@ public final class BatteryChartPreferenceControllerV2Test {
                BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
    }

    @Test
    public void refreshUi_normalCase_returnTrue() {
        mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
        assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
    }

    @Test
    public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
        mBatteryChartPreferenceController.setBatteryHistoryMap(null);
@@ -275,13 +276,33 @@ public final class BatteryChartPreferenceControllerV2Test {

    @Test
    public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
        mBatteryChartPreferenceController.mHourlyChartIndex = 1;
        mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
        mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
        doReturn(0).when(mAppListGroup).getPreferenceCount();

        mBatteryChartPreferenceController.refreshUi();
        verify(mAppListGroup, never()).removeAll();
    }

    @Test
    public void removeAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
        mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
        mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
        doReturn(1).when(mAppListGroup).getPreferenceCount();
        doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
        doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
        doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
        // Ensures the testing data is correct.
        assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();

        mBatteryChartPreferenceController.refreshUi();

        assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
                .isEqualTo(mPowerGaugePreference);
        verify(mAppListGroup).removeAll();
    }

    @Test
    public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
        mBatteryChartPreferenceController.addPreferenceToScreen(
@@ -453,37 +474,10 @@ public final class BatteryChartPreferenceControllerV2Test {
        assertThat(pref.getSummary()).isNull();
    }

    @Test
    public void validateUsageTime_returnTrueIfBatteryDiffEntryIsValid() {
        assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
                createBatteryDiffEntry(
                        /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
                        /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS)))
                .isTrue();
    }

    @Test
    public void validateUsageTime_foregroundTimeExceedThreshold_returnFalse() {
        assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
                createBatteryDiffEntry(
                        /*foregroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3,
                        /*backgroundUsageTimeInMs=*/ 0)))
                .isFalse();
    }

    @Test
    public void validateUsageTime_backgroundTimeExceedThreshold_returnFalse() {
        assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
                createBatteryDiffEntry(
                        /*foregroundUsageTimeInMs=*/ 0,
                        /*backgroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3)))
                .isFalse();
    }

    @Test
    public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
        doReturn(1).when(mAppListGroup).getPreferenceCount();
        mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
        mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
        doReturn("label").when(mBatteryDiffEntry).getAppLabel();
        doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
@@ -505,7 +499,7 @@ public final class BatteryChartPreferenceControllerV2Test {
    public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
        doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
        doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
        mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
        mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
        // Verifies the cache is empty first.
        assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();

@@ -580,18 +574,6 @@ public final class BatteryChartPreferenceControllerV2Test {
                .isFalse();
    }

    @Test
    public void isValidToShowEntry_returnExpectedResult() {
        assertThat(mBatteryChartPreferenceController
                .isValidToShowEntry("com.google.android.apps.scone"))
                .isTrue();

        // Verifies the items which are defined in the array list.
        assertThat(mBatteryChartPreferenceController
                .isValidToShowEntry("com.android.gms.persistent"))
                .isFalse();
    }

    private static Long generateTimestamp(int index) {
        // "2021-04-23 07:00:00 UTC" + index hours
        return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
@@ -603,6 +585,7 @@ public final class BatteryChartPreferenceControllerV2Test {
        for (int index = 0; index < numOfHours; index++) {
            final ContentValues values = new ContentValues();
            values.put("batteryLevel", Integer.valueOf(100 - index));
            values.put("consumePower", Integer.valueOf(100 - index));
            final BatteryHistEntry entry = new BatteryHistEntry(values);
            final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
            entryMap.put("fake_entry_key" + index, entry);
@@ -611,6 +594,22 @@ public final class BatteryChartPreferenceControllerV2Test {
        return batteryHistoryMap;
    }

    private Map<Integer, Map<Integer, BatteryDiffData>> createBatteryUsageMap() {
        final int selectedAll = BatteryChartViewModel.SELECTED_INDEX_ALL;
        return Map.of(
                selectedAll, Map.of(
                        selectedAll, new BatteryDiffData(
                                Arrays.asList(mBatteryDiffEntry),
                                Arrays.asList(mBatteryDiffEntry))),
                0, Map.of(
                        selectedAll, new BatteryDiffData(
                                Arrays.asList(mBatteryDiffEntry),
                                Arrays.asList(mBatteryDiffEntry)),
                        0, new BatteryDiffData(
                                Arrays.asList(mBatteryDiffEntry),
                                Arrays.asList(mBatteryDiffEntry))));
    }

    private BatteryDiffEntry createBatteryDiffEntry(
            long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
        return new BatteryDiffEntry(