Add the async task to compute diff usage data and load labels and icons.
Bug: 236101687 Test: make RunSettingsRoboTests Change-Id: Ie24ea89fa6cfd351c73e64de40e2c9315867af9a
This commit is contained in:
@@ -266,8 +266,9 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
|
||||
Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
|
||||
: ("size=" + batteryHistoryMap.size())));
|
||||
// TODO: implement the callback function.
|
||||
final BatteryLevelData batteryLevelData =
|
||||
DataProcessor.getBatteryLevelData(mContext, batteryHistoryMap);
|
||||
DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap, null);
|
||||
Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
|
||||
if (batteryLevelData == null) {
|
||||
mDailyViewModel = null;
|
||||
|
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/** Wraps the battery usage diff data for each entry used for battery usage app list. */
|
||||
@@ -24,10 +26,24 @@ public class BatteryDiffData {
|
||||
private final List<BatteryDiffEntry> mAppEntries;
|
||||
private final List<BatteryDiffEntry> mSystemEntries;
|
||||
|
||||
/** Constructor for the diff entries which already have totalConsumePower value. */
|
||||
public BatteryDiffData(
|
||||
List<BatteryDiffEntry> appDiffEntries, List<BatteryDiffEntry> systemDiffEntries) {
|
||||
mAppEntries = appDiffEntries == null ? new ArrayList<>() : appDiffEntries;
|
||||
mSystemEntries = systemDiffEntries == null ? new ArrayList<>() : systemDiffEntries;
|
||||
@NonNull List<BatteryDiffEntry> appDiffEntries,
|
||||
@NonNull List<BatteryDiffEntry> systemDiffEntries) {
|
||||
mAppEntries = appDiffEntries;
|
||||
mSystemEntries = systemDiffEntries;
|
||||
sortEntries();
|
||||
}
|
||||
|
||||
/** Constructor for the diff entries which have not set totalConsumePower value. */
|
||||
public BatteryDiffData(
|
||||
@NonNull List<BatteryDiffEntry> appDiffEntries,
|
||||
@NonNull List<BatteryDiffEntry> systemDiffEntries,
|
||||
final double totalConsumePower) {
|
||||
mAppEntries = appDiffEntries;
|
||||
mSystemEntries = systemDiffEntries;
|
||||
setTotalConsumePowerForAllEntries(totalConsumePower);
|
||||
sortEntries();
|
||||
}
|
||||
|
||||
public List<BatteryDiffEntry> getAppDiffEntryList() {
|
||||
@@ -38,9 +54,15 @@ public class BatteryDiffData {
|
||||
return mSystemEntries;
|
||||
}
|
||||
|
||||
/** Sets total consume power for each entry. */
|
||||
public void setTotalConsumePowerForAllEntries(double totalConsumePower) {
|
||||
// Sets total consume power for each entry.
|
||||
private void setTotalConsumePowerForAllEntries(final double totalConsumePower) {
|
||||
mAppEntries.forEach(diffEntry -> diffEntry.setTotalConsumePower(totalConsumePower));
|
||||
mSystemEntries.forEach(diffEntry -> diffEntry.setTotalConsumePower(totalConsumePower));
|
||||
}
|
||||
|
||||
// Sorts entries based on consumed percentage.
|
||||
private void sortEntries() {
|
||||
Collections.sort(mAppEntries, BatteryDiffEntry.COMPARATOR);
|
||||
Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
|
||||
}
|
||||
}
|
||||
|
@@ -18,21 +18,36 @@ package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLocalTime;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.fuelgauge.BatteryStatus;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A utility class to process data loaded from database and make the data easy to use for battery
|
||||
@@ -43,10 +58,27 @@ public final class DataProcessor {
|
||||
private static final String TAG = "DataProcessor";
|
||||
private static final int MIN_DAILY_DATA_SIZE = 2;
|
||||
private static final int MIN_TIMESTAMP_DATA_SIZE = 2;
|
||||
// Maximum total time value for each hourly slot cumulative data at most 2 hours.
|
||||
private static final float TOTAL_HOURLY_TIME_THRESHOLD = DateUtils.HOUR_IN_MILLIS * 2;
|
||||
private static final Map<String, BatteryHistEntry> EMPTY_BATTERY_MAP = new HashMap<>();
|
||||
private static final BatteryHistEntry EMPTY_BATTERY_HIST_ENTRY =
|
||||
new BatteryHistEntry(new ContentValues());
|
||||
|
||||
@VisibleForTesting
|
||||
static final double PERCENTAGE_OF_TOTAL_THRESHOLD = 1f;
|
||||
@VisibleForTesting
|
||||
static final int SELECTED_INDEX_ALL = BatteryChartViewModel.SELECTED_INDEX_ALL;
|
||||
|
||||
/** A fake package name to represent no BatteryEntry data. */
|
||||
public static final String FAKE_PACKAGE_NAME = "fake_package";
|
||||
|
||||
/** A callback listener when battery usage loading async task is executed. */
|
||||
public interface UsageMapAsyncResponse {
|
||||
/** The callback function when batteryUsageMap is loaded. */
|
||||
void onBatteryUsageMapLoaded(
|
||||
Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap);
|
||||
}
|
||||
|
||||
private DataProcessor() {
|
||||
}
|
||||
|
||||
@@ -58,11 +90,14 @@ public final class DataProcessor {
|
||||
@Nullable
|
||||
public static BatteryLevelData getBatteryLevelData(
|
||||
Context context,
|
||||
@Nullable final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
|
||||
@Nullable Handler handler,
|
||||
@Nullable final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
|
||||
final UsageMapAsyncResponse asyncResponseDelegate) {
|
||||
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
|
||||
Log.d(TAG, "getBatteryLevelData() returns null");
|
||||
return null;
|
||||
}
|
||||
handler = handler != null ? handler : new Handler(Looper.getMainLooper());
|
||||
// Process raw history map data into hourly timestamps.
|
||||
final Map<Long, Map<String, BatteryHistEntry>> processedBatteryHistoryMap =
|
||||
getHistoryMapWithExpectedTimestamps(context, batteryHistoryMap);
|
||||
@@ -70,11 +105,33 @@ public final class DataProcessor {
|
||||
final BatteryLevelData batteryLevelData =
|
||||
getLevelDataThroughProcessedHistoryMap(context, processedBatteryHistoryMap);
|
||||
|
||||
//TODO: Add the async task to compute diff usage data and load labels and icons.
|
||||
// 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();
|
||||
}
|
||||
|
||||
return batteryLevelData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns whether the target is in the CharSequence array.
|
||||
*/
|
||||
public static boolean contains(String target, CharSequence[] packageNames) {
|
||||
if (target != null && packageNames != null) {
|
||||
for (CharSequence packageName : packageNames) {
|
||||
if (TextUtils.equals(target, packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the processed history map which has interpolated to every hour data.
|
||||
* The start and end timestamp must be the even hours.
|
||||
@@ -187,7 +244,7 @@ public final class DataProcessor {
|
||||
@VisibleForTesting
|
||||
static boolean isFromFullCharge(@Nullable final Map<String, BatteryHistEntry> entryList) {
|
||||
if (entryList == null) {
|
||||
Log.d(TAG, "entryList is nul in isFromFullCharge()");
|
||||
Log.d(TAG, "entryList is null in isFromFullCharge()");
|
||||
return false;
|
||||
}
|
||||
final List<String> entryKeys = new ArrayList<>(entryList.keySet());
|
||||
@@ -205,14 +262,14 @@ public final class DataProcessor {
|
||||
static long[] findNearestTimestamp(final List<Long> timestamps, final long target) {
|
||||
final long[] results = new long[] {Long.MIN_VALUE, Long.MAX_VALUE};
|
||||
// Searches the nearest lower and upper timestamp value.
|
||||
for (long timestamp : timestamps) {
|
||||
timestamps.forEach(timestamp -> {
|
||||
if (timestamp <= target && timestamp > results[0]) {
|
||||
results[0] = timestamp;
|
||||
}
|
||||
if (timestamp >= target && timestamp < results[1]) {
|
||||
results[1] = timestamp;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Uses zero value to represent invalid searching result.
|
||||
results[0] = results[0] == Long.MIN_VALUE ? 0 : results[0];
|
||||
results[1] = results[1] == Long.MAX_VALUE ? 0 : results[1];
|
||||
@@ -234,6 +291,40 @@ public final class DataProcessor {
|
||||
return nextDayCalendar.getTimeInMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the indexed battery usage data for each corresponding time slot.
|
||||
*
|
||||
* There could be 2 cases of the returned value:
|
||||
* 1) null: empty or invalid data.
|
||||
* 2) non-null: must be a 2d map and composed by 3 parts:
|
||||
* 1 - [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL]
|
||||
* 2 - [0][SELECTED_INDEX_ALL] ~ [maxDailyIndex][SELECTED_INDEX_ALL]
|
||||
* 3 - [0][0] ~ [maxDailyIndex][maxHourlyIndex]
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@Nullable
|
||||
static Map<Integer, Map<Integer, BatteryDiffData>> getBatteryUsageMap(
|
||||
final Context context,
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
|
||||
if (batteryHistoryMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap = new HashMap<>();
|
||||
// Insert diff data from [0][0] to [maxDailyIndex][maxHourlyIndex].
|
||||
insertHourlyUsageDiffData(
|
||||
context, hourlyBatteryLevelsPerDay, batteryHistoryMap, resultMap);
|
||||
// Insert diff data from [0][SELECTED_INDEX_ALL] to [maxDailyIndex][SELECTED_INDEX_ALL].
|
||||
insertDailyUsageDiffData(hourlyBatteryLevelsPerDay, resultMap);
|
||||
// Insert diff data [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL].
|
||||
insertAllUsageDiffData(resultMap);
|
||||
purgeLowPercentageAndFakeData(context, resultMap);
|
||||
if (!isUsageMapValid(resultMap, hourlyBatteryLevelsPerDay)) {
|
||||
return null;
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates history map based on expected timestamp slots and processes the corner case when
|
||||
* the expected start timestamp is earlier than what we have.
|
||||
@@ -458,11 +549,454 @@ public final class DataProcessor {
|
||||
return Math.round(batteryLevelCounter / entryMap.size());
|
||||
}
|
||||
|
||||
private static void log(Context context, String content, long timestamp,
|
||||
BatteryHistEntry entry) {
|
||||
private static void insertHourlyUsageDiffData(
|
||||
Context context,
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
|
||||
final int currentUserId = context.getUserId();
|
||||
final UserHandle userHandle =
|
||||
Utils.getManagedProfile(context.getSystemService(UserManager.class));
|
||||
final int workProfileUserId =
|
||||
userHandle != null ? userHandle.getIdentifier() : Integer.MIN_VALUE;
|
||||
// Each time slot usage diff data =
|
||||
// Math.abs(timestamp[i+2] data - timestamp[i+1] data) +
|
||||
// Math.abs(timestamp[i+1] data - timestamp[i] data);
|
||||
// since we want to aggregate every two hours data into a single time slot.
|
||||
for (int dailyIndex = 0; dailyIndex < hourlyBatteryLevelsPerDay.size(); dailyIndex++) {
|
||||
final Map<Integer, BatteryDiffData> dailyDiffMap = new HashMap<>();
|
||||
resultMap.put(dailyIndex, dailyDiffMap);
|
||||
if (hourlyBatteryLevelsPerDay.get(dailyIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
final List<Long> timestamps = hourlyBatteryLevelsPerDay.get(dailyIndex).getTimestamps();
|
||||
for (int hourlyIndex = 0; hourlyIndex < timestamps.size() - 1; hourlyIndex++) {
|
||||
final BatteryDiffData hourlyBatteryDiffData =
|
||||
insertHourlyUsageDiffDataPerSlot(
|
||||
context,
|
||||
currentUserId,
|
||||
workProfileUserId,
|
||||
hourlyIndex,
|
||||
timestamps,
|
||||
batteryHistoryMap);
|
||||
dailyDiffMap.put(hourlyIndex, hourlyBatteryDiffData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void insertDailyUsageDiffData(
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
|
||||
for (int index = 0; index < hourlyBatteryLevelsPerDay.size(); index++) {
|
||||
Map<Integer, BatteryDiffData> dailyUsageMap = resultMap.get(index);
|
||||
if (dailyUsageMap == null) {
|
||||
dailyUsageMap = new HashMap<>();
|
||||
resultMap.put(index, dailyUsageMap);
|
||||
}
|
||||
dailyUsageMap.put(
|
||||
SELECTED_INDEX_ALL,
|
||||
getAccumulatedUsageDiffData(dailyUsageMap.values()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void insertAllUsageDiffData(
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
|
||||
final List<BatteryDiffData> diffDataList = new ArrayList<>();
|
||||
resultMap.keySet().forEach(
|
||||
key -> diffDataList.add(resultMap.get(key).get(SELECTED_INDEX_ALL)));
|
||||
final Map<Integer, BatteryDiffData> allUsageMap = new HashMap<>();
|
||||
allUsageMap.put(SELECTED_INDEX_ALL, getAccumulatedUsageDiffData(diffDataList));
|
||||
resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BatteryDiffData insertHourlyUsageDiffDataPerSlot(
|
||||
Context context,
|
||||
final int currentUserId,
|
||||
final int workProfileUserId,
|
||||
final int currentIndex,
|
||||
final List<Long> timestamps,
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
|
||||
final List<BatteryDiffEntry> appEntries = new ArrayList<>();
|
||||
final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
|
||||
|
||||
final Long currentTimestamp = timestamps.get(currentIndex);
|
||||
final Long nextTimestamp = currentTimestamp + DateUtils.HOUR_IN_MILLIS;
|
||||
final Long nextTwoTimestamp = nextTimestamp + DateUtils.HOUR_IN_MILLIS;
|
||||
// Fetches BatteryHistEntry data from corresponding time slot.
|
||||
final Map<String, BatteryHistEntry> currentBatteryHistMap =
|
||||
batteryHistoryMap.getOrDefault(currentTimestamp, EMPTY_BATTERY_MAP);
|
||||
final Map<String, BatteryHistEntry> nextBatteryHistMap =
|
||||
batteryHistoryMap.getOrDefault(nextTimestamp, EMPTY_BATTERY_MAP);
|
||||
final Map<String, BatteryHistEntry> nextTwoBatteryHistMap =
|
||||
batteryHistoryMap.getOrDefault(nextTwoTimestamp, EMPTY_BATTERY_MAP);
|
||||
// We should not get the empty list since we have at least one fake data to record
|
||||
// the battery level and status in each time slot, the empty list is used to
|
||||
// represent there is no enough data to apply interpolation arithmetic.
|
||||
if (currentBatteryHistMap.isEmpty()
|
||||
|| nextBatteryHistMap.isEmpty()
|
||||
|| nextTwoBatteryHistMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Collects all keys in these three time slot records as all populations.
|
||||
final Set<String> allBatteryHistEntryKeys = new ArraySet<>();
|
||||
allBatteryHistEntryKeys.addAll(currentBatteryHistMap.keySet());
|
||||
allBatteryHistEntryKeys.addAll(nextBatteryHistMap.keySet());
|
||||
allBatteryHistEntryKeys.addAll(nextTwoBatteryHistMap.keySet());
|
||||
|
||||
double totalConsumePower = 0.0;
|
||||
double consumePowerFromOtherUsers = 0f;
|
||||
// Calculates all packages diff usage data in a specific time slot.
|
||||
for (String key : allBatteryHistEntryKeys) {
|
||||
final BatteryHistEntry currentEntry =
|
||||
currentBatteryHistMap.getOrDefault(key, EMPTY_BATTERY_HIST_ENTRY);
|
||||
final BatteryHistEntry nextEntry =
|
||||
nextBatteryHistMap.getOrDefault(key, EMPTY_BATTERY_HIST_ENTRY);
|
||||
final BatteryHistEntry nextTwoEntry =
|
||||
nextTwoBatteryHistMap.getOrDefault(key, EMPTY_BATTERY_HIST_ENTRY);
|
||||
// Cumulative values is a specific time slot for a specific app.
|
||||
long foregroundUsageTimeInMs =
|
||||
getDiffValue(
|
||||
currentEntry.mForegroundUsageTimeInMs,
|
||||
nextEntry.mForegroundUsageTimeInMs,
|
||||
nextTwoEntry.mForegroundUsageTimeInMs);
|
||||
long backgroundUsageTimeInMs =
|
||||
getDiffValue(
|
||||
currentEntry.mBackgroundUsageTimeInMs,
|
||||
nextEntry.mBackgroundUsageTimeInMs,
|
||||
nextTwoEntry.mBackgroundUsageTimeInMs);
|
||||
double consumePower =
|
||||
getDiffValue(
|
||||
currentEntry.mConsumePower,
|
||||
nextEntry.mConsumePower,
|
||||
nextTwoEntry.mConsumePower);
|
||||
// Excludes entry since we don't have enough data to calculate.
|
||||
if (foregroundUsageTimeInMs == 0
|
||||
&& backgroundUsageTimeInMs == 0
|
||||
&& consumePower == 0) {
|
||||
continue;
|
||||
}
|
||||
final BatteryHistEntry selectedBatteryEntry =
|
||||
selectBatteryHistEntry(currentEntry, nextEntry, nextTwoEntry);
|
||||
if (selectedBatteryEntry == null) {
|
||||
continue;
|
||||
}
|
||||
// Forces refine the cumulative value since it may introduce deviation error since we
|
||||
// will apply the interpolation arithmetic.
|
||||
final float totalUsageTimeInMs =
|
||||
foregroundUsageTimeInMs + backgroundUsageTimeInMs;
|
||||
if (totalUsageTimeInMs > TOTAL_HOURLY_TIME_THRESHOLD) {
|
||||
final float ratio = TOTAL_HOURLY_TIME_THRESHOLD / totalUsageTimeInMs;
|
||||
if (DEBUG) {
|
||||
Log.w(TAG, String.format("abnormal usage time %d|%d for:\n%s",
|
||||
Duration.ofMillis(foregroundUsageTimeInMs).getSeconds(),
|
||||
Duration.ofMillis(backgroundUsageTimeInMs).getSeconds(),
|
||||
currentEntry));
|
||||
}
|
||||
foregroundUsageTimeInMs =
|
||||
Math.round(foregroundUsageTimeInMs * ratio);
|
||||
backgroundUsageTimeInMs =
|
||||
Math.round(backgroundUsageTimeInMs * ratio);
|
||||
consumePower = consumePower * ratio;
|
||||
}
|
||||
totalConsumePower += consumePower;
|
||||
|
||||
final boolean isFromOtherUsers = isConsumedFromOtherUsers(
|
||||
currentUserId, workProfileUserId, selectedBatteryEntry);
|
||||
if (isFromOtherUsers) {
|
||||
consumePowerFromOtherUsers += consumePower;
|
||||
} else {
|
||||
final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
|
||||
context,
|
||||
foregroundUsageTimeInMs,
|
||||
backgroundUsageTimeInMs,
|
||||
consumePower,
|
||||
selectedBatteryEntry);
|
||||
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;
|
||||
}
|
||||
|
||||
final BatteryDiffData resultDiffData =
|
||||
new BatteryDiffData(appEntries, systemEntries, totalConsumePower);
|
||||
return resultDiffData;
|
||||
}
|
||||
|
||||
private static boolean isConsumedFromOtherUsers(
|
||||
final int currentUserId,
|
||||
final int workProfileUserId,
|
||||
final BatteryHistEntry batteryHistEntry) {
|
||||
return batteryHistEntry.mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY
|
||||
&& batteryHistEntry.mUserId != currentUserId
|
||||
&& batteryHistEntry.mUserId != workProfileUserId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BatteryDiffData getAccumulatedUsageDiffData(
|
||||
final Collection<BatteryDiffData> diffEntryListData) {
|
||||
double totalConsumePower = 0f;
|
||||
final Map<String, BatteryDiffEntry> diffEntryMap = new HashMap<>();
|
||||
final List<BatteryDiffEntry> appEntries = new ArrayList<>();
|
||||
final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
|
||||
|
||||
for (BatteryDiffData diffEntryList : diffEntryListData) {
|
||||
if (diffEntryList == null) {
|
||||
continue;
|
||||
}
|
||||
for (BatteryDiffEntry entry : diffEntryList.getAppDiffEntryList()) {
|
||||
computeUsageDiffDataPerEntry(entry, diffEntryMap);
|
||||
totalConsumePower += entry.mConsumePower;
|
||||
}
|
||||
for (BatteryDiffEntry entry : diffEntryList.getSystemDiffEntryList()) {
|
||||
computeUsageDiffDataPerEntry(entry, diffEntryMap);
|
||||
totalConsumePower += entry.mConsumePower;
|
||||
}
|
||||
}
|
||||
|
||||
final Collection<BatteryDiffEntry> diffEntryList = diffEntryMap.values();
|
||||
for (BatteryDiffEntry entry : diffEntryList) {
|
||||
// Sets total daily consume power data into all BatteryDiffEntry.
|
||||
entry.setTotalConsumePower(totalConsumePower);
|
||||
if (entry.isSystemEntry()) {
|
||||
systemEntries.add(entry);
|
||||
} else {
|
||||
appEntries.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return diffEntryList.isEmpty() ? null : new BatteryDiffData(appEntries, systemEntries);
|
||||
}
|
||||
|
||||
private static void computeUsageDiffDataPerEntry(
|
||||
final BatteryDiffEntry entry,
|
||||
final Map<String, BatteryDiffEntry> diffEntryMap) {
|
||||
final String key = entry.mBatteryHistEntry.getKey();
|
||||
final BatteryDiffEntry oldBatteryDiffEntry = diffEntryMap.get(key);
|
||||
// Creates new BatteryDiffEntry if we don't have it.
|
||||
if (oldBatteryDiffEntry == null) {
|
||||
diffEntryMap.put(key, entry.clone());
|
||||
} else {
|
||||
// Sums up some field data into the existing one.
|
||||
oldBatteryDiffEntry.mForegroundUsageTimeInMs +=
|
||||
entry.mForegroundUsageTimeInMs;
|
||||
oldBatteryDiffEntry.mBackgroundUsageTimeInMs +=
|
||||
entry.mBackgroundUsageTimeInMs;
|
||||
oldBatteryDiffEntry.mConsumePower += entry.mConsumePower;
|
||||
}
|
||||
}
|
||||
|
||||
// Removes low percentage data and fake usage data, which will be zero value.
|
||||
private static void purgeLowPercentageAndFakeData(
|
||||
final Context context,
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
|
||||
final Set<CharSequence> backgroundUsageTimeHideList =
|
||||
FeatureFactory.getFactory(context)
|
||||
.getPowerUsageFeatureProvider(context)
|
||||
.getHideBackgroundUsageTimeSet(context);
|
||||
final CharSequence[] notAllowShowEntryPackages =
|
||||
FeatureFactory.getFactory(context)
|
||||
.getPowerUsageFeatureProvider(context)
|
||||
.getHideApplicationEntries(context);
|
||||
resultMap.keySet().forEach(dailyKey -> {
|
||||
final Map<Integer, BatteryDiffData> dailyUsageMap = resultMap.get(dailyKey);
|
||||
dailyUsageMap.values().forEach(diffEntryLists -> {
|
||||
if (diffEntryLists == null) {
|
||||
return;
|
||||
}
|
||||
purgeLowPercentageAndFakeData(
|
||||
diffEntryLists.getAppDiffEntryList(), backgroundUsageTimeHideList,
|
||||
notAllowShowEntryPackages);
|
||||
purgeLowPercentageAndFakeData(
|
||||
diffEntryLists.getSystemDiffEntryList(), backgroundUsageTimeHideList,
|
||||
notAllowShowEntryPackages);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static void purgeLowPercentageAndFakeData(
|
||||
final List<BatteryDiffEntry> entries,
|
||||
final Set<CharSequence> backgroundUsageTimeHideList,
|
||||
final CharSequence[] notAllowShowEntryPackages) {
|
||||
final Iterator<BatteryDiffEntry> iterator = entries.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final BatteryDiffEntry entry = iterator.next();
|
||||
final String packageName = entry.getPackageName();
|
||||
if (entry.getPercentOfTotal() < PERCENTAGE_OF_TOTAL_THRESHOLD
|
||||
|| FAKE_PACKAGE_NAME.equals(packageName)
|
||||
|| contains(packageName, notAllowShowEntryPackages)) {
|
||||
iterator.remove();
|
||||
}
|
||||
if (packageName != null
|
||||
&& !backgroundUsageTimeHideList.isEmpty()
|
||||
&& contains(packageName, backgroundUsageTimeHideList)) {
|
||||
entry.mBackgroundUsageTimeInMs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isUsageMapValid(
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap,
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay) {
|
||||
if (batteryUsageMap.get(SELECTED_INDEX_ALL) == null
|
||||
|| batteryUsageMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL) == null) {
|
||||
Log.e(TAG, "no [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL] in batteryUsageMap");
|
||||
return false;
|
||||
}
|
||||
for (int dailyIndex = 0; dailyIndex < hourlyBatteryLevelsPerDay.size(); dailyIndex++) {
|
||||
if (batteryUsageMap.get(dailyIndex) == null
|
||||
|| !batteryUsageMap.get(dailyIndex).containsKey(SELECTED_INDEX_ALL)) {
|
||||
Log.e(TAG, "no [" + dailyIndex + "][SELECTED_INDEX_ALL] in batteryUsageMap, "
|
||||
+ "daily size is: " + hourlyBatteryLevelsPerDay.size());
|
||||
return false;
|
||||
}
|
||||
if (hourlyBatteryLevelsPerDay.get(dailyIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
final List<Long> timestamps = hourlyBatteryLevelsPerDay.get(dailyIndex).getTimestamps();
|
||||
// Length of hourly usage map should be the length of hourly level data - 1.
|
||||
for (int hourlyIndex = 0; hourlyIndex < timestamps.size() - 1; hourlyIndex++) {
|
||||
if (!batteryUsageMap.get(dailyIndex).containsKey(hourlyIndex)) {
|
||||
Log.e(TAG, "no [" + dailyIndex + "][" + hourlyIndex + "] in batteryUsageMap, "
|
||||
+ "hourly size is: " + (timestamps.size() - 1));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean contains(String target, Set<CharSequence> packageNames) {
|
||||
if (target != null && packageNames != null) {
|
||||
for (CharSequence packageName : packageNames) {
|
||||
if (TextUtils.equals(target, packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static long getDiffValue(long v1, long v2, long v3) {
|
||||
return (v2 > v1 ? v2 - v1 : 0) + (v3 > v2 ? v3 - v2 : 0);
|
||||
}
|
||||
|
||||
private static double getDiffValue(double v1, double v2, double v3) {
|
||||
return (v2 > v1 ? v2 - v1 : 0) + (v3 > v2 ? v3 - v2 : 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BatteryHistEntry selectBatteryHistEntry(
|
||||
final BatteryHistEntry... batteryHistEntries) {
|
||||
for (BatteryHistEntry entry : batteryHistEntries) {
|
||||
if (entry != null && entry != EMPTY_BATTERY_HIST_ENTRY) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BatteryDiffEntry createOtherUsersEntry(
|
||||
Context context, final double consumePower) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(BatteryHistEntry.KEY_UID, BatteryUtils.UID_OTHER_USERS);
|
||||
values.put(BatteryHistEntry.KEY_USER_ID, BatteryUtils.UID_OTHER_USERS);
|
||||
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
|
||||
// We will show the percentage for the "other users" item only, the aggregated
|
||||
// running time information is useless for users to identify individual apps.
|
||||
final BatteryDiffEntry batteryDiffEntry = new BatteryDiffEntry(
|
||||
context,
|
||||
/*foregroundUsageTimeInMs=*/ 0,
|
||||
/*backgroundUsageTimeInMs=*/ 0,
|
||||
consumePower,
|
||||
new BatteryHistEntry(values));
|
||||
return batteryDiffEntry;
|
||||
}
|
||||
|
||||
private static void log(Context context, final String content, final long timestamp,
|
||||
final BatteryHistEntry entry) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format(entry != null ? "%s %s:\n%s" : "%s %s:%s",
|
||||
utcToLocalTime(context, timestamp), content, entry));
|
||||
}
|
||||
}
|
||||
|
||||
// Compute diff map and loads all items (icon and label) in the background.
|
||||
private static final class ComputeUsageMapAndLoadItemsTask
|
||||
extends AsyncTask<Void, Void, Map<Integer, Map<Integer, BatteryDiffData>>> {
|
||||
|
||||
private Context mApplicationContext;
|
||||
private Handler mHandler;
|
||||
private UsageMapAsyncResponse mAsyncResponseDelegate;
|
||||
private List<BatteryLevelData.PeriodBatteryLevelData> mHourlyBatteryLevelsPerDay;
|
||||
private Map<Long, Map<String, BatteryHistEntry>> mBatteryHistoryMap;
|
||||
|
||||
private ComputeUsageMapAndLoadItemsTask(
|
||||
Context context,
|
||||
Handler handler,
|
||||
final UsageMapAsyncResponse asyncResponseDelegate,
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
|
||||
mApplicationContext = context.getApplicationContext();
|
||||
mHandler = handler;
|
||||
mAsyncResponseDelegate = asyncResponseDelegate;
|
||||
mHourlyBatteryLevelsPerDay = hourlyBatteryLevelsPerDay;
|
||||
mBatteryHistoryMap = batteryHistoryMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Integer, Map<Integer, BatteryDiffData>> doInBackground(Void... voids) {
|
||||
if (mApplicationContext == null
|
||||
|| mHandler == null
|
||||
|| mAsyncResponseDelegate == null
|
||||
|| mBatteryHistoryMap == null
|
||||
|| mHourlyBatteryLevelsPerDay == null) {
|
||||
Log.e(TAG, "invalid input for ComputeUsageMapAndLoadItemsTask()");
|
||||
return null;
|
||||
}
|
||||
final long startTime = System.currentTimeMillis();
|
||||
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());
|
||||
}
|
||||
}
|
||||
Log.d(TAG, String.format("execute ComputeUsageMapAndLoadItemsTask in %d/ms",
|
||||
(System.currentTimeMillis() - startTime)));
|
||||
return batteryUsageMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
|
||||
mApplicationContext = null;
|
||||
mHourlyBatteryLevelsPerDay = null;
|
||||
mBatteryHistoryMap = null;
|
||||
// Post results back to main thread to refresh UI.
|
||||
if (mHandler != null && mAsyncResponseDelegate != null) {
|
||||
mHandler.post(() -> {
|
||||
mAsyncResponseDelegate.onBatteryUsageMapLoaded(batteryUsageMap);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,11 +19,16 @@ package com.android.settings.fuelgauge.batteryusage;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
@@ -45,18 +51,30 @@ public class DataProcessorTest {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryLevelData_emptyHistoryMap_returnNull() {
|
||||
assertThat(DataProcessor.getBatteryLevelData(mContext, null)).isNull();
|
||||
assertThat(DataProcessor.getBatteryLevelData(mContext, new HashMap<>())).isNull();
|
||||
assertThat(DataProcessor.getBatteryLevelData(
|
||||
mContext,
|
||||
/*handler=*/ null,
|
||||
/*batteryHistoryMap=*/ null,
|
||||
/*asyncResponseDelegate=*/ null))
|
||||
.isNull();
|
||||
assertThat(DataProcessor.getBatteryLevelData(
|
||||
mContext, /*handler=*/ null, new HashMap<>(), /*asyncResponseDelegate=*/ null))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -67,7 +85,9 @@ public class DataProcessorTest {
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
|
||||
createHistoryMap(timestamps, levels);
|
||||
|
||||
assertThat(DataProcessor.getBatteryLevelData(mContext, batteryHistoryMap)).isNull();
|
||||
assertThat(DataProcessor.getBatteryLevelData(
|
||||
mContext, /*handler=*/ null, batteryHistoryMap, /*asyncResponseDelegate=*/ null))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,7 +99,11 @@ public class DataProcessorTest {
|
||||
createHistoryMap(timestamps, levels);
|
||||
|
||||
final BatteryLevelData resultData =
|
||||
DataProcessor.getBatteryLevelData(mContext, batteryHistoryMap);
|
||||
DataProcessor.getBatteryLevelData(
|
||||
mContext,
|
||||
/*handler=*/ null,
|
||||
batteryHistoryMap,
|
||||
/*asyncResponseDelegate=*/ null);
|
||||
|
||||
final List<Long> expectedDailyTimestamps = List.of(timestamps[0], timestamps[2]);
|
||||
final List<Integer> expectedDailyLevels = List.of(levels[0], levels[2]);
|
||||
@@ -377,6 +401,450 @@ public class DataProcessorTest {
|
||||
.isEqualTo(1640966400000L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
|
||||
|
||||
assertThat(DataProcessor.getBatteryUsageMap(
|
||||
mContext, hourlyBatteryLevelsPerDay, new HashMap<>())).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_emptyHourlyData_returnNull() {
|
||||
final long[] timestamps = {1000000L, 2000000L};
|
||||
final int[] levels = {100, 99};
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
|
||||
createHistoryMap(timestamps, levels);
|
||||
|
||||
assertThat(DataProcessor.getBatteryUsageMap(
|
||||
mContext, new ArrayList<>(), batteryHistoryMap)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_returnsExpectedResult() {
|
||||
final long[] batteryHistoryKeys = new long[]{
|
||||
1641045600000L, // 2022-01-01 22:00:00
|
||||
1641049200000L, // 2022-01-01 23:00:00
|
||||
1641052800000L, // 2022-01-02 00:00:00
|
||||
1641056400000L, // 2022-01-02 01:00:00
|
||||
1641060000000L, // 2022-01-02 02:00:00
|
||||
};
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
final int currentUserId = mContext.getUserId();
|
||||
final BatteryHistEntry fakeEntry = createBatteryHistEntry(
|
||||
ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 0, /*uid=*/ 0L,
|
||||
currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
|
||||
/*foregroundUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
|
||||
// Adds the index = 0 data.
|
||||
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
||||
BatteryHistEntry entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 5.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entryMap.put(fakeEntry.getKey(), fakeEntry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
|
||||
// Adds the index = 1 data.
|
||||
entryMap = new HashMap<>();
|
||||
entryMap.put(fakeEntry.getKey(), fakeEntry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
|
||||
// Adds the index = 2 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 20.0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 15L,
|
||||
25L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entryMap.put(fakeEntry.getKey(), fakeEntry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
|
||||
// Adds the index = 3 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 40.0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 25L,
|
||||
/*backgroundUsageTimeInMs=*/ 35L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 10.0, /*uid=*/ 3L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*foregroundUsageTimeInMs=*/ 40L,
|
||||
/*backgroundUsageTimeInMs=*/ 50L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package3", "label3", /*consumePower=*/ 15.0, /*uid=*/ 4L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 5L,
|
||||
/*backgroundUsageTimeInMs=*/ 5L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entryMap.put(fakeEntry.getKey(), fakeEntry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[3], entryMap);
|
||||
// Adds the index = 4 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 40.0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
|
||||
/*backgroundUsageTimeInMs=*/ 40L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 20.0, /*uid=*/ 3L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*foregroundUsageTimeInMs=*/ 50L,
|
||||
/*backgroundUsageTimeInMs=*/ 60L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package3", "label3", /*consumePower=*/ 40.0, /*uid=*/ 4L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 5L,
|
||||
/*backgroundUsageTimeInMs=*/ 5L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entryMap.put(fakeEntry.getKey(), fakeEntry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[4], entryMap);
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
// Adds the day 1 data.
|
||||
List<Long> timestamps =
|
||||
List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
|
||||
final List<Integer> levels = List.of(100, 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
|
||||
// Adds the day 2 data.
|
||||
timestamps = List.of(batteryHistoryKeys[2], batteryHistoryKeys[4]);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
|
||||
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
|
||||
DataProcessor.getBatteryUsageMap(
|
||||
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap);
|
||||
|
||||
BatteryDiffData resultDiffData =
|
||||
resultMap
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL)
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 40.0,
|
||||
/*foregroundUsageTimeInMs=*/ 30, /*backgroundUsageTimeInMs=*/ 40);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(1), currentUserId, /*uid=*/ 4L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 40.0,
|
||||
/*foregroundUsageTimeInMs=*/ 5, /*backgroundUsageTimeInMs=*/ 5);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
|
||||
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 20.0,
|
||||
/*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
|
||||
resultDiffData = resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
|
||||
/*foregroundUsageTimeInMs=*/ 15, /*backgroundUsageTimeInMs=*/ 25);
|
||||
resultDiffData = resultMap.get(1).get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 4L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
|
||||
/*foregroundUsageTimeInMs=*/ 5, /*backgroundUsageTimeInMs=*/ 5);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(1), currentUserId, /*uid=*/ 2L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 25.0,
|
||||
/*foregroundUsageTimeInMs=*/ 15, /*backgroundUsageTimeInMs=*/ 15);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
|
||||
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 25.0,
|
||||
/*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_multipleUsers_returnsExpectedResult() {
|
||||
final long[] batteryHistoryKeys = new long[]{
|
||||
1641052800000L, // 2022-01-02 00:00:00
|
||||
1641056400000L, // 2022-01-02 01:00:00
|
||||
1641060000000L // 2022-01-02 02:00:00
|
||||
};
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
final int currentUserId = mContext.getUserId();
|
||||
// Adds the index = 0 data.
|
||||
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
||||
BatteryHistEntry entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 5.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 10.0, /*uid=*/ 2L, currentUserId + 1,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 5.0, /*uid=*/ 3L, currentUserId + 2,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
|
||||
/*backgroundUsageTimeInMs=*/ 30L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
|
||||
// Adds the index = 1 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 15.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
|
||||
/*backgroundUsageTimeInMs=*/ 30L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 30.0, /*uid=*/ 2L, currentUserId + 1,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 15.0, /*uid=*/ 3L, currentUserId + 2,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
|
||||
/*backgroundUsageTimeInMs=*/ 30L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
|
||||
// Adds the index = 2 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 25.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
|
||||
/*backgroundUsageTimeInMs=*/ 30L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 50.0, /*uid=*/ 2L, currentUserId + 1,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 25.0, /*uid=*/ 3L, currentUserId + 2,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
|
||||
/*backgroundUsageTimeInMs=*/ 30L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
|
||||
final List<Integer> levels = List.of(100, 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
|
||||
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
|
||||
DataProcessor.getBatteryUsageMap(
|
||||
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap);
|
||||
|
||||
final BatteryDiffData resultDiffData =
|
||||
resultMap
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL)
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 1L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 25.0,
|
||||
/*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getSystemDiffEntryList().get(0), BatteryUtils.UID_OTHER_USERS,
|
||||
/*uid=*/ BatteryUtils.UID_OTHER_USERS, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
|
||||
/*consumePercentage=*/ 75.0, /*foregroundUsageTimeInMs=*/ 0,
|
||||
/*backgroundUsageTimeInMs=*/ 0);
|
||||
assertThat(resultMap.get(0).get(0)).isNotNull();
|
||||
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_usageTimeExceed_returnsExpectedResult() {
|
||||
final long[] batteryHistoryKeys = new long[]{
|
||||
1641052800000L, // 2022-01-02 00:00:00
|
||||
1641056400000L, // 2022-01-02 01:00:00
|
||||
1641060000000L // 2022-01-02 02:00:00
|
||||
};
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
final int currentUserId = mContext.getUserId();
|
||||
// Adds the index = 0 data.
|
||||
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
||||
BatteryHistEntry entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
|
||||
// Adds the index = 1 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
|
||||
// Adds the index = 2 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 500.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 3600000L,
|
||||
/*backgroundUsageTimeInMs=*/ 7200000L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
|
||||
final List<Integer> levels = List.of(100, 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
|
||||
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
|
||||
DataProcessor.getBatteryUsageMap(
|
||||
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap);
|
||||
|
||||
final BatteryDiffData resultDiffData =
|
||||
resultMap
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL)
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
// Verifies the clipped usage time.
|
||||
final float ratio = (float) (7200) / (float) (3600 + 7200);
|
||||
final BatteryDiffEntry resultEntry = resultDiffData.getAppDiffEntryList().get(0);
|
||||
assertThat(resultEntry.mForegroundUsageTimeInMs)
|
||||
.isEqualTo(Math.round(entry.mForegroundUsageTimeInMs * ratio));
|
||||
assertThat(resultEntry.mBackgroundUsageTimeInMs)
|
||||
.isEqualTo(Math.round(entry.mBackgroundUsageTimeInMs * ratio));
|
||||
assertThat(resultEntry.mConsumePower)
|
||||
.isEqualTo(entry.mConsumePower * ratio);
|
||||
assertThat(resultMap.get(0).get(0)).isNotNull();
|
||||
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_hideApplicationEntries_returnsExpectedResult() {
|
||||
final long[] batteryHistoryKeys = new long[]{
|
||||
1641052800000L, // 2022-01-02 00:00:00
|
||||
1641056400000L, // 2022-01-02 01:00:00
|
||||
1641060000000L // 2022-01-02 02:00:00
|
||||
};
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
final int currentUserId = mContext.getUserId();
|
||||
// Adds the index = 0 data.
|
||||
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
||||
BatteryHistEntry entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
|
||||
// Adds the index = 1 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
|
||||
// Adds the index = 2 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 10.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 10.0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
|
||||
final List<Integer> levels = List.of(100, 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
|
||||
when(mPowerUsageFeatureProvider.getHideApplicationEntries(mContext))
|
||||
.thenReturn(new CharSequence[]{"package1"});
|
||||
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
|
||||
DataProcessor.getBatteryUsageMap(
|
||||
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap);
|
||||
|
||||
final BatteryDiffData resultDiffData =
|
||||
resultMap
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL)
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
assertBatteryDiffEntry(
|
||||
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
|
||||
/*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatteryUsageMap_hideBackgroundUsageTime_returnsExpectedResult() {
|
||||
final long[] batteryHistoryKeys = new long[]{
|
||||
1641052800000L, // 2022-01-02 00:00:00
|
||||
1641056400000L, // 2022-01-02 01:00:00
|
||||
1641060000000L // 2022-01-02 02:00:00
|
||||
};
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
final int currentUserId = mContext.getUserId();
|
||||
// Adds the index = 0 data.
|
||||
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
||||
BatteryHistEntry entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
|
||||
// Adds the index = 1 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
|
||||
/*backgroundUsageTimeInMs=*/ 0L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
|
||||
// Adds the index = 2 data.
|
||||
entryMap = new HashMap<>();
|
||||
entry = createBatteryHistEntry(
|
||||
"package1", "label1", /*consumePower=*/ 10.0, /*uid=*/ 1L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
entry = createBatteryHistEntry(
|
||||
"package2", "label2", /*consumePower=*/ 10.0, /*uid=*/ 2L, currentUserId,
|
||||
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
|
||||
/*backgroundUsageTimeInMs=*/ 20L);
|
||||
entryMap.put(entry.getKey(), entry);
|
||||
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
|
||||
final List<Integer> levels = List.of(100, 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
|
||||
when(mPowerUsageFeatureProvider.getHideBackgroundUsageTimeSet(mContext))
|
||||
.thenReturn(new HashSet(Arrays.asList((CharSequence) "package2")));
|
||||
|
||||
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
|
||||
DataProcessor.getBatteryUsageMap(
|
||||
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap);
|
||||
|
||||
final BatteryDiffData resultDiffData =
|
||||
resultMap
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL)
|
||||
.get(DataProcessor.SELECTED_INDEX_ALL);
|
||||
BatteryDiffEntry resultEntry = resultDiffData.getAppDiffEntryList().get(0);
|
||||
assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(20);
|
||||
resultEntry = resultDiffData.getAppDiffEntryList().get(1);
|
||||
assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(0);
|
||||
}
|
||||
|
||||
private static Map<Long, Map<String, BatteryHistEntry>> createHistoryMap(
|
||||
final long[] timestamps, final int[] levels) {
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
@@ -391,6 +859,23 @@ public class DataProcessorTest {
|
||||
return batteryHistoryMap;
|
||||
}
|
||||
|
||||
private static BatteryHistEntry createBatteryHistEntry(
|
||||
final String packageName, final String appLabel, final double consumePower,
|
||||
final long uid, final long userId, final int consumerType,
|
||||
final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs) {
|
||||
// Only insert required fields.
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName);
|
||||
values.put(BatteryHistEntry.KEY_APP_LABEL, appLabel);
|
||||
values.put(BatteryHistEntry.KEY_UID, uid);
|
||||
values.put(BatteryHistEntry.KEY_USER_ID, userId);
|
||||
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, consumerType);
|
||||
values.put(BatteryHistEntry.KEY_CONSUME_POWER, consumePower);
|
||||
values.put(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME, foregroundUsageTimeInMs);
|
||||
values.put(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME, backgroundUsageTimeInMs);
|
||||
return new BatteryHistEntry(values);
|
||||
}
|
||||
|
||||
private static void verifyExpectedBatteryLevelData(
|
||||
final BatteryLevelData resultData,
|
||||
final List<Long> expectedDailyTimestamps,
|
||||
@@ -451,4 +936,15 @@ public class DataProcessorTest {
|
||||
.isEqualTo(expectedEnd.getTimeInMillis());
|
||||
}
|
||||
|
||||
private static void assertBatteryDiffEntry(
|
||||
final BatteryDiffEntry entry, final long userId, final long uid,
|
||||
final int consumerType, final double consumePercentage,
|
||||
final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs) {
|
||||
assertThat(entry.mBatteryHistEntry.mUserId).isEqualTo(userId);
|
||||
assertThat(entry.mBatteryHistEntry.mUid).isEqualTo(uid);
|
||||
assertThat(entry.mBatteryHistEntry.mConsumerType).isEqualTo(consumerType);
|
||||
assertThat(entry.getPercentOfTotal()).isEqualTo(consumePercentage);
|
||||
assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(foregroundUsageTimeInMs);
|
||||
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user