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

This commit is contained in:
TreeHugger Robot
2022-08-03 11:49:26 +00:00
committed by Android (Google) Code Review
2 changed files with 73 additions and 119 deletions

View File

@@ -79,7 +79,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED; private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@VisibleForTesting @VisibleForTesting
Map<Integer, List<BatteryDiffEntry>> mBatteryIndexedMap; Map<Integer, Map<Integer, BatteryDiffData>> mBatteryUsageMap;
@VisibleForTesting @VisibleForTesting
Context mPrefContext; Context mPrefContext;
@@ -112,7 +112,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
private final String mPreferenceKey; private final String mPreferenceKey;
private final SettingsActivity mActivity; private final SettingsActivity mActivity;
private final InstrumentedPreferenceFragment mFragment; private final InstrumentedPreferenceFragment mFragment;
private final CharSequence[] mNotAllowShowEntryPackages;
private final CharSequence[] mNotAllowShowSummaryPackages; private final CharSequence[] mNotAllowShowSummaryPackages;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
private final Handler mHandler = new Handler(Looper.getMainLooper()); 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. // Preference cache to avoid create new instance each time.
@VisibleForTesting @VisibleForTesting
final Map<String, Preference> mPreferenceCache = new HashMap<>(); final Map<String, Preference> mPreferenceCache = new HashMap<>();
@VisibleForTesting
final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>();
public BatteryChartPreferenceControllerV2( public BatteryChartPreferenceControllerV2(
Context context, String preferenceKey, Context context, String preferenceKey,
@@ -134,10 +131,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
mIs24HourFormat = DateFormat.is24HourFormat(context); mIs24HourFormat = DateFormat.is24HourFormat(context);
mMetricsFeatureProvider = mMetricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
mNotAllowShowEntryPackages =
FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context)
.getHideApplicationEntries(context);
mNotAllowShowSummaryPackages = mNotAllowShowSummaryPackages =
FeatureFactory.getFactory(context) FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context) .getPowerUsageFeatureProvider(context)
@@ -266,9 +259,12 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) { final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null" Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
: ("size=" + batteryHistoryMap.size()))); : ("size=" + batteryHistoryMap.size())));
// TODO: implement the callback function.
final BatteryLevelData batteryLevelData = final BatteryLevelData batteryLevelData =
DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap, null); DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
batteryUsageMap -> {
mBatteryUsageMap = batteryUsageMap;
refreshUi();
});
Log.d(TAG, "getBatteryLevelData: " + batteryLevelData); Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
if (batteryLevelData == null) { if (batteryLevelData == null) {
mDailyViewModel = null; mDailyViewModel = null;
@@ -293,7 +289,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS)); BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
} }
refreshUi(); refreshUi();
// TODO: Loads item icon and label and build mBatteryIndexedMap.
} }
void setBatteryChartView(@NonNull final BatteryChartViewV2 dailyChartView, void setBatteryChartView(@NonNull final BatteryChartViewV2 dailyChartView,
@@ -335,7 +330,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
@VisibleForTesting @VisibleForTesting
boolean refreshUi() { boolean refreshUi() {
if (mBatteryIndexedMap == null || mDailyChartView == null || mHourlyChartView == null) { if (mBatteryUsageMap == null || mDailyChartView == null || mHourlyChartView == null) {
return false; return false;
} }
@@ -378,45 +373,22 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
} }
private void addAllPreferences() { private void addAllPreferences() {
// TODO: Get the right diff entry according to daily and hourly chart selection. final BatteryDiffData batteryDiffData =
final int index = mDailyChartIndex; mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
final List<BatteryDiffEntry> entries = addFooterPreferenceIfNeeded(batteryDiffData != null
mBatteryIndexedMap.get(Integer.valueOf(index)); && (!batteryDiffData.getAppDiffEntryList().isEmpty()
addFooterPreferenceIfNeeded(entries != null && !entries.isEmpty()); || !batteryDiffData.getSystemDiffEntryList().isEmpty()));
if (entries == null) { if (batteryDiffData == null) {
Log.w(TAG, "cannot find BatteryDiffEntry for:" + index); Log.w(TAG, "cannot find BatteryDiffEntry for daily_index: " + mDailyChartIndex
+ " hourly_index: " + mHourlyChartIndex);
return; 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. // Adds app entries to the list if it is not empty.
if (!appEntries.isEmpty()) { if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
addPreferenceToScreen(appEntries); addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
} }
// Adds the expabable divider if we have system entries data. // Adds the expabable divider if we have system entries data.
if (!mSystemEntries.isEmpty()) { if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
if (mExpandDividerPreference == null) { if (mExpandDividerPreference == null) {
mExpandDividerPreference = new ExpandDividerPreference(mPrefContext); mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
mExpandDividerPreference.setOnExpandListener(this); mExpandDividerPreference.setOnExpandListener(this);
@@ -490,11 +462,13 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
} }
private void refreshExpandUi() { private void refreshExpandUi() {
final List<BatteryDiffEntry> systemEntries = mBatteryUsageMap.get(mDailyChartIndex).get(
mHourlyChartIndex).getSystemDiffEntryList();
if (mIsExpanded) { if (mIsExpanded) {
addPreferenceToScreen(mSystemEntries); addPreferenceToScreen(systemEntries);
} else { } else {
// Removes and recycles all system entries to hide all of them. // 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 String prefKey = entry.mBatteryHistEntry.getKey();
final Preference pref = mAppListPrefGroup.findPreference(prefKey); final Preference pref = mAppListPrefGroup.findPreference(prefKey);
if (pref != null) { if (pref != null) {
@@ -592,11 +566,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
return !contains(packageName, mNotAllowShowSummaryPackages); return !contains(packageName, mNotAllowShowSummaryPackages);
} }
@VisibleForTesting
boolean isValidToShowEntry(String packageName) {
return !contains(packageName, mNotAllowShowEntryPackages);
}
private void addFooterPreferenceIfNeeded(boolean containAppItems) { private void addFooterPreferenceIfNeeded(boolean containAppItems) {
if (mIsFooterPrefAdded || mFooterPreference == null) { if (mIsFooterPrefAdded || mFooterPreference == null) {
return; return;
@@ -643,20 +612,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
return false; 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. // TODO: Change this method to fromLastFullCharged.
/** Used for {@link AppBatteryPreferenceController}. */ /** Used for {@link AppBatteryPreferenceController}. */

View File

@@ -19,6 +19,7 @@ package com.android.settings.fuelgauge.batteryusage;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
@@ -168,13 +169,10 @@ public final class BatteryChartPreferenceControllerV2Test {
@Test @Test
public void setBatteryChartViewModel_6Hours() { public void setBatteryChartViewModel_6Hours() {
// TODO: Removes the following line after loading mBatteryIndexedMap is supported.
mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6)); mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
verify(mDailyChartView).setVisibility(View.GONE); verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
verify(mHourlyChartView).setVisibility(View.VISIBLE); verify(mHourlyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel( verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 97, 95), List.of(100, 97, 95),
List.of("8 am", "10 am", "12 pm"), List.of("8 am", "10 am", "12 pm"),
@@ -184,13 +182,10 @@ public final class BatteryChartPreferenceControllerV2Test {
@Test @Test
public void setBatteryChartViewModel_60Hours() { public void setBatteryChartViewModel_60Hours() {
// TODO: Removes the following line after loading mBatteryIndexedMap is supported.
mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60)); mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
verify(mDailyChartView).setVisibility(View.VISIBLE); verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setVisibility(View.GONE); verify(mHourlyChartView, atLeastOnce()).setVisibility(View.GONE);
verify(mDailyChartView).setViewModel(new BatteryChartViewModel( verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 83, 59, 41), List.of(100, 83, 59, 41),
List.of("SAT", "SUN", "MON", "MON"), List.of("SAT", "SUN", "MON", "MON"),
@@ -255,6 +250,12 @@ public final class BatteryChartPreferenceControllerV2Test {
BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS)); BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
} }
@Test
public void refreshUi_normalCase_returnTrue() {
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
}
@Test @Test
public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() { public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
mBatteryChartPreferenceController.setBatteryHistoryMap(null); mBatteryChartPreferenceController.setBatteryHistoryMap(null);
@@ -275,13 +276,33 @@ public final class BatteryChartPreferenceControllerV2Test {
@Test @Test
public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() { public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
mBatteryChartPreferenceController.mHourlyChartIndex = 1; mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
doReturn(0).when(mAppListGroup).getPreferenceCount(); doReturn(0).when(mAppListGroup).getPreferenceCount();
mBatteryChartPreferenceController.refreshUi(); mBatteryChartPreferenceController.refreshUi();
verify(mAppListGroup, never()).removeAll(); 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 @Test
public void addPreferenceToScreen_emptyContent_ignoreAddPreference() { public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
mBatteryChartPreferenceController.addPreferenceToScreen( mBatteryChartPreferenceController.addPreferenceToScreen(
@@ -453,37 +474,10 @@ public final class BatteryChartPreferenceControllerV2Test {
assertThat(pref.getSummary()).isNull(); 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 @Test
public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() { public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
doReturn(1).when(mAppListGroup).getPreferenceCount(); doReturn(1).when(mAppListGroup).getPreferenceCount();
mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry); mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
doReturn("label").when(mBatteryDiffEntry).getAppLabel(); doReturn("label").when(mBatteryDiffEntry).getAppLabel();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon(); doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey(); doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
@@ -505,7 +499,7 @@ public final class BatteryChartPreferenceControllerV2Test {
public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() { public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey(); doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY); doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry); mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
// Verifies the cache is empty first. // Verifies the cache is empty first.
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty(); assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
@@ -580,18 +574,6 @@ public final class BatteryChartPreferenceControllerV2Test {
.isFalse(); .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) { private static Long generateTimestamp(int index) {
// "2021-04-23 07:00:00 UTC" + index hours // "2021-04-23 07:00:00 UTC" + index hours
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS; return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
@@ -603,6 +585,7 @@ public final class BatteryChartPreferenceControllerV2Test {
for (int index = 0; index < numOfHours; index++) { for (int index = 0; index < numOfHours; index++) {
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put("batteryLevel", Integer.valueOf(100 - index)); values.put("batteryLevel", Integer.valueOf(100 - index));
values.put("consumePower", Integer.valueOf(100 - index));
final BatteryHistEntry entry = new BatteryHistEntry(values); final BatteryHistEntry entry = new BatteryHistEntry(values);
final Map<String, BatteryHistEntry> entryMap = new HashMap<>(); final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
entryMap.put("fake_entry_key" + index, entry); entryMap.put("fake_entry_key" + index, entry);
@@ -611,6 +594,22 @@ public final class BatteryChartPreferenceControllerV2Test {
return batteryHistoryMap; 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( private BatteryDiffEntry createBatteryDiffEntry(
long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) { long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
return new BatteryDiffEntry( return new BatteryDiffEntry(