Support daily and hourly battery chartview.

https://drive.google.com/file/d/1vjt6FPFAiFakb158t1IBku1IQNzVPW46/view?usp=sharing&resourcekey=0-f5m2eUKWbth6gdEFh5lOIQ

Test: manual
Bug: 236101166
Change-Id: I47d899b936742514801cd4fa7a82ddaea5d21c31
This commit is contained in:
Zaiyue Xue
2022-07-22 15:24:09 +08:00
parent 03182b5781
commit eaf4d1bb50
4 changed files with 295 additions and 318 deletions

View File

@@ -20,7 +20,6 @@ import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@@ -28,6 +27,7 @@ import android.text.TextUtils;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.Log; import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -62,22 +62,19 @@ import java.util.Map;
/** Controls the update for chart graph and the list items. */ /** Controls the update for chart graph and the list items. */
public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceController public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnDestroy, implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnDestroy,
OnSaveInstanceState, BatteryChartViewV2.OnSelectListener, OnResume, OnSaveInstanceState, OnResume, ExpandDividerPreference.OnExpandListener {
ExpandDividerPreference.OnExpandListener {
private static final String TAG = "BatteryChartPreferenceControllerV2"; private static final String TAG = "BatteryChartPreferenceControllerV2";
private static final String KEY_FOOTER_PREF = "battery_graph_footer"; private static final String KEY_FOOTER_PREF = "battery_graph_footer";
private static final String PACKAGE_NAME_NONE = "none"; private static final String PACKAGE_NAME_NONE = "none";
/** Desired battery history size for timestamp slots. */ private static final int TWENTY_FOUR_HOURS_TIME_SLOT_SIZE = 12;
public static final int DESIRED_HISTORY_SIZE = 25;
private static final int CHART_LEVEL_ARRAY_SIZE = 13;
private static final int CHART_KEY_ARRAY_SIZE = DESIRED_HISTORY_SIZE;
private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2; private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2;
private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3; private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3;
// Keys for bundle instance to restore configurations. // Keys for bundle instance to restore configurations.
private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info"; private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info";
private static final String KEY_CURRENT_TIME_SLOT = "current_time_slot"; private static final String KEY_DAILY_CHART_INDEX = "daily_chart_index";
private static final String KEY_HOURLY_CHART_INDEX = "hourly_chart_index";
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED; private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@@ -91,23 +88,26 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
@VisibleForTesting @VisibleForTesting
PreferenceGroup mAppListPrefGroup; PreferenceGroup mAppListPrefGroup;
@VisibleForTesting @VisibleForTesting
BatteryChartViewV2 mBatteryChartView;
@VisibleForTesting
ExpandDividerPreference mExpandDividerPreference; ExpandDividerPreference mExpandDividerPreference;
@VisibleForTesting @VisibleForTesting
boolean mIsExpanded = false; boolean mIsExpanded = false;
@VisibleForTesting @VisibleForTesting
long[] mBatteryHistoryKeys; BatteryChartViewV2 mDailyChartView;
@VisibleForTesting @VisibleForTesting
BatteryChartViewModel mViewModel; BatteryChartViewV2 mHourlyChartView;
@VisibleForTesting @VisibleForTesting
int mTrapezoidIndex = BatteryChartViewModel.SELECTED_INDEX_ALL; int mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
@VisibleForTesting
int mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
private boolean mIs24HourFormat; private boolean mIs24HourFormat;
private boolean mIsFooterPrefAdded = false; private boolean mIsFooterPrefAdded = false;
private PreferenceScreen mPreferenceScreen; private PreferenceScreen mPreferenceScreen;
private FooterPreference mFooterPreference; private FooterPreference mFooterPreference;
private BatteryChartViewModel mDailyViewModel;
private List<BatteryChartViewModel> mHourlyViewModels;
private final String mPreferenceKey; private final String mPreferenceKey;
private final SettingsActivity mActivity; private final SettingsActivity mActivity;
@@ -152,12 +152,14 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
if (savedInstanceState == null) { if (savedInstanceState == null) {
return; return;
} }
mTrapezoidIndex = mDailyChartIndex =
savedInstanceState.getInt(KEY_CURRENT_TIME_SLOT, mTrapezoidIndex); savedInstanceState.getInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
mHourlyChartIndex =
savedInstanceState.getInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
mIsExpanded = mIsExpanded =
savedInstanceState.getBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded); savedInstanceState.getBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
Log.d(TAG, String.format("onCreate() slotIndex=%d isExpanded=%b", Log.d(TAG, String.format("onCreate() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
mTrapezoidIndex, mIsExpanded)); mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
} }
@Override @Override
@@ -179,10 +181,11 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
if (savedInstance == null) { if (savedInstance == null) {
return; return;
} }
savedInstance.putInt(KEY_CURRENT_TIME_SLOT, mTrapezoidIndex); savedInstance.putInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
savedInstance.putInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
savedInstance.putBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded); savedInstance.putBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
Log.d(TAG, String.format("onSaveInstanceState() slotIndex=%d isExpanded=%b", Log.d(TAG, String.format("onSaveInstanceState() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
mTrapezoidIndex, mIsExpanded)); mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
} }
@Override @Override
@@ -249,18 +252,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
return true; return true;
} }
@Override
public void onSelect(int trapezoidIndex) {
Log.d(TAG, "onChartSelect:" + trapezoidIndex);
mTrapezoidIndex = trapezoidIndex;
refreshUi();
mMetricsFeatureProvider.action(
mPrefContext,
trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
: SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
}
@Override @Override
public void onExpand(boolean isExpanded) { public void onExpand(boolean isExpanded) {
mIsExpanded = isExpanded; mIsExpanded = isExpanded;
@@ -273,68 +264,104 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
void setBatteryHistoryMap( void setBatteryHistoryMap(
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) { final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
// Resets all battery history data relative variables. Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) { : ("size=" + batteryHistoryMap.size())));
mBatteryIndexedMap = null; final BatteryLevelData batteryLevelData =
mBatteryHistoryKeys = null; DataProcessor.getBatteryLevelData(mContext, batteryHistoryMap);
mViewModel = null; Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
if (batteryLevelData == null) {
mDailyViewModel = null;
mHourlyViewModels = null;
addFooterPreferenceIfNeeded(false); addFooterPreferenceIfNeeded(false);
return; return;
} }
mBatteryHistoryKeys = getBatteryHistoryKeys(batteryHistoryMap); mDailyViewModel = new BatteryChartViewModel(
List<Integer> levels = new ArrayList<Integer>(); batteryLevelData.getDailyBatteryLevels().getLevels(),
for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) { generateTimestampDayOfWeekTexts(
final long timestamp = mBatteryHistoryKeys[index * 2]; mContext, batteryLevelData.getDailyBatteryLevels().getTimestamps()),
final Map<String, BatteryHistEntry> entryMap = batteryHistoryMap.get(timestamp); mDailyChartIndex);
if (entryMap == null || entryMap.isEmpty()) { mHourlyViewModels = new ArrayList<>();
Log.e(TAG, "abnormal entry list in the timestamp:" for (BatteryLevelData.PeriodBatteryLevelData perDayData :
+ ConvertUtils.utcToLocalTime(mPrefContext, timestamp)); batteryLevelData.getHourlyBatteryLevelsPerDay()) {
levels.add(0); mHourlyViewModels.add(new BatteryChartViewModel(
continue; perDayData.getLevels(),
} generateTimestampHourTexts(
// Averages the battery level in each time slot to avoid corner conditions. mContext, perDayData.getTimestamps()),
float batteryLevelCounter = 0; mHourlyChartIndex));
for (BatteryHistEntry entry : entryMap.values()) {
batteryLevelCounter += entry.mBatteryLevel;
}
levels.add(Math.round(batteryLevelCounter / entryMap.size()));
} }
final List<String> texts = generateTimestampTexts(mBatteryHistoryKeys, mContext);
mViewModel = new BatteryChartViewModel(levels, texts, mTrapezoidIndex);
refreshUi(); refreshUi();
Log.d(TAG, String.format( // TODO: Loads item icon and label and build mBatteryIndexedMap.
"setBatteryHistoryMap() size=%d key=%s\nview model=%s",
batteryHistoryMap.size(),
ConvertUtils.utcToLocalTime(mPrefContext,
mBatteryHistoryKeys[mBatteryHistoryKeys.length - 1]),
mViewModel));
// Loads item icon and label in the background.
new LoadAllItemsInfoTask(batteryHistoryMap).execute();
} }
void setBatteryChartView(final BatteryChartViewV2 batteryChartView) { void setBatteryChartView(@NonNull final BatteryChartViewV2 dailyChartView,
if (mBatteryChartView != batteryChartView) { @NonNull final BatteryChartViewV2 hourlyChartView) {
mHandler.post(() -> setBatteryChartViewInner(batteryChartView)); if (mDailyChartView != dailyChartView || mHourlyChartView != hourlyChartView) {
mHandler.post(() -> setBatteryChartViewInner(dailyChartView, hourlyChartView));
} }
} }
private void setBatteryChartViewInner(final BatteryChartViewV2 batteryChartView) { private void setBatteryChartViewInner(@NonNull final BatteryChartViewV2 dailyChartView,
mBatteryChartView = batteryChartView; @NonNull final BatteryChartViewV2 hourlyChartView) {
mBatteryChartView.setOnSelectListener(this); mDailyChartView = dailyChartView;
mDailyChartView.setOnSelectListener(trapezoidIndex -> {
if (mDailyChartIndex == trapezoidIndex) {
return;
}
Log.d(TAG, "onDailyChartSelect:" + trapezoidIndex);
mDailyChartIndex = trapezoidIndex;
mHourlyChartIndex = BatteryChartView.SELECTED_INDEX_ALL;
refreshUi();
// TODO: Change to log daily data.
});
mHourlyChartView = hourlyChartView;
mHourlyChartView.setOnSelectListener(trapezoidIndex -> {
if (mHourlyChartIndex == trapezoidIndex) {
return;
}
Log.d(TAG, "onHourlyChartSelect:" + trapezoidIndex);
mHourlyChartIndex = trapezoidIndex;
refreshUi();
mMetricsFeatureProvider.action(
mPrefContext,
trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
: SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
});
refreshUi(); refreshUi();
} }
@VisibleForTesting @VisibleForTesting
boolean refreshUi() { boolean refreshUi() {
// Invalid refresh condition. if (mBatteryIndexedMap == null || mDailyChartView == null || mHourlyChartView == null) {
if (mBatteryIndexedMap == null || mBatteryChartView == null) {
return false; return false;
} }
if (mViewModel != null) {
mViewModel.setSelectedIndex(mTrapezoidIndex); if (mDailyViewModel == null || mHourlyViewModels == null) {
// Fail to get battery level data, show an empty hourly chart view.
mDailyChartView.setVisibility(View.GONE);
mHourlyChartView.setViewModel(null);
return false;
}
if (isBatteryLevelDataInOneDay()) {
// Only 1 day data, hide the daily chart view.
mDailyChartView.setVisibility(View.GONE);
mDailyChartIndex = 0;
} else {
mDailyChartView.setVisibility(View.VISIBLE);
mDailyViewModel.setSelectedIndex(mDailyChartIndex);
mDailyChartView.setViewModel(mDailyViewModel);
}
if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
// Multiple days are selected, hide the hourly chart view.
mHourlyChartView.setVisibility(View.GONE);
} else {
mHourlyChartView.setVisibility(View.VISIBLE);
final BatteryChartViewModel hourlyViewModel = mHourlyViewModels.get(mDailyChartIndex);
hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
mHourlyChartView.setViewModel(hourlyViewModel);
} }
mBatteryChartView.setViewModel(mViewModel);
mHandler.post(() -> { mHandler.post(() -> {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
@@ -348,11 +375,13 @@ 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 int index = mDailyChartIndex;
final List<BatteryDiffEntry> entries = final List<BatteryDiffEntry> entries =
mBatteryIndexedMap.get(Integer.valueOf(mTrapezoidIndex)); mBatteryIndexedMap.get(Integer.valueOf(index));
addFooterPreferenceIfNeeded(entries != null && !entries.isEmpty()); addFooterPreferenceIfNeeded(entries != null && !entries.isEmpty());
if (entries == null) { if (entries == null) {
Log.w(TAG, "cannot find BatteryDiffEntry for:" + mTrapezoidIndex); Log.w(TAG, "cannot find BatteryDiffEntry for:" + index);
return; return;
} }
// Separates data into two groups and sort them individually. // Separates data into two groups and sort them individually.
@@ -370,7 +399,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
appEntries.add(entry); appEntries.add(entry);
} }
// Validates the usage time if users click a specific slot. // Validates the usage time if users click a specific slot.
if (mTrapezoidIndex >= 0) { if (index >= 0) {
validateUsageTime(entry); validateUsageTime(entry);
} }
}); });
@@ -488,6 +517,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
} }
private String getSlotInformation(boolean isApp, String slotInformation) { private String getSlotInformation(boolean isApp, String slotInformation) {
// TODO: Updates the right slot information from daily and hourly chart selection.
// Null means we show all information without a specific time slot. // Null means we show all information without a specific time slot.
if (slotInformation == null) { if (slotInformation == null) {
return isApp return isApp
@@ -501,16 +531,8 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
} }
private String getSlotInformation() { private String getSlotInformation() {
if (mTrapezoidIndex < 0) { // TODO: Generate the right slot information from daily and hourly chart selection.
return null; return null;
}
final String fromHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
mBatteryHistoryKeys[mTrapezoidIndex * 2], mIs24HourFormat);
final String toHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
mBatteryHistoryKeys[(mTrapezoidIndex + 1) * 2], mIs24HourFormat);
return mIs24HourFormat
? String.format("%s%s", fromHour, toHour)
: String.format("%s %s", fromHour, toHour);
} }
@VisibleForTesting @VisibleForTesting
@@ -584,13 +606,25 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference)); mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
} }
private static List<String> generateTimestampTexts( private boolean isBatteryLevelDataInOneDay() {
@NonNull long[] timestamps, Context context) { return mHourlyViewModels.size() == 1;
}
private static List<String> generateTimestampDayOfWeekTexts(
@NonNull final Context context, @NonNull final List<Long> timestamps) {
final ArrayList<String> texts = new ArrayList<>();
for (Long timestamp : timestamps) {
texts.add(ConvertUtils.utcToLocalTimeDayOfWeek(context, timestamp));
}
return texts;
}
private static List<String> generateTimestampHourTexts(
@NonNull final Context context, @NonNull final List<Long> timestamps) {
final boolean is24HourFormat = DateFormat.is24HourFormat(context); final boolean is24HourFormat = DateFormat.is24HourFormat(context);
final List<String> texts = new ArrayList<String>(); final ArrayList<String> texts = new ArrayList<>();
for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) { for (Long timestamp : timestamps) {
texts.add(ConvertUtils.utcToLocalTimeHour(context, timestamps[index * 2], texts.add(ConvertUtils.utcToLocalTimeHour(context, timestamp, is24HourFormat));
is24HourFormat));
} }
return texts; return texts;
} }
@@ -620,6 +654,8 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
return true; return true;
} }
// TODO: Change this method to fromLastFullCharged.
/** Used for {@link AppBatteryPreferenceController}. */ /** Used for {@link AppBatteryPreferenceController}. */
public static List<BatteryDiffEntry> getBatteryLast24HrUsageData(Context context) { public static List<BatteryDiffEntry> getBatteryLast24HrUsageData(Context context) {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
@@ -632,16 +668,27 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
} }
Log.d(TAG, String.format("getBatteryLast24HrData() size=%d time=%d/ms", Log.d(TAG, String.format("getBatteryLast24HrData() size=%d time=%d/ms",
batteryHistoryMap.size(), (System.currentTimeMillis() - start))); batteryHistoryMap.size(), (System.currentTimeMillis() - start)));
final List<Long> batteryHistoryKeyList =
new ArrayList<>(batteryHistoryMap.keySet());
Collections.sort(batteryHistoryKeyList);
final long[] batteryHistoryKeys = new long[TWENTY_FOUR_HOURS_TIME_SLOT_SIZE + 1];
for (int index = 0; index < batteryHistoryKeys.length; index++) {
batteryHistoryKeys[index] = batteryHistoryKeyList.get(index);
}
final Map<Integer, List<BatteryDiffEntry>> batteryIndexedMap = final Map<Integer, List<BatteryDiffEntry>> batteryIndexedMap =
ConvertUtils.getIndexedUsageMap( ConvertUtils.getIndexedUsageMap(
context, context,
/*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1, /*timeSlotSize=*/ TWENTY_FOUR_HOURS_TIME_SLOT_SIZE,
getBatteryHistoryKeys(batteryHistoryMap), batteryHistoryKeys,
batteryHistoryMap, batteryHistoryMap,
/*purgeLowPercentageAndFakeData=*/ true); /*purgeLowPercentageAndFakeData=*/ true);
return batteryIndexedMap.get(BatteryChartViewModel.SELECTED_INDEX_ALL); return batteryIndexedMap.get(BatteryChartViewModel.SELECTED_INDEX_ALL);
} }
// TODO: Change this method to fromLastFullCharged.
/** Used for {@link AppBatteryPreferenceController}. */ /** Used for {@link AppBatteryPreferenceController}. */
public static BatteryDiffEntry getBatteryLast24HrUsageData( public static BatteryDiffEntry getBatteryLast24HrUsageData(
Context context, String packageName, int userId) { Context context, String packageName, int userId) {
@@ -663,65 +710,4 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
} }
return null; return null;
} }
private static long[] getBatteryHistoryKeys(
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
final List<Long> batteryHistoryKeyList =
new ArrayList<>(batteryHistoryMap.keySet());
Collections.sort(batteryHistoryKeyList);
final long[] batteryHistoryKeys = new long[CHART_KEY_ARRAY_SIZE];
for (int index = 0; index < CHART_KEY_ARRAY_SIZE; index++) {
batteryHistoryKeys[index] = batteryHistoryKeyList.get(index);
}
return batteryHistoryKeys;
}
// Loads all items icon and label in the background.
private final class LoadAllItemsInfoTask
extends AsyncTask<Void, Void, Map<Integer, List<BatteryDiffEntry>>> {
private long[] mBatteryHistoryKeysCache;
private Map<Long, Map<String, BatteryHistEntry>> mBatteryHistoryMap;
private LoadAllItemsInfoTask(
Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
this.mBatteryHistoryMap = batteryHistoryMap;
this.mBatteryHistoryKeysCache = mBatteryHistoryKeys;
}
@Override
protected Map<Integer, List<BatteryDiffEntry>> doInBackground(Void... voids) {
if (mPrefContext == null || mBatteryHistoryKeysCache == null) {
return null;
}
final long startTime = System.currentTimeMillis();
final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap =
ConvertUtils.getIndexedUsageMap(
mPrefContext, /*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1,
mBatteryHistoryKeysCache, mBatteryHistoryMap,
/*purgeLowPercentageAndFakeData=*/ true);
// Pre-loads each BatteryDiffEntry relative icon and label for all slots.
for (List<BatteryDiffEntry> entries : indexedUsageMap.values()) {
entries.forEach(entry -> entry.loadLabelAndIcon());
}
Log.d(TAG, String.format("execute LoadAllItemsInfoTask in %d/ms",
(System.currentTimeMillis() - startTime)));
return indexedUsageMap;
}
@Override
protected void onPostExecute(
Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) {
mBatteryHistoryMap = null;
mBatteryHistoryKeysCache = null;
if (indexedUsageMap == null) {
return;
}
// Posts results back to main thread to refresh UI.
mHandler.post(() -> {
mBatteryIndexedMap = indexedUsageMap;
refreshUi();
});
}
}
} }

View File

@@ -20,6 +20,8 @@ import androidx.annotation.NonNull;
import androidx.core.util.Preconditions; import androidx.core.util.Preconditions;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Objects;
/** Wraps the battery timestamp and level data used for battery usage chart. */ /** Wraps the battery timestamp and level data used for battery usage chart. */
public final class BatteryLevelData { public final class BatteryLevelData {
@@ -46,6 +48,12 @@ public final class BatteryLevelData {
public List<Integer> getLevels() { public List<Integer> getLevels() {
return mLevels; return mLevels;
} }
@Override
public String toString() {
return String.format(Locale.ENGLISH, "timestamps: %s; levels: %s",
Objects.toString(mTimestamps), Objects.toString(mLevels));
}
} }
/** /**
@@ -78,4 +86,13 @@ public final class BatteryLevelData {
public List<PeriodBatteryLevelData> getHourlyBatteryLevelsPerDay() { public List<PeriodBatteryLevelData> getHourlyBatteryLevelsPerDay() {
return mHourlyBatteryLevelsPerDay; return mHourlyBatteryLevelsPerDay;
} }
}
@Override
public String toString() {
return String.format(Locale.ENGLISH,
"dailyBatteryLevels: %s; hourlyBatteryLevelsPerDay: %s",
Objects.toString(mDailyBatteryLevels),
Objects.toString(mHourlyBatteryLevelsPerDay));
}
}

View File

@@ -140,7 +140,7 @@ public final class ConvertUtils {
/** Converts UTC timestamp to local time hour data. */ /** Converts UTC timestamp to local time hour data. */
public static String utcToLocalTimeHour( public static String utcToLocalTimeHour(
Context context, long timestamp, boolean is24HourFormat) { final Context context, final long timestamp, final boolean is24HourFormat) {
final Locale locale = getLocale(context); final Locale locale = getLocale(context);
// e.g. for 12-hour format: 9 pm // e.g. for 12-hour format: 9 pm
// e.g. for 24-hour format: 09:00 // e.g. for 24-hour format: 09:00
@@ -149,6 +149,13 @@ public final class ConvertUtils {
return DateFormat.format(pattern, timestamp).toString().toLowerCase(locale); return DateFormat.format(pattern, timestamp).toString().toLowerCase(locale);
} }
/** Converts UTC timestamp to local time day of week data. */
public static String utcToLocalTimeDayOfWeek(final Context context, final long timestamp) {
final Locale locale = getLocale(context);
final String pattern = DateFormat.getBestDateTimePattern(locale, "E");
return DateFormat.format(pattern, timestamp).toString().toUpperCase(locale);
}
/** Gets indexed battery usage data for each corresponding time slot. */ /** Gets indexed battery usage data for each corresponding time slot. */
public static Map<Integer, List<BatteryDiffEntry>> getIndexedUsageMap( public static Map<Integer, List<BatteryDiffEntry>> getIndexedUsageMap(
final Context context, final Context context,

View File

@@ -21,6 +21,7 @@ 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.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.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -32,6 +33,7 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.LocaleList; import android.os.LocaleList;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.view.View;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
@@ -64,8 +66,6 @@ import java.util.TimeZone;
public final class BatteryChartPreferenceControllerV2Test { public final class BatteryChartPreferenceControllerV2Test {
private static final String PREF_KEY = "pref_key"; private static final String PREF_KEY = "pref_key";
private static final String PREF_SUMMARY = "fake preference summary"; private static final String PREF_SUMMARY = "fake preference summary";
private static final int DESIRED_HISTORY_SIZE =
BatteryChartPreferenceControllerV2.DESIRED_HISTORY_SIZE;
@Mock @Mock
private InstrumentedPreferenceFragment mFragment; private InstrumentedPreferenceFragment mFragment;
@@ -78,7 +78,9 @@ public final class BatteryChartPreferenceControllerV2Test {
@Mock @Mock
private BatteryHistEntry mBatteryHistEntry; private BatteryHistEntry mBatteryHistEntry;
@Mock @Mock
private BatteryChartViewV2 mBatteryChartView; private BatteryChartViewV2 mDailyChartView;
@Mock
private BatteryChartViewV2 mHourlyChartView;
@Mock @Mock
private PowerGaugePreference mPowerGaugePreference; private PowerGaugePreference mPowerGaugePreference;
@Mock @Mock
@@ -111,7 +113,8 @@ public final class BatteryChartPreferenceControllerV2Test {
mBatteryChartPreferenceController = createController(); mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mPrefContext = mContext; mBatteryChartPreferenceController.mPrefContext = mContext;
mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup; mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
mBatteryChartPreferenceController.mBatteryChartView = mBatteryChartView; mBatteryChartPreferenceController.mDailyChartView = mDailyChartView;
mBatteryChartPreferenceController.mHourlyChartView = mHourlyChartView;
mBatteryDiffEntry = new BatteryDiffEntry( mBatteryDiffEntry = new BatteryDiffEntry(
mContext, mContext,
/*foregroundUsageTimeInMs=*/ 1, /*foregroundUsageTimeInMs=*/ 1,
@@ -123,12 +126,10 @@ public final class BatteryChartPreferenceControllerV2Test {
BatteryDiffEntry.sResourceCache.put( BatteryDiffEntry.sResourceCache.put(
"fakeBatteryDiffEntryKey", "fakeBatteryDiffEntryKey",
new BatteryEntry.NameAndIcon("fakeName", /*icon=*/ null, /*iconId=*/ 1)); new BatteryEntry.NameAndIcon("fakeName", /*icon=*/ null, /*iconId=*/ 1));
mBatteryChartPreferenceController.setBatteryHistoryMap(
createBatteryHistoryMap());
} }
@Test @Test
public void testOnDestroy_activityIsChanging_clearBatteryEntryCache() { public void onDestroy_activityIsChanging_clearBatteryEntryCache() {
doReturn(true).when(mSettingsActivity).isChangingConfigurations(); doReturn(true).when(mSettingsActivity).isChangingConfigurations();
// Ensures the testing environment is correct. // Ensures the testing environment is correct.
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1); assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
@@ -138,7 +139,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnDestroy_activityIsNotChanging_notClearBatteryEntryCache() { public void onDestroy_activityIsNotChanging_notClearBatteryEntryCache() {
doReturn(false).when(mSettingsActivity).isChangingConfigurations(); doReturn(false).when(mSettingsActivity).isChangingConfigurations();
// Ensures the testing environment is correct. // Ensures the testing environment is correct.
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1); assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
@@ -148,7 +149,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnDestroy_clearPreferenceCache() { public void onDestroy_clearPreferenceCache() {
// Ensures the testing environment is correct. // Ensures the testing environment is correct.
mBatteryChartPreferenceController.mPreferenceCache.put( mBatteryChartPreferenceController.mPreferenceCache.put(
PREF_KEY, mPowerGaugePreference); PREF_KEY, mPowerGaugePreference);
@@ -160,81 +161,113 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnDestroy_removeAllPreferenceFromPreferenceGroup() { public void onDestroy_removeAllPreferenceFromPreferenceGroup() {
mBatteryChartPreferenceController.onDestroy(); mBatteryChartPreferenceController.onDestroy();
verify(mAppListGroup).removeAll(); verify(mAppListGroup).removeAll();
} }
@Test @Test
public void testSetBatteryHistoryMap_createExpectedKeysAndLevels() { public void setBatteryChartViewModel_6Hours() {
mBatteryChartPreferenceController.setBatteryHistoryMap( // TODO: Removes the following line after loading mBatteryIndexedMap is supported.
createBatteryHistoryMap()); mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();
// Verifies the created battery keys array. mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index]) verify(mDailyChartView).setVisibility(View.GONE);
// These values is are calculated by hand from createBatteryHistoryMap(). verify(mHourlyChartView).setVisibility(View.VISIBLE);
.isEqualTo(generateTimestamp(index)); verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
} List.of(100, 97, 95),
// Verifies the created battery levels array. List.of("8 am", "10 am", "12 pm"),
for (int index = 0; index < 13; index++) { BatteryChartViewModel.SELECTED_INDEX_ALL));
assertThat(mBatteryChartPreferenceController.mViewModel.levels().get(index))
// These values is are calculated by hand from createBatteryHistoryMap().
.isEqualTo(100 - index * 2);
}
assertThat(mBatteryChartPreferenceController.mBatteryIndexedMap).hasSize(13);
} }
@Test @Test
public void testSetBatteryHistoryMap_largeSize_createExpectedKeysAndLevels() { public void setBatteryChartViewModel_60Hours() {
mBatteryChartPreferenceController.setBatteryHistoryMap( // TODO: Removes the following line after loading mBatteryIndexedMap is supported.
createBatteryHistoryMap()); mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();
// Verifies the created battery keys array. mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index]) verify(mDailyChartView).setVisibility(View.VISIBLE);
// These values is are calculated by hand from createBatteryHistoryMap(). verify(mHourlyChartView).setVisibility(View.GONE);
.isEqualTo(generateTimestamp(index)); verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
} List.of(100, 83, 59, 41),
// Verifies the created battery levels array. List.of("SAT", "SUN", "MON", "MON"),
for (int index = 0; index < 13; index++) { BatteryChartViewModel.SELECTED_INDEX_ALL));
assertThat(mBatteryChartPreferenceController.mViewModel.levels().get(index))
// These values is are calculated by hand from createBatteryHistoryMap(). reset(mDailyChartView);
.isEqualTo(100 - index * 2); reset(mHourlyChartView);
} mBatteryChartPreferenceController.mDailyChartIndex = 0;
assertThat(mBatteryChartPreferenceController.mBatteryIndexedMap).hasSize(13); mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setVisibility(View.VISIBLE);
verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 83, 59, 41),
List.of("SAT", "SUN", "MON", "MON"),
0));
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 97, 95, 93, 91, 89, 87, 85, 83),
List.of("8 am", "10 am", "12 pm", "2 pm", "4 pm", "6 pm", "8 pm", "10 pm",
"12 am"),
BatteryChartViewModel.SELECTED_INDEX_ALL));
reset(mDailyChartView);
reset(mHourlyChartView);
mBatteryChartPreferenceController.mDailyChartIndex = 1;
mBatteryChartPreferenceController.mHourlyChartIndex = 6;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setVisibility(View.VISIBLE);
verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 83, 59, 41),
List.of("SAT", "SUN", "MON", "MON"),
1));
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
List.of(83, 81, 79, 77, 75, 73, 71, 69, 67, 65, 63, 61, 59),
List.of("12 am", "2 am", "4 am", "6 am", "8 am", "10 am", "12 pm", "2 pm",
"4 pm", "6 pm", "8 pm", "10 pm", "12 am"),
6));
reset(mDailyChartView);
reset(mHourlyChartView);
mBatteryChartPreferenceController.mDailyChartIndex = 2;
mBatteryChartPreferenceController.mHourlyChartIndex =
BatteryChartViewModel.SELECTED_INDEX_ALL;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setVisibility(View.VISIBLE);
verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 83, 59, 41),
List.of("SAT", "SUN", "MON", "MON"),
2));
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
List.of(59, 57, 55, 53, 51, 49, 47, 45, 43, 41),
List.of("12 am", "2 am", "4 am", "6 am", "8 am", "10 am", "12 pm", "2 pm",
"4 pm", "6 pm"),
BatteryChartViewModel.SELECTED_INDEX_ALL));
} }
@Test @Test
public void testSetBatteryChartViewModel() { public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
verify(mBatteryChartPreferenceController.mBatteryChartView)
.setViewModel(new BatteryChartViewModel(
List.of(100, 98, 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76),
List.of("7 am", "9 am", "11 am", "1 pm", "3 pm", "5 pm", "7 pm",
"9 pm", "11 pm", "1 am", "3 am", "5 am", "7 am"),
BatteryChartViewModel.SELECTED_INDEX_ALL));
}
@Test
public void testRefreshUi_refresh() {
assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
}
@Test
public void testRefreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
mBatteryChartPreferenceController.setBatteryHistoryMap(null); mBatteryChartPreferenceController.setBatteryHistoryMap(null);
assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse(); assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
} }
@Test @Test
public void testRefreshUi_batteryChartViewIsNull_ignoreRefresh() { public void refreshUi_dailyChartViewIsNull_ignoreRefresh() {
mBatteryChartPreferenceController.mBatteryChartView = null; mBatteryChartPreferenceController.mDailyChartView = null;
assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse(); assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
} }
@Test @Test
public void testRemoveAndCacheAllPrefs_emptyContent_ignoreRemoveAll() { public void refreshUi_hourlyChartViewIsNull_ignoreRefresh() {
mBatteryChartPreferenceController.mTrapezoidIndex = 1; mBatteryChartPreferenceController.mHourlyChartView = null;
assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
}
@Test
public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
mBatteryChartPreferenceController.mHourlyChartIndex = 1;
doReturn(0).when(mAppListGroup).getPreferenceCount(); doReturn(0).when(mAppListGroup).getPreferenceCount();
mBatteryChartPreferenceController.refreshUi(); mBatteryChartPreferenceController.refreshUi();
@@ -242,30 +275,14 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testRemoveAndCacheAllPrefs_buildCacheAndRemoveAllPreference() { public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
mBatteryChartPreferenceController.mTrapezoidIndex = 1;
doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
// 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 testAddPreferenceToScreen_emptyContent_ignoreAddPreference() {
mBatteryChartPreferenceController.addPreferenceToScreen( mBatteryChartPreferenceController.addPreferenceToScreen(
new ArrayList<BatteryDiffEntry>()); new ArrayList<BatteryDiffEntry>());
verify(mAppListGroup, never()).addPreference(any()); verify(mAppListGroup, never()).addPreference(any());
} }
@Test @Test
public void testAddPreferenceToScreen_addPreferenceIntoScreen() { public void addPreferenceToScreen_addPreferenceIntoScreen() {
final String appLabel = "fake app label"; final String appLabel = "fake app label";
doReturn(1).when(mAppListGroup).getPreferenceCount(); doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon(); doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
@@ -294,7 +311,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testAddPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() { public void addPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
final String appLabel = "fake app label"; final String appLabel = "fake app label";
doReturn(1).when(mAppListGroup).getPreferenceCount(); doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon(); doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
@@ -309,7 +326,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testHandlePreferenceTreeiClick_notPowerGaugePreference_returnFalse() { public void handlePreferenceTreeiClick_notPowerGaugePreference_returnFalse() {
assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup)) assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup))
.isFalse(); .isFalse();
@@ -320,7 +337,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testHandlePreferenceTreeClick_forAppEntry_returnTrue() { public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
doReturn(false).when(mBatteryHistEntry).isAppEntry(); doReturn(false).when(mBatteryHistEntry).isAppEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry(); doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
@@ -336,7 +353,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testHandlePreferenceTreeClick_forSystemEntry_returnTrue() { public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
mBatteryChartPreferenceController.mBatteryUtils = mBatteryUtils; mBatteryChartPreferenceController.mBatteryUtils = mBatteryUtils;
doReturn(true).when(mBatteryHistEntry).isAppEntry(); doReturn(true).when(mBatteryHistEntry).isAppEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry(); doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
@@ -353,7 +370,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testSetPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() { public void setPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext); final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY); pref.setSummary(PREF_SUMMARY);
@@ -365,7 +382,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testSetPreferenceSummary_setBackgroundUsageTimeOnly() { public void setPreferenceSummary_setBackgroundUsageTimeOnly() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext); final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY); pref.setSummary(PREF_SUMMARY);
@@ -377,7 +394,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testSetPreferenceSummary_setTotalUsageTimeLessThanAMinute() { public void setPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext); final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY); pref.setSummary(PREF_SUMMARY);
@@ -389,7 +406,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testSetPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() { public void setPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext); final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY); pref.setSummary(PREF_SUMMARY);
@@ -402,7 +419,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testSetPreferenceSummary_setTotalAndBackgroundUsageTime() { public void setPreferenceSummary_setTotalAndBackgroundUsageTime() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext); final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY); pref.setSummary(PREF_SUMMARY);
@@ -414,7 +431,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testSetPreferenceSummary_notAllowShownPackage_setSummayAsNull() { public void setPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext); final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY); pref.setSummary(PREF_SUMMARY);
final BatteryDiffEntry batteryDiffEntry = final BatteryDiffEntry batteryDiffEntry =
@@ -429,7 +446,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testValidateUsageTime_returnTrueIfBatteryDiffEntryIsValid() { public void validateUsageTime_returnTrueIfBatteryDiffEntryIsValid() {
assertThat(BatteryChartPreferenceControllerV2.validateUsageTime( assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
createBatteryDiffEntry( createBatteryDiffEntry(
/*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS, /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
@@ -438,7 +455,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testValidateUsageTime_foregroundTimeExceedThreshold_returnFalse() { public void validateUsageTime_foregroundTimeExceedThreshold_returnFalse() {
assertThat(BatteryChartPreferenceControllerV2.validateUsageTime( assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
createBatteryDiffEntry( createBatteryDiffEntry(
/*foregroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3, /*foregroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3,
@@ -447,7 +464,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testValidateUsageTime_backgroundTimeExceedThreshold_returnFalse() { public void validateUsageTime_backgroundTimeExceedThreshold_returnFalse() {
assertThat(BatteryChartPreferenceControllerV2.validateUsageTime( assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
createBatteryDiffEntry( createBatteryDiffEntry(
/*foregroundUsageTimeInMs=*/ 0, /*foregroundUsageTimeInMs=*/ 0,
@@ -456,7 +473,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() { public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
doReturn(1).when(mAppListGroup).getPreferenceCount(); doReturn(1).when(mAppListGroup).getPreferenceCount();
mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry); mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
doReturn("label").when(mBatteryDiffEntry).getAppLabel(); doReturn("label").when(mBatteryDiffEntry).getAppLabel();
@@ -477,7 +494,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnExpand_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.mSystemEntries.add(mBatteryDiffEntry);
@@ -497,56 +514,14 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnSelect_selectSpecificTimeSlot_logMetric() { public void refreshCategoryTitle_setLast24HrIntoBothTitleTextView() {
mBatteryChartPreferenceController.onSelect(1 /*slot index*/);
verify(mMetricsFeatureProvider)
.action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
}
@Test
public void testOnSelect_selectAll_logMetric() {
mBatteryChartPreferenceController.onSelect(
BatteryChartViewModel.SELECTED_INDEX_ALL /*slot index*/);
verify(mMetricsFeatureProvider)
.action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL);
}
@Test
public void testRefreshCategoryTitle_setHourIntoBothTitleTextView() {
mBatteryChartPreferenceController = createController();
setUpBatteryHistoryKeys();
mBatteryChartPreferenceController.mAppListPrefGroup =
spy(new PreferenceCategory(mContext));
mBatteryChartPreferenceController.mExpandDividerPreference =
spy(new ExpandDividerPreference(mContext));
// Simulates select the first slot.
mBatteryChartPreferenceController.mTrapezoidIndex = 0;
mBatteryChartPreferenceController.refreshCategoryTitle();
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
// Verifies the title in the preference group.
verify(mBatteryChartPreferenceController.mAppListPrefGroup)
.setTitle(captor.capture());
assertThat(captor.getValue()).isNotEqualTo("App usage for past 24 hr");
// Verifies the title in the expandable divider.
captor = ArgumentCaptor.forClass(String.class);
verify(mBatteryChartPreferenceController.mExpandDividerPreference)
.setTitle(captor.capture());
assertThat(captor.getValue()).isNotEqualTo("System usage for past 24 hr");
}
@Test
public void testRefreshCategoryTitle_setLast24HrIntoBothTitleTextView() {
mBatteryChartPreferenceController = createController(); mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mAppListPrefGroup = mBatteryChartPreferenceController.mAppListPrefGroup =
spy(new PreferenceCategory(mContext)); spy(new PreferenceCategory(mContext));
mBatteryChartPreferenceController.mExpandDividerPreference = mBatteryChartPreferenceController.mExpandDividerPreference =
spy(new ExpandDividerPreference(mContext)); spy(new ExpandDividerPreference(mContext));
// Simulates select all condition. // Simulates select all condition.
mBatteryChartPreferenceController.mTrapezoidIndex = mBatteryChartPreferenceController.mHourlyChartIndex =
BatteryChartViewModel.SELECTED_INDEX_ALL; BatteryChartViewModel.SELECTED_INDEX_ALL;
mBatteryChartPreferenceController.refreshCategoryTitle(); mBatteryChartPreferenceController.refreshCategoryTitle();
@@ -566,28 +541,27 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testOnSaveInstanceState_restoreSelectedIndexAndExpandState() { public void onSaveInstanceState_restoreSelectedIndexAndExpandState() {
final int expectedIndex = 1; final int expectedIndex = 1;
final boolean isExpanded = true; final boolean isExpanded = true;
final Bundle bundle = new Bundle(); final Bundle bundle = new Bundle();
mBatteryChartPreferenceController.mTrapezoidIndex = expectedIndex; mBatteryChartPreferenceController.mHourlyChartIndex = expectedIndex;
mBatteryChartPreferenceController.mIsExpanded = isExpanded; mBatteryChartPreferenceController.mIsExpanded = isExpanded;
mBatteryChartPreferenceController.onSaveInstanceState(bundle); mBatteryChartPreferenceController.onSaveInstanceState(bundle);
// Replaces the original controller with other values. // Replaces the original controller with other values.
mBatteryChartPreferenceController.mTrapezoidIndex = -1; mBatteryChartPreferenceController.mHourlyChartIndex = -1;
mBatteryChartPreferenceController.mIsExpanded = false; mBatteryChartPreferenceController.mIsExpanded = false;
mBatteryChartPreferenceController.onCreate(bundle); mBatteryChartPreferenceController.onCreate(bundle);
mBatteryChartPreferenceController.setBatteryHistoryMap( mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(25));
createBatteryHistoryMap());
assertThat(mBatteryChartPreferenceController.mTrapezoidIndex) assertThat(mBatteryChartPreferenceController.mHourlyChartIndex)
.isEqualTo(expectedIndex); .isEqualTo(expectedIndex);
assertThat(mBatteryChartPreferenceController.mIsExpanded).isTrue(); assertThat(mBatteryChartPreferenceController.mIsExpanded).isTrue();
} }
@Test @Test
public void testIsValidToShowSummary_returnExpectedResult() { public void isValidToShowSummary_returnExpectedResult() {
assertThat(mBatteryChartPreferenceController assertThat(mBatteryChartPreferenceController
.isValidToShowSummary("com.google.android.apps.scone")) .isValidToShowSummary("com.google.android.apps.scone"))
.isTrue(); .isTrue();
@@ -599,7 +573,7 @@ public final class BatteryChartPreferenceControllerV2Test {
} }
@Test @Test
public void testIsValidToShowEntry_returnExpectedResult() { public void isValidToShowEntry_returnExpectedResult() {
assertThat(mBatteryChartPreferenceController assertThat(mBatteryChartPreferenceController
.isValidToShowEntry("com.google.android.apps.scone")) .isValidToShowEntry("com.google.android.apps.scone"))
.isTrue(); .isTrue();
@@ -615,9 +589,10 @@ public final class BatteryChartPreferenceControllerV2Test {
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS; return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
} }
private static Map<Long, Map<String, BatteryHistEntry>> createBatteryHistoryMap() { private static Map<Long, Map<String, BatteryHistEntry>> createBatteryHistoryMap(
int numOfHours) {
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>(); final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < DESIRED_HISTORY_SIZE; 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));
final BatteryHistEntry entry = new BatteryHistEntry(values); final BatteryHistEntry entry = new BatteryHistEntry(values);
@@ -635,14 +610,6 @@ public final class BatteryChartPreferenceControllerV2Test {
/*consumePower=*/ 0, mBatteryHistEntry); /*consumePower=*/ 0, mBatteryHistEntry);
} }
private void setUpBatteryHistoryKeys() {
mBatteryChartPreferenceController.mBatteryHistoryKeys =
// "2021-04-23 16:53:06 UTC", "1970-01-01 00:00:00 UTC", "2021-04-23 07:00:36 UTC"
new long[]{1619196786769L, 0L, 1619247636826L};
ConvertUtils.utcToLocalTimeHour(
mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
}
private BatteryChartPreferenceControllerV2 createController() { private BatteryChartPreferenceControllerV2 createController() {
final BatteryChartPreferenceControllerV2 controller = final BatteryChartPreferenceControllerV2 controller =
new BatteryChartPreferenceControllerV2( new BatteryChartPreferenceControllerV2(