Show app list in Battery Usage page when there is no battery level data.
https://drive.google.com/file/d/1mZ2Sn3dmjQcCxnhKqDPxfLJDyiTe6mEk/view?usp=sharing
Bug: 246233366
Test: make RunSettingsRoboTests + manually
Change-Id: If536c93652506c8009f5cabf3d0ae373b6825bfc
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 79f0880..69b19d3 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -31,6 +31,7 @@
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
+import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -111,6 +112,7 @@
private View mCategoryTitleView;
private PreferenceScreen mPreferenceScreen;
private FooterPreference mFooterPreference;
+ private TextView mChartSummaryTextView;
private BatteryChartViewModel mDailyViewModel;
private List<BatteryChartViewModel> mHourlyViewModels;
@@ -121,9 +123,9 @@
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final AnimatorListenerAdapter mHourlyChartFadeInAdapter =
- createHourlyChartAnimatorListenerAdapter(/*isToShow=*/ true);
+ createHourlyChartAnimatorListenerAdapter(/*visible=*/ true);
private final AnimatorListenerAdapter mHourlyChartFadeOutAdapter =
- createHourlyChartAnimatorListenerAdapter(/*isToShow=*/ false);
+ createHourlyChartAnimatorListenerAdapter(/*visible=*/ false);
@VisibleForTesting
final DailyChartLabelTextGenerator mDailyChartLabelTextGenerator =
@@ -289,6 +291,8 @@
getTotalHours(batteryLevelData));
if (batteryLevelData == null) {
+ mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
mDailyViewModel = null;
mHourlyViewModels = null;
refreshUi();
@@ -321,6 +325,11 @@
mHandler.post(() -> setBatteryChartViewInner(dailyChartView, hourlyChartView));
animateBatteryChartViewGroup();
}
+ if (mBatteryChartViewGroup != null) {
+ final View grandparentView = (View) mBatteryChartViewGroup.getParent();
+ mChartSummaryTextView = grandparentView != null
+ ? grandparentView.findViewById(R.id.chart_summary) : null;
+ }
}
private void setBatteryChartViewInner(@NonNull final BatteryChartView dailyChartView,
@@ -367,8 +376,45 @@
// Chart views are not initialized.
return false;
}
- if (mDailyViewModel == null || mHourlyViewModels == null) {
- // Fail to get battery level data, show an empty hourly chart view.
+
+ // When mDailyViewModel or mHourlyViewModels is null, there is no battery level data.
+ // This is mainly in 2 cases:
+ // 1) battery data is within 2 hours
+ // 2) no battery data in the latest 7 days (power off >= 7 days)
+ final boolean refreshUiResult = mDailyViewModel == null || mHourlyViewModels == null
+ ? refreshUiWithNoLevelDataCase()
+ : refreshUiWithLevelDataCase();
+
+ if (!refreshUiResult) {
+ return false;
+ }
+
+ mHandler.post(() -> {
+ final long start = System.currentTimeMillis();
+ removeAndCacheAllPrefs();
+ addAllPreferences();
+ refreshCategoryTitle();
+ Log.d(TAG, String.format("refreshUi is finished in %d/ms",
+ (System.currentTimeMillis() - start)));
+ });
+ return true;
+ }
+
+ private boolean refreshUiWithNoLevelDataCase() {
+ setChartSummaryVisible(false);
+ if (mBatteryUsageMap == null) {
+ // There is no battery level data and battery usage data is not ready, wait for data
+ // ready to refresh UI. Show nothing temporarily.
+ mDailyChartView.setVisibility(View.GONE);
+ mHourlyChartView.setVisibility(View.GONE);
+ mDailyChartView.setViewModel(null);
+ mHourlyChartView.setViewModel(null);
+ return false;
+ } else if (mBatteryUsageMap
+ .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
+ .get(BatteryChartViewModel.SELECTED_INDEX_ALL) == null) {
+ // There is no battery level data and battery usage data, show an empty hourly chart
+ // view.
mDailyChartView.setVisibility(View.GONE);
mHourlyChartView.setVisibility(View.VISIBLE);
mHourlyChartView.setViewModel(null);
@@ -376,7 +422,12 @@
addFooterPreferenceIfNeeded(false);
return false;
}
+ return true;
+ }
+ private boolean refreshUiWithLevelDataCase() {
+ setChartSummaryVisible(true);
+ // Gets valid battery level data.
if (isBatteryLevelDataInOneDay()) {
// Only 1 day data, hide the daily chart view.
mDailyChartView.setVisibility(View.GONE);
@@ -389,10 +440,11 @@
if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
// Multiple days are selected, hide the hourly chart view.
- animateBatteryHourlyChartView(/*isToShow=*/ false);
+ animateBatteryHourlyChartView(/*visible=*/ false);
} else {
- animateBatteryHourlyChartView(/*isToShow=*/ true);
- final BatteryChartViewModel hourlyViewModel = mHourlyViewModels.get(mDailyChartIndex);
+ animateBatteryHourlyChartView(/*visible=*/ true);
+ final BatteryChartViewModel hourlyViewModel =
+ mHourlyViewModels.get(mDailyChartIndex);
hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
mHourlyChartView.setViewModel(hourlyViewModel);
}
@@ -401,14 +453,6 @@
// Battery usage data is not ready, wait for data ready to refresh UI.
return false;
}
- mHandler.post(() -> {
- final long start = System.currentTimeMillis();
- removeAndCacheAllPrefs();
- addAllPreferences();
- refreshCategoryTitle();
- Log.d(TAG, String.format("refreshUi is finished in %d/ms",
- (System.currentTimeMillis() - start)));
- });
return true;
}
@@ -427,7 +471,7 @@
if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
}
- // Adds the expabable divider if we have system entries data.
+ // Adds the expandable divider if we have system entries data.
if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
if (mExpandDividerPreference == null) {
mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
@@ -645,12 +689,12 @@
}
}
- private void animateBatteryHourlyChartView(final boolean isToShow) {
+ private void animateBatteryHourlyChartView(final boolean visible) {
if (mHourlyChartView == null) {
return;
}
- if (isToShow) {
+ if (visible) {
mHourlyChartView.setAlpha(0f);
mHourlyChartView.setVisibility(View.VISIBLE);
mHourlyChartView.animate()
@@ -667,9 +711,15 @@
}
}
+ private void setChartSummaryVisible(final boolean visible) {
+ if (mChartSummaryTextView != null) {
+ mChartSummaryTextView.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+ }
+
private AnimatorListenerAdapter createHourlyChartAnimatorListenerAdapter(
- final boolean isToShow) {
- final int visibility = isToShow ? View.VISIBLE : View.GONE;
+ final boolean visible) {
+ final int visibility = visible ? View.VISIBLE : View.GONE;
return new AnimatorListenerAdapter() {
@Override
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index 68f0dc7..1303573 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -55,11 +55,6 @@
// Maximum total time value for each slot cumulative data at most 2 hours.
private static final float TOTAL_TIME_THRESHOLD = DateUtils.HOUR_IN_MILLIS * 2;
- // Keys for metric metadata.
- static final int METRIC_KEY_PACKAGE = 1;
- static final int METRIC_KEY_BATTERY_LEVEL = 2;
- static final int METRIC_KEY_BATTERY_USAGE = 3;
-
@VisibleForTesting
static double PERCENTAGE_OF_TOTAL_THRESHOLD = 1f;
@@ -87,7 +82,7 @@
}
/** Converts to content values */
- public static ContentValues convert(
+ public static ContentValues convertToContentValues(
BatteryEntry entry,
BatteryUsageStats batteryUsageStats,
int batteryLevel,
@@ -130,6 +125,21 @@
return values;
}
+ /** Converts to {@link BatteryHistEntry} */
+ public static BatteryHistEntry convertToBatteryHistEntry(
+ BatteryEntry entry,
+ BatteryUsageStats batteryUsageStats) {
+ return new BatteryHistEntry(
+ convertToContentValues(
+ entry,
+ batteryUsageStats,
+ /*batteryLevel=*/ 0,
+ /*batteryStatus=*/ 0,
+ /*batteryHealth=*/ 0,
+ /*bootTimestamp=*/ 0,
+ /*timestamp=*/ 0));
+ }
+
/** Converts UTC timestamp to human readable local time string. */
public static String utcToLocalTime(Context context, long timestamp) {
final Locale locale = getLocale(context);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index f493ece..9c2c4d5 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -22,6 +22,9 @@
import android.content.ContentValues;
import android.content.Context;
import android.os.AsyncTask;
+import android.os.BatteryStatsManager;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -50,6 +53,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* A utility class to process data loaded from database and make the data easy to use for battery
@@ -97,7 +101,9 @@
@Nullable final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
final UsageMapAsyncResponse asyncResponseDelegate) {
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
- Log.d(TAG, "getBatteryLevelData() returns null");
+ Log.d(TAG, "batteryHistoryMap is null in getBatteryLevelData()");
+ loadBatteryUsageDataFromBatteryStatsService(
+ context, handler, asyncResponseDelegate);
return null;
}
handler = handler != null ? handler : new Handler(Looper.getMainLooper());
@@ -107,16 +113,20 @@
// Wrap and processed history map into easy-to-use format for UI rendering.
final BatteryLevelData batteryLevelData =
getLevelDataThroughProcessedHistoryMap(context, processedBatteryHistoryMap);
+ if (batteryLevelData == null) {
+ loadBatteryUsageDataFromBatteryStatsService(
+ context, handler, asyncResponseDelegate);
+ Log.d(TAG, "getBatteryLevelData() returns null");
+ return null;
+ }
// Start the async task to compute diff usage data and load labels and icons.
- if (batteryLevelData != null) {
- new ComputeUsageMapAndLoadItemsTask(
- context,
- handler,
- asyncResponseDelegate,
- batteryLevelData.getHourlyBatteryLevelsPerDay(),
- processedBatteryHistoryMap).execute();
- }
+ new ComputeUsageMapAndLoadItemsTask(
+ context,
+ handler,
+ asyncResponseDelegate,
+ batteryLevelData.getHourlyBatteryLevelsPerDay(),
+ processedBatteryHistoryMap).execute();
return batteryLevelData;
}
@@ -365,19 +375,165 @@
return null;
}
- final MetricsFeatureProvider metricsFeatureProvider =
- FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- metricsFeatureProvider.action(
- context,
- SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
- countOfAppAfterPurge);
- metricsFeatureProvider.action(
- context,
- SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
- countOfAppBeforePurge - countOfAppAfterPurge);
+ logAppCountMetrics(context, countOfAppBeforePurge, countOfAppAfterPurge);
return resultMap;
}
+ @VisibleForTesting
+ @Nullable
+ static BatteryDiffData generateBatteryDiffData(
+ final Context context,
+ @Nullable final List<BatteryEntry> batteryEntryList,
+ final BatteryUsageStats batteryUsageStats) {
+ final List<BatteryHistEntry> batteryHistEntryList =
+ convertToBatteryHistEntry(batteryEntryList, batteryUsageStats);
+ if (batteryHistEntryList == null || batteryHistEntryList.isEmpty()) {
+ Log.w(TAG, "batteryHistEntryList is null or empty in generateBatteryDiffData()");
+ return null;
+ }
+ final int currentUserId = context.getUserId();
+ final UserHandle userHandle =
+ Utils.getManagedProfile(context.getSystemService(UserManager.class));
+ final int workProfileUserId =
+ userHandle != null ? userHandle.getIdentifier() : Integer.MIN_VALUE;
+ final List<BatteryDiffEntry> appEntries = new ArrayList<>();
+ final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
+ double totalConsumePower = 0f;
+ double consumePowerFromOtherUsers = 0f;
+
+ for (BatteryHistEntry entry : batteryHistEntryList) {
+ final boolean isFromOtherUsers = isConsumedFromOtherUsers(
+ currentUserId, workProfileUserId, entry);
+ totalConsumePower += entry.mConsumePower;
+ if (isFromOtherUsers) {
+ consumePowerFromOtherUsers += entry.mConsumePower;
+ } else {
+ final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
+ context,
+ entry.mForegroundUsageTimeInMs,
+ entry.mBackgroundUsageTimeInMs,
+ entry.mConsumePower,
+ entry);
+ if (currentBatteryDiffEntry.isSystemEntry()) {
+ systemEntries.add(currentBatteryDiffEntry);
+ } else {
+ appEntries.add(currentBatteryDiffEntry);
+ }
+ }
+ }
+ if (consumePowerFromOtherUsers != 0) {
+ systemEntries.add(createOtherUsersEntry(context, consumePowerFromOtherUsers));
+ }
+
+ // If there is no data, return null instead of empty item.
+ if (appEntries.isEmpty() && systemEntries.isEmpty()) {
+ return null;
+ }
+
+ return new BatteryDiffData(appEntries, systemEntries, totalConsumePower);
+ }
+
+ /**
+ * Starts the async task to load battery diff usage data and load app labels + icons.
+ */
+ private static void loadBatteryUsageDataFromBatteryStatsService(
+ Context context,
+ @Nullable Handler handler,
+ final UsageMapAsyncResponse asyncResponseDelegate) {
+ new LoadUsageMapFromBatteryStatsServiceTask(
+ context,
+ handler,
+ asyncResponseDelegate).execute();
+ }
+
+ /**
+ * @return Returns the overall battery usage data from battery stats service directly.
+ *
+ * The returned value should be always a 2d map and composed by only 1 part:
+ * - [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL]
+ */
+ @Nullable
+ private static Map<Integer, Map<Integer, BatteryDiffData>> getBatteryUsageMapFromStatsService(
+ final Context context) {
+ final Map<Integer, Map<Integer, BatteryDiffData>> resultMap = new HashMap<>();
+ final Map<Integer, BatteryDiffData> allUsageMap = new HashMap<>();
+ // Always construct the map whether the value is null or not.
+ allUsageMap.put(SELECTED_INDEX_ALL,
+ getBatteryDiffDataFromBatteryStatsService(context));
+ resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
+
+ // Compute the apps number before purge. Must put before purgeLowPercentageAndFakeData.
+ final int countOfAppBeforePurge = getCountOfApps(resultMap);
+ purgeLowPercentageAndFakeData(context, resultMap);
+ // Compute the apps number after purge. Must put after purgeLowPercentageAndFakeData.
+ final int countOfAppAfterPurge = getCountOfApps(resultMap);
+
+ logAppCountMetrics(context, countOfAppBeforePurge, countOfAppAfterPurge);
+ return resultMap;
+ }
+
+ @Nullable
+ private static BatteryDiffData getBatteryDiffDataFromBatteryStatsService(
+ final Context context) {
+ BatteryDiffData batteryDiffData = null;
+ try {
+ final BatteryUsageStatsQuery batteryUsageStatsQuery =
+ new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build();
+ final BatteryUsageStats batteryUsageStats =
+ context.getSystemService(BatteryStatsManager.class)
+ .getBatteryUsageStats(batteryUsageStatsQuery);
+
+ if (batteryUsageStats == null) {
+ Log.w(TAG, "batteryUsageStats is null content");
+ return null;
+ }
+
+ final List<BatteryEntry> batteryEntryList =
+ generateBatteryEntryListFromBatteryUsageStats(context, batteryUsageStats);
+ batteryDiffData = generateBatteryDiffData(context, batteryEntryList, batteryUsageStats);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "load batteryUsageStats:" + e);
+ }
+
+ return batteryDiffData;
+ }
+
+ @Nullable
+ private static List<BatteryEntry> generateBatteryEntryListFromBatteryUsageStats(
+ final Context context, final BatteryUsageStats batteryUsageStats) {
+ // Loads the battery consuming data.
+ final BatteryAppListPreferenceController controller =
+ new BatteryAppListPreferenceController(
+ context,
+ /*preferenceKey=*/ null,
+ /*lifecycle=*/ null,
+ /*activity*=*/ null,
+ /*fragment=*/ null);
+ return controller.getBatteryEntryList(batteryUsageStats, /*showAllApps=*/ true);
+ }
+
+ @Nullable
+ private static List<BatteryHistEntry> convertToBatteryHistEntry(
+ @Nullable final List<BatteryEntry> batteryEntryList,
+ final BatteryUsageStats batteryUsageStats) {
+ if (batteryEntryList == null || batteryEntryList.isEmpty()) {
+ Log.w(TAG, "batteryEntryList is null or empty in convertToBatteryHistEntry()");
+ return null;
+ }
+ return batteryEntryList.stream()
+ .filter(entry -> {
+ final long foregroundMs = entry.getTimeInForegroundMs();
+ final long backgroundMs = entry.getTimeInBackgroundMs();
+ return entry.getConsumedPower() > 0
+ || (entry.getConsumedPower() == 0
+ && (foregroundMs != 0 || backgroundMs != 0));
+ })
+ .map(entry -> ConvertUtils.convertToBatteryHistEntry(
+ entry,
+ batteryUsageStats))
+ .collect(Collectors.toList());
+ }
+
/**
* Interpolates history map based on expected timestamp slots and processes the corner case when
* the expected start timestamp is earlier than what we have.
@@ -940,6 +1096,22 @@
return true;
}
+ private static void loadLabelAndIcon(
+ @Nullable final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
+ if (batteryUsageMap == null) {
+ return;
+ }
+ // Pre-loads each BatteryDiffEntry relative icon and label for all slots.
+ final BatteryDiffData batteryUsageMapForAll =
+ batteryUsageMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
+ if (batteryUsageMapForAll != null) {
+ batteryUsageMapForAll.getAppDiffEntryList().forEach(
+ entry -> entry.loadLabelAndIcon());
+ batteryUsageMapForAll.getSystemDiffEntryList().forEach(
+ entry -> entry.loadLabelAndIcon());
+ }
+ }
+
private static long getTimestampWithDayDiff(final long timestamp, final int dayDiff) {
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
@@ -1006,6 +1178,21 @@
return batteryDiffEntry;
}
+ private static void logAppCountMetrics(
+ Context context, final int countOfAppBeforePurge, final int countOfAppAfterPurge) {
+ context = context.getApplicationContext();
+ final MetricsFeatureProvider metricsFeatureProvider =
+ FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ metricsFeatureProvider.action(
+ context,
+ SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+ countOfAppAfterPurge);
+ metricsFeatureProvider.action(
+ context,
+ SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+ countOfAppBeforePurge - countOfAppAfterPurge);
+ }
+
private static void log(Context context, final String content, final long timestamp,
final BatteryHistEntry entry) {
if (DEBUG) {
@@ -1015,12 +1202,12 @@
}
// Compute diff map and loads all items (icon and label) in the background.
- private static final class ComputeUsageMapAndLoadItemsTask
+ private static class ComputeUsageMapAndLoadItemsTask
extends AsyncTask<Void, Void, Map<Integer, Map<Integer, BatteryDiffData>>> {
- private Context mApplicationContext;
- private Handler mHandler;
- private UsageMapAsyncResponse mAsyncResponseDelegate;
+ Context mApplicationContext;
+ final Handler mHandler;
+ final UsageMapAsyncResponse mAsyncResponseDelegate;
private List<BatteryLevelData.PeriodBatteryLevelData> mHourlyBatteryLevelsPerDay;
private Map<Long, Map<String, BatteryHistEntry>> mBatteryHistoryMap;
@@ -1051,17 +1238,7 @@
final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap =
getBatteryUsageMap(
mApplicationContext, mHourlyBatteryLevelsPerDay, mBatteryHistoryMap);
- if (batteryUsageMap != null) {
- // Pre-loads each BatteryDiffEntry relative icon and label for all slots.
- final BatteryDiffData batteryUsageMapForAll =
- batteryUsageMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
- if (batteryUsageMapForAll != null) {
- batteryUsageMapForAll.getAppDiffEntryList().forEach(
- entry -> entry.loadLabelAndIcon());
- batteryUsageMapForAll.getSystemDiffEntryList().forEach(
- entry -> entry.loadLabelAndIcon());
- }
- }
+ loadLabelAndIcon(batteryUsageMap);
Log.d(TAG, String.format("execute ComputeUsageMapAndLoadItemsTask in %d/ms",
(System.currentTimeMillis() - startTime)));
return batteryUsageMap;
@@ -1081,4 +1258,35 @@
}
}
}
+
+ // Loads battery usage data from battery stats service directly and loads all items (icon and
+ // label) in the background.
+ private static final class LoadUsageMapFromBatteryStatsServiceTask
+ extends ComputeUsageMapAndLoadItemsTask {
+
+ private LoadUsageMapFromBatteryStatsServiceTask(
+ Context context,
+ Handler handler,
+ final UsageMapAsyncResponse asyncResponseDelegate) {
+ super(context, handler, asyncResponseDelegate, /*hourlyBatteryLevelsPerDay=*/ null,
+ /*batteryHistoryMap=*/ null);
+ }
+
+ @Override
+ protected Map<Integer, Map<Integer, BatteryDiffData>> doInBackground(Void... voids) {
+ if (mApplicationContext == null
+ || mHandler == null
+ || mAsyncResponseDelegate == null) {
+ Log.e(TAG, "invalid input for ComputeUsageMapAndLoadItemsTask()");
+ return null;
+ }
+ final long startTime = System.currentTimeMillis();
+ final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap =
+ getBatteryUsageMapFromStatsService(mApplicationContext);
+ loadLabelAndIcon(batteryUsageMap);
+ Log.d(TAG, String.format("execute LoadUsageMapFromBatteryStatsServiceTask in %d/ms",
+ (System.currentTimeMillis() - startTime)));
+ return batteryUsageMap;
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
index 553c089..5dfdd39 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
@@ -64,7 +64,7 @@
when(mMockBatteryEntry.getConsumerType())
.thenReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
final ContentValues values =
- ConvertUtils.convert(
+ ConvertUtils.convertToContentValues(
mMockBatteryEntry,
mBatteryUsageStats,
/*batteryLevel=*/ 12,
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index c9bac03..2ae73b1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -71,7 +71,7 @@
}
@Test
- public void convert_returnsExpectedContentValues() {
+ public void convertToContentValues_returnsExpectedContentValues() {
final int expectedType = 3;
when(mMockBatteryEntry.getUid()).thenReturn(1001);
when(mMockBatteryEntry.getLabel()).thenReturn("Settings");
@@ -88,7 +88,7 @@
.thenReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
final ContentValues values =
- ConvertUtils.convert(
+ ConvertUtils.convertToContentValues(
mMockBatteryEntry,
mBatteryUsageStats,
/*batteryLevel=*/ 12,
@@ -128,9 +128,9 @@
}
@Test
- public void convert_nullBatteryEntry_returnsExpectedContentValues() {
+ public void convertToContentValues_nullBatteryEntry_returnsExpectedContentValues() {
final ContentValues values =
- ConvertUtils.convert(
+ ConvertUtils.convertToContentValues(
/*entry=*/ null,
/*batteryUsageStats=*/ null,
/*batteryLevel=*/ 12,
@@ -155,6 +155,76 @@
}
@Test
+ public void convertToBatteryHistEntry_returnsExpectedResult() {
+ final int expectedType = 3;
+ when(mMockBatteryEntry.getUid()).thenReturn(1001);
+ when(mMockBatteryEntry.getLabel()).thenReturn("Settings");
+ when(mMockBatteryEntry.getDefaultPackageName())
+ .thenReturn("com.android.settings.battery");
+ when(mMockBatteryEntry.isHidden()).thenReturn(true);
+ when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
+ when(mMockBatteryEntry.getConsumedPower()).thenReturn(1.1);
+ mMockBatteryEntry.mPercent = 0.3;
+ when(mMockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
+ when(mMockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
+ when(mMockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
+ when(mMockBatteryEntry.getConsumerType())
+ .thenReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+
+ final BatteryHistEntry batteryHistEntry =
+ ConvertUtils.convertToBatteryHistEntry(
+ mMockBatteryEntry,
+ mBatteryUsageStats);
+
+ assertThat(batteryHistEntry.mUid).isEqualTo(1001L);
+ assertThat(batteryHistEntry.mUserId)
+ .isEqualTo(UserHandle.getUserId(1001));
+ assertThat(batteryHistEntry.mAppLabel)
+ .isEqualTo("Settings");
+ assertThat(batteryHistEntry.mPackageName)
+ .isEqualTo("com.android.settings.battery");
+ assertThat(batteryHistEntry.mIsHidden).isTrue();
+ assertThat(batteryHistEntry.mBootTimestamp)
+ .isEqualTo(0L);
+ assertThat(batteryHistEntry.mTimestamp).isEqualTo(0L);
+ assertThat(batteryHistEntry.mZoneId)
+ .isEqualTo(TimeZone.getDefault().getID());
+ assertThat(batteryHistEntry.mTotalPower).isEqualTo(5.1);
+ assertThat(batteryHistEntry.mConsumePower).isEqualTo(1.1);
+ assertThat(batteryHistEntry.mPercentOfTotal).isEqualTo(0.3);
+ assertThat(batteryHistEntry.mForegroundUsageTimeInMs)
+ .isEqualTo(1234L);
+ assertThat(batteryHistEntry.mBackgroundUsageTimeInMs)
+ .isEqualTo(5689L);
+ assertThat(batteryHistEntry.mDrainType).isEqualTo(expectedType);
+ assertThat(batteryHistEntry.mConsumerType)
+ .isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+ assertThat(batteryHistEntry.mBatteryLevel).isEqualTo(0);
+ assertThat(batteryHistEntry.mBatteryStatus).isEqualTo(0);
+ assertThat(batteryHistEntry.mBatteryHealth).isEqualTo(0);
+ }
+
+ @Test
+ public void convertToBatteryHistEntry_nullBatteryEntry_returnsExpectedResult() {
+ final BatteryHistEntry batteryHistEntry =
+ ConvertUtils.convertToBatteryHistEntry(
+ /*entry=*/ null,
+ /*batteryUsageStats=*/ null);
+
+ assertThat(batteryHistEntry.mBootTimestamp)
+ .isEqualTo(0L);
+ assertThat(batteryHistEntry.mTimestamp)
+ .isEqualTo(0);
+ assertThat(batteryHistEntry.mZoneId)
+ .isEqualTo(TimeZone.getDefault().getID());
+ assertThat(batteryHistEntry.mBatteryLevel).isEqualTo(0);
+ assertThat(batteryHistEntry.mBatteryStatus).isEqualTo(0);
+ assertThat(batteryHistEntry.mBatteryHealth).isEqualTo(0);
+ assertThat(batteryHistEntry.mPackageName)
+ .isEqualTo(ConvertUtils.FAKE_PACKAGE_NAME);
+ }
+
+ @Test
public void getIndexedUsageMap_nullOrEmptyHistoryMap_returnEmptyCollection() {
final int timeSlotSize = 2;
final long[] batteryHistoryKeys = new long[]{101L, 102L, 103L, 104L, 105L};
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index 84f9310..c483204 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -26,6 +27,8 @@
import android.app.settings.SettingsEnums;
import android.content.ContentValues;
import android.content.Context;
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
import android.text.format.DateUtils;
import com.android.settings.fuelgauge.BatteryUtils;
@@ -36,6 +39,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@@ -59,6 +63,13 @@
private MetricsFeatureProvider mMetricsFeatureProvider;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+ @Mock private BatteryUsageStats mBatteryUsageStats;
+ @Mock private BatteryEntry mMockBatteryEntry1;
+ @Mock private BatteryEntry mMockBatteryEntry2;
+ @Mock private BatteryEntry mMockBatteryEntry3;
+ @Mock private BatteryEntry mMockBatteryEntry4;
+
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -883,6 +894,60 @@
.action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
}
+ @Test
+ public void generateBatteryDiffData_emptyBatteryEntryList_returnNull() {
+ assertThat(DataProcessor.generateBatteryDiffData(
+ mContext, null, mBatteryUsageStats)).isNull();
+ }
+
+ @Test
+ public void generateBatteryDiffData_returnsExpectedResult() {
+ final List<BatteryEntry> batteryEntryList = new ArrayList<>();
+ batteryEntryList.add(mMockBatteryEntry1);
+ batteryEntryList.add(mMockBatteryEntry2);
+ batteryEntryList.add(mMockBatteryEntry3);
+ batteryEntryList.add(mMockBatteryEntry4);
+ doReturn(0.0).when(mMockBatteryEntry1).getConsumedPower();
+ doReturn(30L).when(mMockBatteryEntry1).getTimeInForegroundMs();
+ doReturn(40L).when(mMockBatteryEntry1).getTimeInBackgroundMs();
+ doReturn(1).when(mMockBatteryEntry1).getUid();
+ doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry1).getConsumerType();
+ doReturn(0.5).when(mMockBatteryEntry2).getConsumedPower();
+ doReturn(20L).when(mMockBatteryEntry2).getTimeInForegroundMs();
+ doReturn(20L).when(mMockBatteryEntry2).getTimeInBackgroundMs();
+ doReturn(2).when(mMockBatteryEntry2).getUid();
+ doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry2).getConsumerType();
+ doReturn(0.0).when(mMockBatteryEntry3).getConsumedPower();
+ doReturn(0L).when(mMockBatteryEntry3).getTimeInForegroundMs();
+ doReturn(0L).when(mMockBatteryEntry3).getTimeInBackgroundMs();
+ doReturn(3).when(mMockBatteryEntry3).getUid();
+ doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry3).getConsumerType();
+ doReturn(1.5).when(mMockBatteryEntry4).getConsumedPower();
+ doReturn(10L).when(mMockBatteryEntry4).getTimeInForegroundMs();
+ doReturn(10L).when(mMockBatteryEntry4).getTimeInBackgroundMs();
+ doReturn(4).when(mMockBatteryEntry4).getUid();
+ doReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY)
+ .when(mMockBatteryEntry4).getConsumerType();
+ doReturn(BatteryConsumer.POWER_COMPONENT_CAMERA)
+ .when(mMockBatteryEntry4).getPowerComponentId();
+
+ final BatteryDiffData batteryDiffData = DataProcessor.generateBatteryDiffData(
+ mContext, batteryEntryList, mBatteryUsageStats);
+
+ assertBatteryDiffEntry(
+ batteryDiffData.getAppDiffEntryList().get(0), 0, /*uid=*/ 2L,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 25.0,
+ /*foregroundUsageTimeInMs=*/ 20, /*backgroundUsageTimeInMs=*/ 20);
+ assertBatteryDiffEntry(
+ batteryDiffData.getAppDiffEntryList().get(1), 0, /*uid=*/ 1L,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 0.0,
+ /*foregroundUsageTimeInMs=*/ 30, /*backgroundUsageTimeInMs=*/ 40);
+ assertBatteryDiffEntry(
+ batteryDiffData.getSystemDiffEntryList().get(0), 0, /*uid=*/ 4L,
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 75.0,
+ /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10);
+ }
+
private static Map<Long, Map<String, BatteryHistEntry>> createHistoryMap(
final long[] timestamps, final int[] levels) {
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();