diff --git a/Android.bp b/Android.bp
index 44f83f38fdf..c6a62a7eed9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -85,6 +85,7 @@ android_library {
"net-utils-framework-common",
"app-usage-event-protos-lite",
"battery-event-protos-lite",
+ "battery-usage-slot-protos-lite",
"power-anomaly-event-protos-lite",
"settings-contextual-card-protos-lite",
"settings-log-bridge-protos-lite",
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index b443773b6cd..4ec1f7b6b21 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -16,6 +16,8 @@
package com.android.settings.fuelgauge;
+import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.isUserConsumer;
+
import android.app.Activity;
import android.app.ActivityManager;
import android.app.backup.BackupManager;
@@ -41,7 +43,6 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
-import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.HelpUtils;
@@ -149,14 +150,13 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
Context context, int sourceMetricsCategory,
BatteryDiffEntry diffEntry, String usagePercent, String slotInformation,
boolean showTimeInformation) {
- final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry;
final LaunchBatteryDetailPageArgs launchArgs = new LaunchBatteryDetailPageArgs();
// configure the launch argument.
launchArgs.mUsagePercent = usagePercent;
launchArgs.mPackageName = diffEntry.getPackageName();
launchArgs.mAppLabel = diffEntry.getAppLabel();
launchArgs.mSlotInformation = slotInformation;
- launchArgs.mUid = (int) histEntry.mUid;
+ launchArgs.mUid = (int) diffEntry.mUid;
launchArgs.mIconId = diffEntry.getAppIconId();
launchArgs.mConsumedPower = (int) diffEntry.mConsumePower;
if (showTimeInformation) {
@@ -164,7 +164,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
launchArgs.mBackgroundTimeMs = diffEntry.mBackgroundUsageTimeInMs;
launchArgs.mScreenOnTimeMs = diffEntry.mScreenOnTimeInMs;
}
- launchArgs.mIsUserEntry = histEntry.isUserEntry();
+ launchArgs.mIsUserEntry = isUserConsumer(diffEntry.mConsumerType);
startBatteryDetailPage(context, sourceMetricsCategory, launchArgs);
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/AppUsageDataLoader.java b/src/com/android/settings/fuelgauge/batteryusage/AppUsageDataLoader.java
deleted file mode 100644
index c336fcdfc65..00000000000
--- a/src/com/android/settings/fuelgauge/batteryusage/AppUsageDataLoader.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.fuelgauge.batteryusage;
-
-import android.app.usage.UsageEvents;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import java.util.List;
-import java.util.Map;
-import java.util.function.Supplier;
-
-/** Load app usage events data in the background. */
-public final class AppUsageDataLoader {
- private static final String TAG = "AppUsageDataLoader";
-
- // For testing only.
- @VisibleForTesting
- static Supplier
*
* {@code Long} stands for the userId.
* {@code String} stands for the packageName.
@@ -403,8 +410,8 @@ public final class DataProcessor {
/**
* @return Returns the processed history map which has interpolated to every hour data.
- * The start and end timestamp must be the even hours.
- * The keys of processed history map should contain every hour between the start and end
+ * The start timestamp is the first timestamp in batteryHistoryMap. The end timestamp is current
+ * time. The keys of processed history map should contain every hour between the start and end
* timestamp. If there's no data in some key, the value will be the empty map.
*/
static Map> getHistoryMapWithExpectedTimestamps(
@@ -431,28 +438,23 @@ public final class DataProcessor {
static BatteryLevelData getLevelDataThroughProcessedHistoryMap(
Context context,
final Map> processedBatteryHistoryMap) {
- final List timestampList = new ArrayList<>(processedBatteryHistoryMap.keySet());
- Collections.sort(timestampList);
- final List dailyTimestamps = getDailyTimestamps(timestampList);
// There should be at least the start and end timestamps. Otherwise, return null to not show
// data in usage chart.
- if (dailyTimestamps.size() < MIN_DAILY_DATA_SIZE) {
+ if (processedBatteryHistoryMap.size() < MIN_DAILY_DATA_SIZE) {
return null;
}
-
- final List> hourlyTimestamps = getHourlyTimestamps(dailyTimestamps);
- final BatteryLevelData.PeriodBatteryLevelData dailyLevelData =
- getPeriodBatteryLevelData(context, processedBatteryHistoryMap, dailyTimestamps);
- final List hourlyLevelData =
- getHourlyPeriodBatteryLevelData(
- context, processedBatteryHistoryMap, hourlyTimestamps);
- return new BatteryLevelData(dailyLevelData, hourlyLevelData);
+ Map batteryLevelMap = new ArrayMap<>();
+ for (Long timestamp : processedBatteryHistoryMap.keySet()) {
+ batteryLevelMap.put(
+ timestamp, getLevel(context, processedBatteryHistoryMap, timestamp));
+ }
+ return new BatteryLevelData(batteryLevelMap);
}
/**
- * Computes expected timestamp slots. The start timestamp is the last full charge time.
- * The end timestamp is current time. The middle timestamps are the sharp hour timestamps
- * between the start and end timestamps.
+ * Computes expected timestamp slots. The start timestamp is the first timestamp in
+ * rawTimestampList. The end timestamp is current time. The middle timestamps are the sharp hour
+ * timestamps between the start and end timestamps.
*/
@VisibleForTesting
static List getTimestampSlots(final List rawTimestampList, final long currentTime) {
@@ -475,56 +477,6 @@ public final class DataProcessor {
return timestampSlots;
}
- /**
- * Computes expected daily timestamp slots.
- *
- * The valid result should be composed of 3 parts:
- * 1) start timestamp
- * 2) every 00:00 timestamp (default timezone) between the start and end
- * 3) end timestamp
- * Otherwise, returns an empty list.
- */
- @VisibleForTesting
- static List getDailyTimestamps(final List timestampList) {
- final List dailyTimestampList = new ArrayList<>();
- // If timestamp number is smaller than 2, the following computation is not necessary.
- if (timestampList.size() < MIN_TIMESTAMP_DATA_SIZE) {
- return dailyTimestampList;
- }
- final long startTime = timestampList.get(0);
- final long endTime = timestampList.get(timestampList.size() - 1);
- for (long timestamp = startTime; timestamp < endTime;
- timestamp = TimestampUtils.getNextDayTimestamp(timestamp)) {
- dailyTimestampList.add(timestamp);
- }
- dailyTimestampList.add(endTime);
- return dailyTimestampList;
- }
-
- @VisibleForTesting
- static List> getHourlyTimestamps(final List dailyTimestamps) {
- final List> hourlyTimestamps = new ArrayList<>();
- if (dailyTimestamps.size() < MIN_DAILY_DATA_SIZE) {
- return hourlyTimestamps;
- }
-
- for (int dailyIndex = 0; dailyIndex < dailyTimestamps.size() - 1; dailyIndex++) {
- final List hourlyTimestampsPerDay = new ArrayList<>();
- final long startTime = dailyTimestamps.get(dailyIndex);
- final long endTime = dailyTimestamps.get(dailyIndex + 1);
-
- hourlyTimestampsPerDay.add(startTime);
- for (long timestamp = TimestampUtils.getNextEvenHourTimestamp(startTime);
- timestamp < endTime; timestamp += MIN_TIME_SLOT) {
- hourlyTimestampsPerDay.add(timestamp);
- }
- hourlyTimestampsPerDay.add(endTime);
-
- hourlyTimestamps.add(hourlyTimestampsPerDay);
- }
- return hourlyTimestamps;
- }
-
@VisibleForTesting
static boolean isFromFullCharge(@Nullable final Map entryList) {
if (entryList == null) {
@@ -560,34 +512,102 @@ public final class DataProcessor {
return results;
}
+ static Map getBatteryDiffDataMap(
+ Context context,
+ final List hourlyBatteryLevelsPerDay,
+ final Map> batteryHistoryMap,
+ final Map>>>>
+ appUsagePeriodMap,
+ final @NonNull Set systemAppsPackageNames,
+ final @NonNull Set systemAppsUids) {
+ final Map batteryDiffDataMap = new ArrayMap<>();
+ 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 =
+ // sum(Math.abs(timestamp[i+1] data - timestamp[i] data));
+ // since we want to aggregate every hour usage diff data into a single time slot.
+ for (int dailyIndex = 0; dailyIndex < hourlyBatteryLevelsPerDay.size(); dailyIndex++) {
+ if (hourlyBatteryLevelsPerDay.get(dailyIndex) == null) {
+ continue;
+ }
+ final List hourlyTimestamps =
+ hourlyBatteryLevelsPerDay.get(dailyIndex).getTimestamps();
+ for (int hourlyIndex = 0; hourlyIndex < hourlyTimestamps.size() - 1; hourlyIndex++) {
+ final Long startTimestamp = hourlyTimestamps.get(hourlyIndex);
+ final Long endTimestamp = hourlyTimestamps.get(hourlyIndex + 1);
+ final int startBatteryLevel =
+ hourlyBatteryLevelsPerDay.get(dailyIndex).getLevels().get(hourlyIndex);
+ final int endBatteryLevel =
+ hourlyBatteryLevelsPerDay.get(dailyIndex).getLevels().get(hourlyIndex + 1);
+ final long slotDuration = endTimestamp - startTimestamp;
+ List> slotBatteryHistoryList = new ArrayList<>();
+ slotBatteryHistoryList.add(
+ batteryHistoryMap.getOrDefault(startTimestamp, EMPTY_BATTERY_MAP));
+ for (Long timestamp = TimestampUtils.getNextHourTimestamp(startTimestamp);
+ timestamp < endTimestamp; timestamp += DateUtils.HOUR_IN_MILLIS) {
+ slotBatteryHistoryList.add(
+ batteryHistoryMap.getOrDefault(timestamp, EMPTY_BATTERY_MAP));
+ }
+ slotBatteryHistoryList.add(
+ batteryHistoryMap.getOrDefault(endTimestamp, EMPTY_BATTERY_MAP));
+
+ final BatteryDiffData hourlyBatteryDiffData =
+ insertHourlyUsageDiffDataPerSlot(
+ context,
+ startTimestamp,
+ endTimestamp,
+ startBatteryLevel,
+ endBatteryLevel,
+ currentUserId,
+ workProfileUserId,
+ slotDuration,
+ systemAppsPackageNames,
+ systemAppsUids,
+ appUsagePeriodMap == null
+ || appUsagePeriodMap.get(dailyIndex) == null
+ ? null
+ : appUsagePeriodMap.get(dailyIndex).get(hourlyIndex),
+ slotBatteryHistoryList);
+ batteryDiffDataMap.put(startTimestamp, hourlyBatteryDiffData);
+ }
+ }
+ return batteryDiffDataMap;
+ }
+
/**
* @return Returns the indexed battery usage data for each corresponding time slot.
*
* There could be 2 cases of the returned value:
*
- * - null: empty or invalid data.
- * - non-null: must be a 2d map and composed by 3 parts:
+ * - null: empty or invalid data.
+ * - 1 part: if batteryLevelData is null.
+ * [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL]
+ * - 3 parts: if batteryLevelData is not null.
* 1 - [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL]
* 2 - [0][SELECTED_INDEX_ALL] ~ [maxDailyIndex][SELECTED_INDEX_ALL]
* 3 - [0][0] ~ [maxDailyIndex][maxHourlyIndex]
*
*/
- @Nullable
- static Map> getBatteryUsageMap(
+ static Map> generateBatteryUsageMap(
final Context context,
- final List hourlyBatteryLevelsPerDay,
- final Map> batteryHistoryMap,
- final Map>>>>
- appUsagePeriodMap) {
- if (batteryHistoryMap.isEmpty()) {
- return null;
- }
+ final Map batteryDiffDataMap,
+ final @Nullable BatteryLevelData batteryLevelData) {
final Map> resultMap = new ArrayMap<>();
- final Set systemAppsPackageNames = getSystemAppsPackageNames(context);
- final Set systemAppsUids = getSystemAppsUids(context);
+ if (batteryLevelData == null) {
+ Preconditions.checkArgument(batteryDiffDataMap.size() == 1);
+ BatteryDiffData batteryDiffData = batteryDiffDataMap.values().stream().toList().get(0);
+ final Map allUsageMap = new ArrayMap<>();
+ allUsageMap.put(SELECTED_INDEX_ALL, batteryDiffData);
+ resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
+ return resultMap;
+ }
+ List hourlyBatteryLevelsPerDay =
+ batteryLevelData.getHourlyBatteryLevelsPerDay();
// Insert diff data from [0][0] to [maxDailyIndex][maxHourlyIndex].
- insertHourlyUsageDiffData(context, systemAppsPackageNames, systemAppsUids,
- hourlyBatteryLevelsPerDay, batteryHistoryMap, appUsagePeriodMap, resultMap);
+ insertHourlyUsageDiffData(hourlyBatteryLevelsPerDay, batteryDiffDataMap, resultMap);
// Insert diff data from [0][SELECTED_INDEX_ALL] to [maxDailyIndex][SELECTED_INDEX_ALL].
insertDailyUsageDiffData(context, hourlyBatteryLevelsPerDay, resultMap);
// Insert diff data [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL].
@@ -602,7 +622,10 @@ public final class DataProcessor {
@Nullable
static BatteryDiffData generateBatteryDiffData(
final Context context,
- final List batteryHistEntryList) {
+ final long startTimestamp,
+ final List batteryHistEntryList,
+ final @NonNull Set systemAppsPackageNames,
+ final @NonNull Set systemAppsUids) {
if (batteryHistEntryList == null || batteryHistEntryList.isEmpty()) {
Log.w(TAG, "batteryHistEntryList is null or empty in generateBatteryDiffData()");
return null;
@@ -624,6 +647,14 @@ public final class DataProcessor {
} else {
final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
context,
+ entry.mUid,
+ entry.mUserId,
+ entry.getKey(),
+ entry.mIsHidden,
+ entry.mDrainType,
+ entry.mPackageName,
+ entry.mAppLabel,
+ entry.mConsumerType,
entry.mForegroundUsageTimeInMs,
entry.mBackgroundUsageTimeInMs,
/*screenOnTimeInMs=*/ 0,
@@ -631,8 +662,7 @@ public final class DataProcessor {
entry.mForegroundUsageConsumePower,
entry.mForegroundServiceUsageConsumePower,
entry.mBackgroundUsageConsumePower,
- entry.mCachedUsageConsumePower,
- entry);
+ entry.mCachedUsageConsumePower);
if (currentBatteryDiffEntry.isSystemEntry()) {
systemEntries.add(currentBatteryDiffEntry);
} else {
@@ -645,11 +675,10 @@ public final class DataProcessor {
if (appEntries.isEmpty() && systemEntries.isEmpty()) {
return null;
}
-
- final Set systemAppsPackageNames = getSystemAppsPackageNames(context);
- final Set systemAppsUids = getSystemAppsUids(context);
- return new BatteryDiffData(context, /* screenOnTime= */ 0L, appEntries, systemEntries,
- systemAppsPackageNames, systemAppsUids, /* isAccumulated= */ false);
+ return new BatteryDiffData(context, startTimestamp, getCurrentTimeMillis(),
+ /* startBatteryLevel =*/ 100, getCurrentLevel(context), /* screenOnTime= */ 0L,
+ appEntries, systemEntries, systemAppsPackageNames, systemAppsUids,
+ /* isAccumulated= */ false);
}
/**
@@ -845,21 +874,15 @@ public final class DataProcessor {
return getScreenOnTime(appUsageMap.get(userId).get(packageName));
}
- /**
- * @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]
- */
- static Map> getBatteryUsageMapFromStatsService(
- final Context context) {
- final Map> resultMap = new ArrayMap<>();
- final Map allUsageMap = new ArrayMap<>();
- // Always construct the map whether the value is null or not.
- allUsageMap.put(SELECTED_INDEX_ALL,
- generateBatteryDiffData(context, getBatteryHistListFromFromStatsService(context)));
- resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
- return resultMap;
+ static Map getBatteryDiffDataMapFromStatsService(
+ final Context context, final long startTimestamp,
+ @NonNull final Set systemAppsPackageNames,
+ @NonNull final Set systemAppsUids) {
+ Map batteryDiffDataMap = new ArrayMap<>(1);
+ batteryDiffDataMap.put(startTimestamp, generateBatteryDiffData(
+ context, startTimestamp, getBatteryHistListFromFromStatsService(context),
+ systemAppsPackageNames, systemAppsUids));
+ return batteryDiffDataMap;
}
static void loadLabelAndIcon(
@@ -878,6 +901,22 @@ public final class DataProcessor {
}
}
+ static Set getSystemAppsPackageNames(Context context) {
+ return sTestSystemAppsPackageNames != null ? sTestSystemAppsPackageNames
+ : AppListRepositoryUtil.getSystemPackageNames(context, context.getUserId());
+ }
+
+ static Set getSystemAppsUids(Context context) {
+ Set result = new ArraySet<>(1);
+ try {
+ result.add(context.getPackageManager().getUidForSharedUser(
+ ANDROID_CORE_APPS_SHARED_USER_ID));
+ } catch (PackageManager.NameNotFoundException e) {
+ // No Android Core Apps
+ }
+ return result;
+ }
+
/**
* Generates the list of {@link AppUsageEvent} within the specific time range.
* The buffer is added to make sure the app usage calculation near the boundaries is correct.
@@ -1158,28 +1197,6 @@ public final class DataProcessor {
resultMap.put(currentSlot, newHistEntryMap);
}
- private static List getHourlyPeriodBatteryLevelData(
- Context context,
- final Map> processedBatteryHistoryMap,
- final List> timestamps) {
- final List levelData = new ArrayList<>();
- timestamps.forEach(
- timestampList -> levelData.add(
- getPeriodBatteryLevelData(
- context, processedBatteryHistoryMap, timestampList)));
- return levelData;
- }
-
- private static BatteryLevelData.PeriodBatteryLevelData getPeriodBatteryLevelData(
- Context context,
- final Map> processedBatteryHistoryMap,
- final List timestamps) {
- final List levels = new ArrayList<>();
- timestamps.forEach(
- timestamp -> levels.add(getLevel(context, processedBatteryHistoryMap, timestamp)));
- return new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels);
- }
-
private static Integer getLevel(
Context context,
final Map> processedBatteryHistoryMap,
@@ -1188,13 +1205,12 @@ public final class DataProcessor {
if (entryMap == null || entryMap.isEmpty()) {
Log.e(TAG, "abnormal entry list in the timestamp:"
+ ConvertUtils.utcToLocalTimeForLogging(timestamp));
- return null;
+ return BATTERY_LEVEL_UNKNOWN;
}
// The current time battery history hasn't been loaded yet, returns the current battery
// level.
if (entryMap.containsKey(CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER)) {
- final Intent intent = BatteryUtils.getBatteryIntent(context);
- return BatteryStatus.getBatteryLevel(intent);
+ return getCurrentLevel(context);
}
// Averages the battery level in each time slot to avoid corner conditions.
float batteryLevelCounter = 0;
@@ -1204,20 +1220,15 @@ public final class DataProcessor {
return Math.round(batteryLevelCounter / entryMap.size());
}
+ private static int getCurrentLevel(Context context) {
+ final Intent intent = BatteryUtils.getBatteryIntent(context);
+ return BatteryStatus.getBatteryLevel(intent);
+ }
+
private static void insertHourlyUsageDiffData(
- Context context,
- final Set systemAppsPackageNames,
- final Set systemAppsUids,
final List hourlyBatteryLevelsPerDay,
- final Map> batteryHistoryMap,
- final Map>>>>
- appUsagePeriodMap,
+ final Map batteryDiffDataMap,
final Map> 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 =
// sum(Math.abs(timestamp[i+1] data - timestamp[i] data));
// since we want to aggregate every hour usage diff data into a single time slot.
@@ -1231,33 +1242,7 @@ public final class DataProcessor {
hourlyBatteryLevelsPerDay.get(dailyIndex).getTimestamps();
for (int hourlyIndex = 0; hourlyIndex < hourlyTimestamps.size() - 1; hourlyIndex++) {
final Long startTimestamp = hourlyTimestamps.get(hourlyIndex);
- final Long endTimestamp = hourlyTimestamps.get(hourlyIndex + 1);
- final long slotDuration = endTimestamp - startTimestamp;
- List> slotBatteryHistoryList = new ArrayList<>();
- slotBatteryHistoryList.add(
- batteryHistoryMap.getOrDefault(startTimestamp, EMPTY_BATTERY_MAP));
- for (Long timestamp = TimestampUtils.getNextHourTimestamp(startTimestamp);
- timestamp < endTimestamp; timestamp += DateUtils.HOUR_IN_MILLIS) {
- slotBatteryHistoryList.add(
- batteryHistoryMap.getOrDefault(timestamp, EMPTY_BATTERY_MAP));
- }
- slotBatteryHistoryList.add(
- batteryHistoryMap.getOrDefault(endTimestamp, EMPTY_BATTERY_MAP));
-
- final BatteryDiffData hourlyBatteryDiffData =
- insertHourlyUsageDiffDataPerSlot(
- context,
- currentUserId,
- workProfileUserId,
- slotDuration,
- systemAppsPackageNames,
- systemAppsUids,
- appUsagePeriodMap == null
- || appUsagePeriodMap.get(dailyIndex) == null
- ? null
- : appUsagePeriodMap.get(dailyIndex).get(hourlyIndex),
- slotBatteryHistoryList);
- dailyDiffMap.put(hourlyIndex, hourlyBatteryDiffData);
+ dailyDiffMap.put(hourlyIndex, batteryDiffDataMap.get(startTimestamp));
}
}
}
@@ -1292,6 +1277,10 @@ public final class DataProcessor {
@Nullable
private static BatteryDiffData insertHourlyUsageDiffDataPerSlot(
final Context context,
+ final long startTimestamp,
+ final long endTimestamp,
+ final int startBatteryLevel,
+ final int endBatteryLevel,
final int currentUserId,
final int workProfileUserId,
final long slotDuration,
@@ -1401,7 +1390,7 @@ public final class DataProcessor {
currentEntry.mCachedUsageConsumePower,
nextEntry.mCachedUsageConsumePower);
}
- if (selectedBatteryEntry.isSystemEntry()
+ if (isSystemConsumer(selectedBatteryEntry.mConsumerType)
&& selectedBatteryEntry.mDrainType == BatteryConsumer.POWER_COMPONENT_SCREEN) {
// Replace Screen system component time with screen on time.
foregroundUsageTimeInMs = slotScreenOnTime;
@@ -1447,6 +1436,14 @@ public final class DataProcessor {
backgroundUsageTimeInMs, (long) slotDuration - screenOnTime);
final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
context,
+ selectedBatteryEntry.mUid,
+ selectedBatteryEntry.mUserId,
+ selectedBatteryEntry.getKey(),
+ selectedBatteryEntry.mIsHidden,
+ selectedBatteryEntry.mDrainType,
+ selectedBatteryEntry.mPackageName,
+ selectedBatteryEntry.mAppLabel,
+ selectedBatteryEntry.mConsumerType,
foregroundUsageTimeInMs,
backgroundUsageTimeInMs,
screenOnTime,
@@ -1454,8 +1451,7 @@ public final class DataProcessor {
foregroundUsageConsumePower,
foregroundServiceUsageConsumePower,
backgroundUsageConsumePower,
- cachedUsageConsumePower,
- selectedBatteryEntry);
+ cachedUsageConsumePower);
if (currentBatteryDiffEntry.isSystemEntry()) {
systemEntries.add(currentBatteryDiffEntry);
} else {
@@ -1468,7 +1464,8 @@ public final class DataProcessor {
return null;
}
- return new BatteryDiffData(context, slotScreenOnTime, appEntries, systemEntries,
+ return new BatteryDiffData(context, startTimestamp, endTimestamp, startBatteryLevel,
+ endBatteryLevel, slotScreenOnTime, appEntries, systemEntries,
systemAppsPackageNames, systemAppsUids, /* isAccumulated= */ false);
}
@@ -1519,7 +1516,7 @@ public final class DataProcessor {
final int currentUserId,
final int workProfileUserId,
final BatteryHistEntry batteryHistEntry) {
- return batteryHistEntry.mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY
+ return isUidConsumer(batteryHistEntry.mConsumerType)
&& batteryHistEntry.mUserId != currentUserId
&& batteryHistEntry.mUserId != workProfileUserId;
}
@@ -1531,11 +1528,23 @@ public final class DataProcessor {
final List appEntries = new ArrayList<>();
final List systemEntries = new ArrayList<>();
+ long startTimestamp = Long.MAX_VALUE;
+ long endTimestamp = 0;
+ int startBatteryLevel = BATTERY_LEVEL_UNKNOWN;
+ int endBatteryLevel = BATTERY_LEVEL_UNKNOWN;
long totalScreenOnTime = 0;
for (BatteryDiffData batteryDiffData : batteryDiffDataList) {
if (batteryDiffData == null) {
continue;
}
+ if (startTimestamp > batteryDiffData.getStartTimestamp()) {
+ startTimestamp = batteryDiffData.getStartTimestamp();
+ startBatteryLevel = batteryDiffData.getStartBatteryLevel();
+ }
+ if (endTimestamp > batteryDiffData.getEndTimestamp()) {
+ endTimestamp = batteryDiffData.getEndTimestamp();
+ endBatteryLevel = batteryDiffData.getEndBatteryLevel();
+ }
totalScreenOnTime += batteryDiffData.getScreenOnTime();
for (BatteryDiffEntry entry : batteryDiffData.getAppDiffEntryList()) {
computeUsageDiffDataPerEntry(entry, diffEntryMap);
@@ -1554,8 +1563,9 @@ public final class DataProcessor {
}
}
- return diffEntryList.isEmpty() ? null : new BatteryDiffData(context, totalScreenOnTime,
- appEntries, systemEntries, /* systemAppsPackageNames= */ new ArraySet<>(),
+ return diffEntryList.isEmpty() ? null : new BatteryDiffData(context, startTimestamp,
+ endTimestamp, startBatteryLevel, endBatteryLevel, totalScreenOnTime, appEntries,
+ systemEntries, /* systemAppsPackageNames= */ new ArraySet<>(),
/* systemAppsUids= */ new ArraySet<>(), /* isAccumulated= */ true);
}
@@ -1751,22 +1761,6 @@ public final class DataProcessor {
return v2 > v1 ? v2 - v1 : 0;
}
- private static Set getSystemAppsPackageNames(Context context) {
- return sTestSystemAppsPackageNames != null ? sTestSystemAppsPackageNames
- : AppListRepositoryUtil.getSystemPackageNames(context, context.getUserId());
- }
-
- private static Set getSystemAppsUids(Context context) {
- Set result = new ArraySet<>();
- try {
- result.add(context.getPackageManager().getUidForSharedUser(
- ANDROID_CORE_APPS_SHARED_USER_ID));
- } catch (PackageManager.NameNotFoundException e) {
- // No Android Core Apps
- }
- return result;
- }
-
private static long getCurrentTimeMillis() {
return sTestCurrentTimeMillis > 0 ? sTestCurrentTimeMillis : System.currentTimeMillis();
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index b54563bd566..465afbe8c59 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -15,6 +15,8 @@
*/
package com.android.settings.fuelgauge.batteryusage;
+import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLocalTimeForLogging;
+
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageStatsManager;
import android.content.ContentResolver;
@@ -76,12 +78,20 @@ public final class DatabaseUtils {
public static final String BATTERY_EVENT_TABLE = "BatteryEvent";
/** A table name for battery usage history. */
public static final String BATTERY_STATE_TABLE = "BatteryState";
+ /** A table name for battery usage slot. */
+ public static final String BATTERY_USAGE_SLOT_TABLE = "BatteryUsageSlot";
+ /** A path name for last full charge time query. */
+ public static final String LAST_FULL_CHARGE_TIMESTAMP_PATH = "lastFullChargeTimestamp";
+ /** A path name for querying the latest record timestamp in battery state table. */
+ public static final String BATTERY_STATE_LATEST_TIMESTAMP_PATH = "batteryStateLatestTimestamp";
/** A path name for app usage latest timestamp query. */
public static final String APP_USAGE_LATEST_TIMESTAMP_PATH = "appUsageLatestTimestamp";
/** Key for query parameter timestamp used in BATTERY_CONTENT_URI **/
public static final String QUERY_KEY_TIMESTAMP = "timestamp";
/** Key for query parameter userid used in APP_USAGE_EVENT_URI **/
public static final String QUERY_KEY_USERID = "userid";
+ /** Key for query parameter battery event type used in BATTERY_EVENT_URI **/
+ public static final String QUERY_BATTERY_EVENT_TYPE = "batteryEventType";
public static final long INVALID_USER_ID = Integer.MIN_VALUE;
/**
@@ -111,6 +121,13 @@ public final class DatabaseUtils {
.authority(AUTHORITY)
.appendPath(BATTERY_STATE_TABLE)
.build();
+ /** A content URI to access battery usage slots data. */
+ public static final Uri BATTERY_USAGE_SLOT_URI =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendPath(BATTERY_USAGE_SLOT_TABLE)
+ .build();
// For testing only.
@VisibleForTesting
@@ -140,7 +157,7 @@ public final class DatabaseUtils {
.build();
final long latestTimestamp =
loadAppUsageLatestTimestampFromContentProvider(context, appUsageLatestTimestampUri);
- final String latestTimestampString = ConvertUtils.utcToLocalTimeForLogging(latestTimestamp);
+ final String latestTimestampString = utcToLocalTimeForLogging(latestTimestamp);
Log.d(TAG, String.format(
"getAppUsageStartTimestampOfUser() userId=%d latestTimestamp=%s in %d/ms",
userId, latestTimestampString, (System.currentTimeMillis() - startTime)));
@@ -161,8 +178,7 @@ public final class DatabaseUtils {
// sure the app usage calculation near the boundaries is correct.
final long queryTimestamp =
Math.max(rawStartTimestamp, sixDaysAgoTimestamp) - USAGE_QUERY_BUFFER_HOURS;
- Log.d(TAG, "sixDayAgoTimestamp: " + ConvertUtils.utcToLocalTimeForLogging(
- sixDaysAgoTimestamp));
+ Log.d(TAG, "sixDaysAgoTimestamp: " + utcToLocalTimeForLogging(sixDaysAgoTimestamp));
final String queryUserIdString = userIds.stream()
.map(userId -> String.valueOf(userId))
.collect(Collectors.joining(","));
@@ -189,11 +205,15 @@ public final class DatabaseUtils {
public static List getBatteryEvents(
Context context,
final Calendar calendar,
- final long rawStartTimestamp) {
+ final long rawStartTimestamp,
+ final List queryBatteryEventTypes) {
final long startTime = System.currentTimeMillis();
final long sixDaysAgoTimestamp = getTimestampSixDaysAgo(calendar);
final long queryTimestamp = Math.max(rawStartTimestamp, sixDaysAgoTimestamp);
Log.d(TAG, "getBatteryEvents for timestamp: " + queryTimestamp);
+ final String queryBatteryEventTypesString = queryBatteryEventTypes.stream()
+ .map(type -> String.valueOf(type.getNumber()))
+ .collect(Collectors.joining(","));
// Builds the content uri everytime to avoid cache.
final Uri batteryEventUri =
new Uri.Builder()
@@ -202,6 +222,8 @@ public final class DatabaseUtils {
.appendPath(BATTERY_EVENT_TABLE)
.appendQueryParameter(
QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+ .appendQueryParameter(
+ QUERY_BATTERY_EVENT_TYPE, queryBatteryEventTypesString)
.build();
final List batteryEventList =
@@ -211,13 +233,82 @@ public final class DatabaseUtils {
return batteryEventList;
}
- /** Long: for timestamp and String: for BatteryHistEntry.getKey() */
- public static Map> getHistoryMapSinceLastFullCharge(
- Context context, Calendar calendar) {
+ /**
+ * Returns the battery usage slot data after {@code rawStartTimestamp} in battery event table.
+ */
+ public static List getBatteryUsageSlots(
+ Context context,
+ final Calendar calendar,
+ final long rawStartTimestamp) {
final long startTime = System.currentTimeMillis();
final long sixDaysAgoTimestamp = getTimestampSixDaysAgo(calendar);
- Log.d(TAG, "sixDayAgoTimestamp: " + ConvertUtils.utcToLocalTimeForLogging(
- sixDaysAgoTimestamp));
+ final long queryTimestamp = Math.max(rawStartTimestamp, sixDaysAgoTimestamp);
+ Log.d(TAG, "getBatteryUsageSlots for timestamp: " + queryTimestamp);
+ // Builds the content uri everytime to avoid cache.
+ final Uri batteryUsageSlotUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendPath(BATTERY_USAGE_SLOT_TABLE)
+ .appendQueryParameter(
+ QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+ .build();
+
+ final List batteryUsageSlotList =
+ loadBatteryUsageSlotsFromContentProvider(context, batteryUsageSlotUri);
+ Log.d(TAG, String.format("getBatteryUsageSlots size=%d in %d/ms",
+ batteryUsageSlotList.size(), (System.currentTimeMillis() - startTime)));
+ return batteryUsageSlotList;
+ }
+
+ /** Returns the last full charge time. */
+ public static long getLastFullChargeTime(Context context) {
+ final long startTime = System.currentTimeMillis();
+ // Builds the content uri everytime to avoid cache.
+ final Uri lastFullChargeTimeUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendPath(LAST_FULL_CHARGE_TIMESTAMP_PATH)
+ .build();
+ final long lastFullChargeTime = loadLastFullChargeTimeFromContentProvider(
+ context, lastFullChargeTimeUri);
+ final String lastFullChargeTimeString = utcToLocalTimeForLogging(lastFullChargeTime);
+ Log.d(TAG, String.format(
+ "getLastFullChargeTime() lastFullChargeTime=%s in %d/ms",
+ lastFullChargeTimeString, (System.currentTimeMillis() - startTime)));
+ return lastFullChargeTime;
+ }
+
+ /** Returns the first battery state timestamp no later than the {@code queryTimestamp}. */
+ @VisibleForTesting
+ static long getBatteryStateLatestTimestampBeforeQueryTimestamp(
+ Context context, final long queryTimestamp) {
+ final long startTime = System.currentTimeMillis();
+ // Builds the content uri everytime to avoid cache.
+ final Uri batteryStateLatestTimestampUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendPath(BATTERY_STATE_LATEST_TIMESTAMP_PATH)
+ .appendQueryParameter(
+ QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+ .build();
+ final long batteryStateLatestTimestamp = loadBatteryStateLatestTimestampFromContentProvider(
+ context, batteryStateLatestTimestampUri);
+ final String batteryStateLatestTimestampString =
+ utcToLocalTimeForLogging(batteryStateLatestTimestamp);
+ Log.d(TAG, String.format(
+ "getBatteryStateLatestTimestamp() batteryStateLatestTimestamp=%s in %d/ms",
+ batteryStateLatestTimestampString, (System.currentTimeMillis() - startTime)));
+ return batteryStateLatestTimestamp;
+ }
+
+ /** Returns the battery history map after the given timestamp. */
+ @VisibleForTesting
+ static Map> getHistoryMapSinceQueryTimestamp(
+ Context context, final long queryTimestamp) {
+ final long startTime = System.currentTimeMillis();
// Builds the content uri everytime to avoid cache.
final Uri batteryStateUri =
new Uri.Builder()
@@ -225,20 +316,46 @@ public final class DatabaseUtils {
.authority(AUTHORITY)
.appendPath(BATTERY_STATE_TABLE)
.appendQueryParameter(
- QUERY_KEY_TIMESTAMP, Long.toString(sixDaysAgoTimestamp))
+ QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
.build();
final Map> resultMap =
loadHistoryMapFromContentProvider(context, batteryStateUri);
if (resultMap == null || resultMap.isEmpty()) {
- Log.d(TAG, "getHistoryMapSinceLastFullCharge() returns empty or null");
+ Log.d(TAG, "getBatteryHistoryMap() returns empty or null");
} else {
- Log.d(TAG, String.format("getHistoryMapSinceLastFullCharge() size=%d in %d/ms",
+ Log.d(TAG, String.format("getBatteryHistoryMap() size=%d in %d/ms",
resultMap.size(), (System.currentTimeMillis() - startTime)));
}
return resultMap;
}
+ /**
+ * Returns the battery history map since the latest record no later than the given timestamp.
+ * If there is no record before the given timestamp or the given timestamp is before last full
+ * charge time, returns the history map since last full charge time.
+ */
+ public static Map>
+ getHistoryMapSinceLatestRecordBeforeQueryTimestamp(Context context, Calendar calendar,
+ final long queryTimestamp, final long lastFullChargeTime) {
+ final long sixDaysAgoTimestamp = getTimestampSixDaysAgo(calendar);
+ Log.d(TAG, "sixDaysAgoTimestamp: " + utcToLocalTimeForLogging(sixDaysAgoTimestamp));
+ final long batteryStateLatestTimestamp =
+ queryTimestamp == 0L ? 0L : getBatteryStateLatestTimestampBeforeQueryTimestamp(
+ context, queryTimestamp);
+ final long maxTimestamp = Math.max(Math.max(
+ sixDaysAgoTimestamp, lastFullChargeTime), batteryStateLatestTimestamp);
+ return getHistoryMapSinceQueryTimestamp(context, maxTimestamp);
+ }
+
+ /** Returns the history map since last full charge time. */
+ public static Map> getHistoryMapSinceLastFullCharge(
+ Context context, Calendar calendar) {
+ final long lastFullChargeTime = getLastFullChargeTime(context);
+ return getHistoryMapSinceLatestRecordBeforeQueryTimestamp(
+ context, calendar, 0, lastFullChargeTime);
+ }
+
/** Clears all data in the battery usage database. */
public static void clearAll(Context context) {
AsyncTask.execute(() -> {
@@ -248,6 +365,7 @@ public final class DatabaseUtils {
database.appUsageEventDao().clearAll();
database.batteryEventDao().clearAll();
database.batteryStateDao().clearAll();
+ database.batteryUsageSlotDao().clearAll();
} catch (RuntimeException e) {
Log.e(TAG, "clearAll() failed", e);
}
@@ -265,6 +383,7 @@ public final class DatabaseUtils {
database.appUsageEventDao().clearAllBefore(earliestTimestamp);
database.batteryEventDao().clearAllBefore(earliestTimestamp);
database.batteryStateDao().clearAllBefore(earliestTimestamp);
+ database.batteryUsageSlotDao().clearAllBefore(earliestTimestamp);
} catch (RuntimeException e) {
Log.e(TAG, "clearAllBefore() failed", e);
}
@@ -293,7 +412,7 @@ public final class DatabaseUtils {
/*user=*/ context.getSystemService(UserManager.class)
.getProfileParent(context.getUser()));
} catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "context.createPackageContextAsUser() fail:" + e);
+ Log.e(TAG, "context.createPackageContextAsUser() fail:", e);
return null;
}
}
@@ -320,7 +439,7 @@ public final class DatabaseUtils {
resolver.notifyChange(APP_USAGE_EVENT_URI, /*observer=*/ null);
Log.d(TAG, "insert() app usage events data into database");
} catch (Exception e) {
- Log.e(TAG, "bulkInsert() app usage data into database error:\n" + e);
+ Log.e(TAG, "bulkInsert() app usage data into database error:", e);
}
}
Log.d(TAG, String.format("sendAppUsageEventData() size=%d in %d/ms",
@@ -346,8 +465,65 @@ public final class DatabaseUtils {
return contentValues;
}
+ static List sendBatteryEventData(
+ final Context context, final List batteryEventList) {
+ final long startTime = System.currentTimeMillis();
+ // Creates the ContentValues list to insert them into provider.
+ final List valuesList = new ArrayList<>();
+ batteryEventList.stream()
+ .forEach(batteryEvent -> valuesList.add(
+ ConvertUtils.convertBatteryEventToContentValues(batteryEvent)));
+ int size = 0;
+ final ContentResolver resolver = context.getContentResolver();
+ // Inserts all ContentValues into battery provider.
+ if (!valuesList.isEmpty()) {
+ final ContentValues[] valuesArray = new ContentValues[valuesList.size()];
+ valuesList.toArray(valuesArray);
+ try {
+ size = resolver.bulkInsert(BATTERY_EVENT_URI, valuesArray);
+ resolver.notifyChange(BATTERY_EVENT_URI, /*observer=*/ null);
+ Log.d(TAG, "insert() battery event data into database");
+ } catch (Exception e) {
+ Log.e(TAG, "bulkInsert() battery event data into database error:", e);
+ }
+ }
+ Log.d(TAG, String.format("sendBatteryEventData() size=%d in %d/ms",
+ size, (System.currentTimeMillis() - startTime)));
+ clearMemory();
+ return valuesList;
+ }
+
+ static List sendBatteryUsageSlotData(
+ final Context context, final List batteryUsageSlotList) {
+ final long startTime = System.currentTimeMillis();
+ // Creates the ContentValues list to insert them into provider.
+ final List valuesList = new ArrayList<>();
+ batteryUsageSlotList.stream()
+ .forEach(batteryUsageSlot -> valuesList.add(
+ ConvertUtils.convertBatteryUsageSlotToContentValues(batteryUsageSlot)));
+ int size = 0;
+ final ContentResolver resolver = context.getContentResolver();
+ // Inserts all ContentValues into battery provider.
+ if (!valuesList.isEmpty()) {
+ final ContentValues[] valuesArray = new ContentValues[valuesList.size()];
+ valuesList.toArray(valuesArray);
+ try {
+ size = resolver.bulkInsert(BATTERY_USAGE_SLOT_URI, valuesArray);
+ resolver.notifyChange(BATTERY_USAGE_SLOT_URI, /*observer=*/ null);
+ Log.d(TAG, "insert() battery usage slots data into database");
+ } catch (Exception e) {
+ Log.e(TAG, "bulkInsert() battery usage slots data into database error:", e);
+ }
+ }
+ Log.d(TAG, String.format("sendBatteryUsageSlotData() size=%d in %d/ms",
+ size, (System.currentTimeMillis() - startTime)));
+ clearMemory();
+ return valuesList;
+ }
+
static List sendBatteryEntryData(
final Context context,
+ final long snapshotTimestamp,
final List batteryEntryList,
final BatteryUsageStats batteryUsageStats,
final boolean isFullChargeStart) {
@@ -364,7 +540,6 @@ public final class DatabaseUtils {
final int batteryHealth = intent.getIntExtra(
BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN);
// We should use the same timestamp for each data snapshot.
- final long snapshotTimestamp = Clock.systemUTC().millis();
final long snapshotBootTimestamp = SystemClock.elapsedRealtime();
// Creates the ContentValues list to insert them into provider.
@@ -409,8 +584,7 @@ public final class DatabaseUtils {
Log.d(TAG, "insert() battery states data into database with isFullChargeStart:"
+ isFullChargeStart);
} catch (Exception e) {
- errorMessage = e.toString();
- Log.e(TAG, "bulkInsert() data into database error:\n" + errorMessage);
+ Log.e(TAG, "bulkInsert() data into database error:", e);
}
} else {
// Inserts one fake data into battery provider.
@@ -430,8 +604,7 @@ public final class DatabaseUtils {
+ isFullChargeStart);
} catch (Exception e) {
- errorMessage = e.toString();
- Log.e(TAG, "insert() data into database error:\n" + errorMessage);
+ Log.e(TAG, "insert() data into database error:", e);
}
valuesList.add(contentValues);
}
@@ -504,8 +677,7 @@ public final class DatabaseUtils {
static void recordDateTime(Context context, String preferenceKey) {
final SharedPreferences sharedPreferences = getSharedPreferences(context);
if (sharedPreferences != null) {
- final String currentTime = ConvertUtils.utcToLocalTimeForLogging(
- System.currentTimeMillis());
+ final String currentTime = utcToLocalTimeForLogging(System.currentTimeMillis());
sharedPreferences.edit().putString(preferenceKey, currentTime).apply();
}
}
@@ -533,11 +705,6 @@ public final class DatabaseUtils {
cursor.moveToFirst();
// There is only one column returned so use the index 0 directly.
final long latestTimestamp = cursor.getLong(/*columnIndex=*/ 0);
- try {
- cursor.close();
- } catch (Exception e) {
- Log.e(TAG, "cursor.close() failed", e);
- }
// If there is no data for this user, 0 will be returned from the database.
return latestTimestamp == 0 ? INVALID_USER_ID : latestTimestamp;
}
@@ -556,14 +723,9 @@ public final class DatabaseUtils {
if (cursor == null || cursor.getCount() == 0) {
return appUsageEventList;
}
- // Loads and recovers all AppUsageEvent data from cursor.
+ // Loads and converts all AppUsageEvent data from cursor.
while (cursor.moveToNext()) {
- appUsageEventList.add(ConvertUtils.convertToAppUsageEventFromCursor(cursor));
- }
- try {
- cursor.close();
- } catch (Exception e) {
- Log.e(TAG, "cursor.close() failed", e);
+ appUsageEventList.add(ConvertUtils.convertToAppUsageEvent(cursor));
}
}
return appUsageEventList;
@@ -582,19 +744,71 @@ public final class DatabaseUtils {
if (cursor == null || cursor.getCount() == 0) {
return batteryEventList;
}
- // Loads and recovers all AppUsageEvent data from cursor.
+ // Loads and converts all AppUsageEvent data from cursor.
while (cursor.moveToNext()) {
- batteryEventList.add(ConvertUtils.convertToBatteryEventFromCursor(cursor));
- }
- try {
- cursor.close();
- } catch (Exception e) {
- Log.e(TAG, "cursor.close() failed", e);
+ batteryEventList.add(ConvertUtils.convertToBatteryEvent(cursor));
}
}
return batteryEventList;
}
+ private static List loadBatteryUsageSlotsFromContentProvider(
+ Context context, Uri batteryUsageSlotUri) {
+ final List batteryUsageSlotList = new ArrayList<>();
+ context = getParentContext(context);
+ if (context == null) {
+ return batteryUsageSlotList;
+ }
+ try (Cursor cursor = sFakeSupplier != null
+ ? sFakeSupplier.get()
+ : context.getContentResolver().query(batteryUsageSlotUri, null, null, null)) {
+ if (cursor == null || cursor.getCount() == 0) {
+ return batteryUsageSlotList;
+ }
+ // Loads and converts all AppUsageEvent data from cursor.
+ while (cursor.moveToNext()) {
+ batteryUsageSlotList.add(ConvertUtils.convertToBatteryUsageSlot(cursor));
+ }
+ }
+ return batteryUsageSlotList;
+ }
+
+ private static long loadLastFullChargeTimeFromContentProvider(
+ Context context, final Uri lastFullChargeTimeUri) {
+ // We have already make sure the context here is with profile parent's user identity. Don't
+ // need to check whether current user is work profile.
+ try (Cursor cursor = sFakeSupplier != null
+ ? sFakeSupplier.get()
+ : context.getContentResolver().query(
+ lastFullChargeTimeUri, null, null, null)) {
+ if (cursor == null || cursor.getCount() == 0) {
+ return 0L;
+ }
+ cursor.moveToFirst();
+ // There is only one column returned so use the index 0 directly.
+ final long lastFullChargeTime = cursor.getLong(/*columnIndex=*/ 0);
+ return lastFullChargeTime;
+ }
+ }
+
+ private static long loadBatteryStateLatestTimestampFromContentProvider(
+ Context context, final Uri batteryStateLatestTimestampUri) {
+ // We have already make sure the context here is with profile parent's user identity. Don't
+ // need to check whether current user is work profile.
+ try (Cursor cursor = sFakeSupplier != null
+ ? sFakeSupplier.get()
+ : context.getContentResolver().query(
+ batteryStateLatestTimestampUri, null, null, null)) {
+ if (cursor == null || cursor.getCount() == 0) {
+ return 0L;
+ }
+ cursor.moveToFirst();
+ // There is only one column returned so use the index 0 directly.
+ final long batteryStateLatestTimestamp = cursor.getLong(/*columnIndex=*/ 0);
+ return batteryStateLatestTimestamp;
+ }
+ }
+
private static Map> loadHistoryMapFromContentProvider(
Context context, Uri batteryStateUri) {
context = getParentContext(context);
@@ -607,7 +821,7 @@ public final class DatabaseUtils {
if (cursor == null || cursor.getCount() == 0) {
return resultMap;
}
- // Loads and recovers all BatteryHistEntry data from cursor.
+ // Loads and converts all BatteryHistEntry data from cursor.
while (cursor.moveToNext()) {
final BatteryHistEntry entry = new BatteryHistEntry(cursor);
final long timestamp = entry.mTimestamp;
@@ -620,11 +834,6 @@ public final class DatabaseUtils {
}
batteryHistEntryMap.put(key, entry);
}
- try {
- cursor.close();
- } catch (Exception e) {
- Log.e(TAG, "cursor.close() failed", e);
- }
}
return resultMap;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java
index 2bd04669b31..2371a19f85c 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java
@@ -44,7 +44,6 @@ public final class PeriodicJobReceiver extends BroadcastReceiver {
}
BatteryUsageLogUtils.writeLog(context, Action.EXECUTE_JOB, "");
BatteryUsageDataLoader.enqueueWork(context, /*isFullChargeStart=*/ false);
- AppUsageDataLoader.enqueueWork(context);
Log.d(TAG, "refresh periodic job from action=" + action);
PeriodicJobManager.getInstance(context).refreshJob(/*fromBoot=*/ false);
DatabaseUtils.clearExpiredDataIfNeeded(context);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
index 5a96fb40abc..f13f34c906e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
@@ -21,12 +21,13 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.provider.SearchIndexableResource;
import android.util.Log;
-import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
@@ -39,11 +40,13 @@ import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.utils.AsyncLoaderCompat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
/** Advanced power usage. */
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
@@ -55,16 +58,17 @@ public class PowerUsageAdvanced extends PowerUsageBase {
@VisibleForTesting
BatteryHistoryPreference mHistPref;
@VisibleForTesting
- Map> mBatteryHistoryMap;
- @VisibleForTesting
- final BatteryHistoryLoaderCallbacks mBatteryHistoryLoaderCallbacks =
- new BatteryHistoryLoaderCallbacks();
+ final BatteryLevelDataLoaderCallbacks mBatteryLevelDataLoaderCallbacks =
+ new BatteryLevelDataLoaderCallbacks();
private boolean mIsChartDataLoaded = false;
+ private long mResumeTimestamp;
private BatteryChartPreferenceController mBatteryChartPreferenceController;
+ private Optional mBatteryLevelData;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
private final ContentObserver mBatteryObserver =
- new ContentObserver(new Handler()) {
+ new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
Log.d(TAG, "onBatteryContentChange: " + selfChange);
@@ -79,6 +83,7 @@ public class PowerUsageAdvanced extends PowerUsageBase {
super.onCreate(icicle);
mHistPref = findPreference(KEY_BATTERY_CHART);
setBatteryChartPreferenceController();
+ AsyncTask.execute(() -> BootBroadcastReceiver.invokeJobRecheck(getContext()));
}
@Override
@@ -109,6 +114,7 @@ public class PowerUsageAdvanced extends PowerUsageBase {
super.onPause();
// Resets the flag to reload usage data in onResume() callback.
mIsChartDataLoaded = false;
+ mBatteryLevelData = null;
final Uri uri = DatabaseUtils.BATTERY_CONTENT_URI;
if (uri != null) {
getContext().getContentResolver().unregisterContentObserver(mBatteryObserver);
@@ -118,6 +124,7 @@ public class PowerUsageAdvanced extends PowerUsageBase {
@Override
public void onResume() {
super.onResume();
+ mResumeTimestamp = System.currentTimeMillis();
final Uri uri = DatabaseUtils.BATTERY_CONTENT_URI;
if (uri != null) {
getContext().getContentResolver().registerContentObserver(
@@ -158,21 +165,9 @@ public class PowerUsageAdvanced extends PowerUsageBase {
return controllers;
}
- @Override
- protected boolean isBatteryHistoryNeeded() {
- return true;
- }
-
@Override
protected void refreshUi(@BatteryUpdateType int refreshType) {
- final Context context = getContext();
- if (context == null) {
- return;
- }
- updatePreference(mHistPref);
- if (mBatteryChartPreferenceController != null && mBatteryHistoryMap != null) {
- mBatteryChartPreferenceController.setBatteryHistoryMap(mBatteryHistoryMap);
- }
+ // Do nothing
}
@Override
@@ -181,11 +176,32 @@ public class PowerUsageAdvanced extends PowerUsageBase {
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
if (!mIsChartDataLoaded) {
mIsChartDataLoaded = true;
- restartLoader(LoaderIndex.BATTERY_HISTORY_LOADER, bundle,
- mBatteryHistoryLoaderCallbacks);
+ restartLoader(LoaderIndex.BATTERY_LEVEL_DATA_LOADER, bundle,
+ mBatteryLevelDataLoaderCallbacks);
}
}
+ private void onBatteryLevelDataUpdate(BatteryLevelData batteryLevelData) {
+ mBatteryLevelData = Optional.ofNullable(batteryLevelData);
+ if (mBatteryChartPreferenceController != null) {
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(batteryLevelData);
+ Log.d(TAG, String.format("Battery chart shows in %d millis",
+ System.currentTimeMillis() - mResumeTimestamp));
+ }
+ }
+
+ private void onBatteryDiffDataMapUpdate(Map batteryDiffDataMap) {
+ if (mBatteryLevelData != null && mBatteryChartPreferenceController != null) {
+ Map> batteryUsageMap =
+ DataProcessor.generateBatteryUsageMap(
+ getContext(), batteryDiffDataMap, mBatteryLevelData.orElse(null));
+ DataProcessor.loadLabelAndIcon(batteryUsageMap);
+ mBatteryChartPreferenceController.onBatteryUsageMapUpdate(batteryUsageMap);
+ }
+ Log.d(TAG, String.format("Battery usage list shows in %d millis",
+ System.currentTimeMillis() - mResumeTimestamp));
+ }
+
private void setBatteryChartPreferenceController() {
if (mHistPref != null && mBatteryChartPreferenceController != null) {
mHistPref.setChartPreferenceController(mBatteryChartPreferenceController);
@@ -216,28 +232,31 @@ public class PowerUsageAdvanced extends PowerUsageBase {
}
};
- private class BatteryHistoryLoaderCallbacks
- implements LoaderManager.LoaderCallbacks>> {
- private int mRefreshType;
-
+ private class BatteryLevelDataLoaderCallbacks
+ implements LoaderManager.LoaderCallbacks {
@Override
- @NonNull
- public Loader>> onCreateLoader(
- int id, Bundle bundle) {
- mRefreshType = bundle.getInt(KEY_REFRESH_TYPE);
- return new BatteryHistoryLoader(getContext());
+ public Loader onCreateLoader(int id, Bundle bundle) {
+ return new AsyncLoaderCompat(getContext().getApplicationContext()) {
+ @Override
+ protected void onDiscardResult(BatteryLevelData result) {}
+
+ @Override
+ public BatteryLevelData loadInBackground() {
+ return DataProcessManager.getBatteryLevelData(
+ getContext(), mHandler, /*isFromPeriodJob=*/ false,
+ map -> PowerUsageAdvanced.this.onBatteryDiffDataMapUpdate(map));
+ }
+ };
}
@Override
- public void onLoadFinished(Loader>> loader,
- Map> batteryHistoryMap) {
- mBatteryHistoryMap = batteryHistoryMap;
- PowerUsageAdvanced.this.onLoadFinished(mRefreshType);
+ public void onLoadFinished(Loader loader,
+ BatteryLevelData batteryLevelData) {
+ PowerUsageAdvanced.this.onBatteryLevelDataUpdate(batteryLevelData);
}
@Override
- public void onLoaderReset(Loader>> loader) {
+ public void onLoaderReset(Loader loader) {
}
}
-
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java
index ed3a9215352..22856b60d86 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java
@@ -32,7 +32,6 @@ import androidx.loader.content.Loader;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
-import com.android.settings.fuelgauge.BatteryUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -63,14 +62,14 @@ public abstract class PowerUsageBase extends DashboardFragment {
LoaderIndex.BATTERY_USAGE_STATS_LOADER,
LoaderIndex.BATTERY_INFO_LOADER,
LoaderIndex.BATTERY_TIP_LOADER,
- LoaderIndex.BATTERY_HISTORY_LOADER
+ LoaderIndex.BATTERY_LEVEL_DATA_LOADER
})
public @interface LoaderIndex {
int BATTERY_USAGE_STATS_LOADER = 0;
int BATTERY_INFO_LOADER = 1;
int BATTERY_TIP_LOADER = 2;
- int BATTERY_HISTORY_LOADER = 3;
+ int BATTERY_LEVEL_DATA_LOADER = 3;
}
@Override
@@ -108,7 +107,7 @@ public abstract class PowerUsageBase extends DashboardFragment {
protected void restartBatteryStatsLoader(int refreshType) {
final Bundle bundle = new Bundle();
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
- bundle.putBoolean(KEY_INCLUDE_HISTORY, isBatteryHistoryNeeded());
+ bundle.putBoolean(KEY_INCLUDE_HISTORY, false);
restartLoader(LoaderIndex.BATTERY_USAGE_STATS_LOADER, bundle,
mBatteryUsageStatsLoaderCallbacks);
}
@@ -137,14 +136,6 @@ public abstract class PowerUsageBase extends DashboardFragment {
protected abstract void refreshUi(@BatteryUpdateType int refreshType);
- protected abstract boolean isBatteryHistoryNeeded();
-
- protected void updatePreference(BatteryHistoryPreference historyPref) {
- final long startTime = System.currentTimeMillis();
- historyPref.setBatteryUsageStats(mBatteryUsageStats);
- BatteryUtils.logRuntime(TAG, "updatePreference", startTime);
- }
-
private class BatteryUsageStatsLoaderCallbacks
implements LoaderManager.LoaderCallbacks {
private int mRefreshType;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
index a0c5843988a..e93fb624186 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
@@ -45,7 +45,6 @@ import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.widget.LayoutPreference;
import java.util.List;
@@ -69,8 +68,6 @@ public class PowerUsageSummary extends PowerUsageBase implements
@VisibleForTesting
BatteryUtils mBatteryUtils;
@VisibleForTesting
- LayoutPreference mBatteryLayoutPref;
- @VisibleForTesting
BatteryInfo mBatteryInfo;
@VisibleForTesting
@@ -208,11 +205,6 @@ public class PowerUsageSummary extends PowerUsageBase implements
return R.string.help_url_battery;
}
- @Override
- protected boolean isBatteryHistoryNeeded() {
- return false;
- }
-
protected void refreshUi(@BatteryUpdateType int refreshType) {
final Context context = getContext();
if (context == null) {
@@ -239,11 +231,6 @@ public class PowerUsageSummary extends PowerUsageBase implements
restartLoader(LoaderIndex.BATTERY_TIP_LOADER, Bundle.EMPTY, mBatteryTipsCallbacks);
}
- @VisibleForTesting
- void setBatteryLayoutPreference(LayoutPreference layoutPreference) {
- mBatteryLayoutPref = layoutPreference;
- }
-
@VisibleForTesting
void initFeatureProvider() {
mPowerFeatureProvider = FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
index a638d094519..0a6de712e2d 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
@@ -36,9 +36,16 @@ public interface BatteryEventDao {
@Query("SELECT * FROM BatteryEventEntity ORDER BY timestamp DESC")
List getAll();
+ /** Gets the {@link Cursor} of the last full charge time . */
+ @Query("SELECT MAX(timestamp) FROM BatteryEventEntity"
+ + " WHERE batteryEventType = 3") // BatteryEventType.FULL_CHARGED = 3
+ Cursor getLastFullChargeTimestamp();
+
/** Gets the {@link Cursor} of all recorded data after a specific timestamp. */
- @Query("SELECT * FROM BatteryEventEntity WHERE timestamp > :timestamp ORDER BY timestamp DESC")
- Cursor getAllAfter(long timestamp);
+ @Query("SELECT * FROM BatteryEventEntity"
+ + " WHERE timestamp > :timestamp AND batteryEventType IN (:batteryEventTypes)"
+ + " ORDER BY timestamp DESC")
+ Cursor getAllAfter(long timestamp, List batteryEventTypes);
/** Deletes all recorded data before a specific timestamp. */
@Query("DELETE FROM BatteryEventEntity WHERE timestamp <= :timestamp")
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
index 6d2ab8d3c26..520c6bed484 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
@@ -37,16 +37,18 @@ public interface BatteryStateDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List states);
+ /** Gets the {@link Cursor} of the latest record timestamp no later than the given timestamp. */
+ @Query("SELECT MAX(timestamp) FROM BatteryState WHERE timestamp <= :timestamp")
+ Cursor getLatestTimestampBefore(long timestamp);
+
+ /** Lists all recorded battery states after a specific timestamp. */
+ @Query("SELECT * FROM BatteryState WHERE timestamp >= :timestamp ORDER BY timestamp ASC")
+ Cursor getBatteryStatesAfter(long timestamp);
+
/** Lists all recorded data after a specific timestamp. */
@Query("SELECT * FROM BatteryState WHERE timestamp > :timestamp ORDER BY timestamp DESC")
List getAllAfter(long timestamp);
- /** Gets the {@link Cursor} of all recorded data since last full charge within 7 days. */
- @Query("SELECT * FROM BatteryState WHERE timestamp >= :timestampSixDaysAgo AND timestamp >= "
- + "(SELECT IFNULL((SELECT MAX(timestamp) FROM BatteryState "
- + "WHERE isFullChargeCycleStart = 1), 0)) ORDER BY timestamp ASC")
- Cursor getCursorSinceLastFullCharge(long timestampSixDaysAgo);
-
/** Get the count of distinct timestamp after a specific timestamp. */
@Query("SELECT COUNT(DISTINCT timestamp) FROM BatteryState WHERE timestamp > :timestamp")
int getDistinctTimestampCount(long timestamp);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDatabase.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDatabase.java
index 466a7ca4740..28a0012234a 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDatabase.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDatabase.java
@@ -25,7 +25,8 @@ import androidx.room.RoomDatabase;
/** A {@link RoomDatabase} for battery usage states history. */
@Database(
- entities = {AppUsageEventEntity.class, BatteryEventEntity.class, BatteryState.class},
+ entities = {AppUsageEventEntity.class, BatteryEventEntity.class, BatteryState.class,
+ BatteryUsageSlotEntity.class},
version = 1)
public abstract class BatteryStateDatabase extends RoomDatabase {
private static final String TAG = "BatteryStateDatabase";
@@ -38,13 +39,15 @@ public abstract class BatteryStateDatabase extends RoomDatabase {
public abstract BatteryEventDao batteryEventDao();
/** Provides DAO for battery state table. */
public abstract BatteryStateDao batteryStateDao();
+ /** Provides DAO for battery usage slot table. */
+ public abstract BatteryUsageSlotDao batteryUsageSlotDao();
/** Gets or creates an instance of {@link RoomDatabase}. */
public static BatteryStateDatabase getInstance(Context context) {
if (sBatteryStateDatabase == null) {
sBatteryStateDatabase =
Room.databaseBuilder(
- context, BatteryStateDatabase.class, "battery-usage-db-v8")
+ context, BatteryStateDatabase.class, "battery-usage-db-v9")
// Allows accessing data in the main thread for dumping bugreport.
.allowMainThreadQueries()
.fallbackToDestructiveMigration()
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
new file mode 100644
index 00000000000..a695f6ab75e
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage.db;
+
+import android.database.Cursor;
+
+import androidx.room.Dao;
+import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
+import androidx.room.Query;
+
+import java.util.List;
+
+/** Data access object for accessing {@link BatteryUsageSlotEntity} in the database. */
+@Dao
+public interface BatteryUsageSlotDao {
+ /** Inserts a {@link BatteryUsageSlotEntity} data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ void insert(BatteryUsageSlotEntity event);
+
+ /** Gets all recorded data. */
+ @Query("SELECT * FROM BatteryUsageSlotEntity ORDER BY timestamp ASC")
+ List getAll();
+
+ /** Gets the {@link Cursor} of all recorded data after a specific timestamp. */
+ @Query("SELECT * FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp"
+ + " ORDER BY timestamp ASC")
+ Cursor getAllAfter(long timestamp);
+
+ /** Deletes all recorded data before a specific timestamp. */
+ @Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp <= :timestamp")
+ void clearAllBefore(long timestamp);
+
+ /** Clears all recorded data in the database. */
+ @Query("DELETE FROM BatteryUsageSlotEntity")
+ void clearAll();
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotEntity.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotEntity.java
new file mode 100644
index 00000000000..c2d5631aae8
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotEntity.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage.db;
+
+import android.content.ContentValues;
+
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
+
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+
+import java.util.Locale;
+
+/** A {@link Entity} class to save battery usage slot into database. */
+@Entity
+public class BatteryUsageSlotEntity {
+ /** Keys for accessing {@link ContentValues}. */
+ public static final String KEY_TIMESTAMP = "timestamp";
+ public static final String KEY_BATTERY_USAGE_SLOT = "batteryUsageSlot";
+
+ @PrimaryKey(autoGenerate = true)
+ private long mId;
+
+ public final long timestamp;
+ public final String batteryUsageSlot;
+
+ public BatteryUsageSlotEntity(final long timestamp, final String batteryUsageSlot) {
+ this.timestamp = timestamp;
+ this.batteryUsageSlot = batteryUsageSlot;
+ }
+
+ /** Sets the auto-generated content ID. */
+ public void setId(long id) {
+ this.mId = id;
+ }
+
+ /** Gets the auto-generated content ID. */
+ public long getId() {
+ return mId;
+ }
+
+ @Override
+ public String toString() {
+ final String recordAtDateTime = ConvertUtils.utcToLocalTimeForLogging(timestamp);
+ final StringBuilder builder = new StringBuilder()
+ .append("\nBatteryUsageSlot{")
+ .append(String.format(Locale.US, "\n\ttimestamp=%s|batteryUsageSlot=%s",
+ recordAtDateTime, batteryUsageSlot))
+ .append("\n}");
+ return builder.toString();
+ }
+
+ /** Creates new {@link BatteryUsageSlotEntity} from {@link ContentValues}. */
+ public static BatteryUsageSlotEntity create(ContentValues contentValues) {
+ Builder builder = BatteryUsageSlotEntity.newBuilder();
+ if (contentValues.containsKey(KEY_TIMESTAMP)) {
+ builder.setTimestamp(contentValues.getAsLong(KEY_TIMESTAMP));
+ }
+ if (contentValues.containsKey(KEY_BATTERY_USAGE_SLOT)) {
+ builder.setBatteryUsageSlot(contentValues.getAsString(KEY_BATTERY_USAGE_SLOT));
+ }
+ return builder.build();
+ }
+
+ /** Creates a new {@link Builder} instance. */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /** A convenience builder class to improve readability. */
+ public static class Builder {
+ private long mTimestamp;
+ private String mBatteryUsageSlot;
+
+ /** Sets the timestamp. */
+ @CanIgnoreReturnValue
+ public Builder setTimestamp(final long timestamp) {
+ mTimestamp = timestamp;
+ return this;
+ }
+
+ /** Sets the battery usage slot. */
+ @CanIgnoreReturnValue
+ public Builder setBatteryUsageSlot(final String batteryUsageSlot) {
+ mBatteryUsageSlot = batteryUsageSlot;
+ return this;
+ }
+
+ /** Builds the {@link BatteryUsageSlotEntity}. */
+ public BatteryUsageSlotEntity build() {
+ return new BatteryUsageSlotEntity(mTimestamp, mBatteryUsageSlot);
+ }
+
+ private Builder() {}
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/protos/Android.bp b/src/com/android/settings/fuelgauge/protos/Android.bp
index 1f3cdd98b02..531bdc32293 100644
--- a/src/com/android/settings/fuelgauge/protos/Android.bp
+++ b/src/com/android/settings/fuelgauge/protos/Android.bp
@@ -23,6 +23,14 @@ java_library {
srcs: ["battery_event.proto"],
}
+java_library {
+ name: "battery-usage-slot-protos-lite",
+ proto: {
+ type: "lite",
+ },
+ srcs: ["battery_usage_slot.proto"],
+}
+
java_library {
name: "fuelgauge-usage-state-protos-lite",
proto: {
diff --git a/src/com/android/settings/fuelgauge/protos/battery_event.proto b/src/com/android/settings/fuelgauge/protos/battery_event.proto
index 80ccb3b24f4..58ab3be2409 100644
--- a/src/com/android/settings/fuelgauge/protos/battery_event.proto
+++ b/src/com/android/settings/fuelgauge/protos/battery_event.proto
@@ -8,6 +8,8 @@ enum BatteryEventType {
UNKNOWN_EVENT = 0;
POWER_CONNECTED = 1;
POWER_DISCONNECTED = 2;
+ FULL_CHARGED = 3;
+ EVEN_HOUR = 4;
}
message BatteryEvent {
diff --git a/src/com/android/settings/fuelgauge/protos/battery_usage_slot.proto b/src/com/android/settings/fuelgauge/protos/battery_usage_slot.proto
new file mode 100644
index 00000000000..e3b604ba0a7
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/protos/battery_usage_slot.proto
@@ -0,0 +1,32 @@
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "com.android.settings.fuelgauge.batteryusage";
+option java_outer_classname = "BatteryUsageSlotProto";
+
+message BatteryUsageSlot {
+ optional int64 start_timestamp = 1;
+ optional int64 end_timestamp = 2;
+ optional int32 start_battery_level = 3;
+ optional int32 end_battery_level = 4;
+ optional int64 screen_on_time = 5;
+ repeated BatteryUsageDiff app_usage = 6;
+ repeated BatteryUsageDiff system_usage = 7;
+}
+
+message BatteryUsageDiff {
+ optional int64 uid = 1;
+ optional int64 user_id = 2;
+ optional string package_name = 3;
+ optional string label = 4;
+ optional string key = 5;
+ optional bool is_hidden = 6;
+ optional int32 component_id = 7;
+ optional int32 consumer_type = 8;
+ optional double consume_power = 9;
+ optional double foreground_usage_consume_power = 10;
+ optional double background_usage_consume_power = 11;
+ optional int64 foreground_usage_time = 12;
+ optional int64 background_usage_time = 13;
+ optional int64 screen_on_time = 14;
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/AppUsageDataLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/AppUsageDataLoaderTest.java
deleted file mode 100644
index 4b250a3dd12..00000000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/AppUsageDataLoaderTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.fuelgauge.batteryusage;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.UserManager;
-
-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;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public final class AppUsageDataLoaderTest {
- private Context mContext;
- @Mock
- private ContentResolver mMockContentResolver;
- @Mock
- private UserManager mUserManager;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application);
- doReturn(mContext).when(mContext).getApplicationContext();
- doReturn(mMockContentResolver).when(mContext).getContentResolver();
- doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
- doReturn(new Intent()).when(mContext).registerReceiver(any(), any());
- }
-
- @Test
- public void loadAppUsageData_withData_insertFakeDataIntoProvider() {
- final List AppUsageEventList = new ArrayList<>();
- final AppUsageEvent appUsageEvent = AppUsageEvent.newBuilder().setUid(0).build();
- AppUsageEventList.add(appUsageEvent);
- AppUsageDataLoader.sFakeAppUsageEventsSupplier = () -> new HashMap<>();
- AppUsageDataLoader.sFakeUsageEventsListSupplier = () -> AppUsageEventList;
-
- AppUsageDataLoader.loadAppUsageData(mContext);
-
- verify(mMockContentResolver).bulkInsert(any(), any());
- verify(mMockContentResolver).notifyChange(any(), any());
- }
-
- @Test
- public void loadAppUsageData_nullAppUsageEvents_notInsertDataIntoProvider() {
- AppUsageDataLoader.sFakeAppUsageEventsSupplier = () -> null;
-
- AppUsageDataLoader.loadAppUsageData(mContext);
-
- verifyNoMoreInteractions(mMockContentResolver);
- }
-
- @Test
- public void loadAppUsageData_nullUsageEventsList_notInsertDataIntoProvider() {
- AppUsageDataLoader.sFakeAppUsageEventsSupplier = () -> new HashMap<>();
- AppUsageDataLoader.sFakeUsageEventsListSupplier = () -> null;
-
- AppUsageDataLoader.loadAppUsageData(mContext);
-
- verifyNoMoreInteractions(mMockContentResolver);
- }
-
- @Test
- public void loadAppUsageData_emptyUsageEventsList_notInsertDataIntoProvider() {
- AppUsageDataLoader.sFakeAppUsageEventsSupplier = () -> new HashMap<>();
- AppUsageDataLoader.sFakeUsageEventsListSupplier = () -> new ArrayList<>();
-
- AppUsageDataLoader.loadAppUsageData(mContext);
-
- verifyNoMoreInteractions(mMockContentResolver);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index e1c193cf004..a54d4c174d7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.fuelgauge.batteryusage;
+import static com.android.settings.fuelgauge.batteryusage.BatteryChartViewModel.SELECTED_INDEX_ALL;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -30,7 +32,6 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -39,6 +40,7 @@ import android.os.Bundle;
import android.os.LocaleList;
import android.os.UserManager;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.LinearLayout;
@@ -54,7 +56,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -112,6 +113,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mPrefContext = mContext;
mBatteryChartPreferenceController.mDailyChartView = mDailyChartView;
mBatteryChartPreferenceController.mHourlyChartView = mHourlyChartView;
+ BatteryDiffEntry.clearCache();
// Adds fake testing data.
BatteryDiffEntry.sResourceCache.put(
"fakeBatteryDiffEntryKey",
@@ -144,7 +146,7 @@ public final class BatteryChartPreferenceControllerTest {
reset(mHourlyChartView);
setupHourlyChartViewAnimationMock();
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
// Ignore fast refresh ui from the data processor callback.
@@ -176,16 +178,18 @@ public final class BatteryChartPreferenceControllerTest {
BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS,
mBatteryChartPreferenceController.mDailyChartLabelTextGenerator);
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+ mBatteryChartPreferenceController.onBatteryUsageMapUpdate(getEmptyBatteryUsageMap());
verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
verify(mViewPropertyAnimator, atLeastOnce()).alpha(0f);
- verify(mDailyChartView).setViewModel(expectedDailyViewModel);
+ verify(mDailyChartView, atLeastOnce()).setViewModel(expectedDailyViewModel);
reset(mDailyChartView);
reset(mHourlyChartView);
setupHourlyChartViewAnimationMock();
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
+ doReturn(View.GONE).when(mHourlyChartView).getVisibility();
mBatteryChartPreferenceController.mDailyChartIndex = 0;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
@@ -245,8 +249,7 @@ public final class BatteryChartPreferenceControllerTest {
setupHourlyChartViewAnimationMock();
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
mBatteryChartPreferenceController.mDailyChartIndex = 2;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
verify(mViewPropertyAnimator, atLeastOnce()).alpha(1f);
@@ -272,13 +275,15 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void refreshUi_normalCase_returnTrue() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
+ mBatteryChartPreferenceController.onBatteryUsageMapUpdate(getEmptyBatteryUsageMap());
assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
}
@Test
public void refreshUi_batteryIndexedMapIsNull_returnTrue() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(null);
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(null);
+ mBatteryChartPreferenceController.onBatteryUsageMapUpdate(getEmptyBatteryUsageMap());
assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
}
@@ -296,38 +301,34 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void selectedSlotText_selectAllDaysAllHours_returnNull() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
- mBatteryChartPreferenceController.mDailyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
+ mBatteryChartPreferenceController.mDailyChartIndex = SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(null);
}
@Test
public void selectedSlotText_onlyOneDayDataSelectAllHours_returnNull() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
mBatteryChartPreferenceController.mDailyChartIndex = 0;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(null);
}
@Test
public void selectedSlotText_selectADayAllHours_onlyDayText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
mBatteryChartPreferenceController.mDailyChartIndex = 1;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo("Sunday");
}
@Test
public void selectedSlotText_onlyOneDayDataSelectAnHour_onlyHourText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
mBatteryChartPreferenceController.mDailyChartIndex = 0;
mBatteryChartPreferenceController.mHourlyChartIndex = 2;
@@ -337,7 +338,7 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void selectedSlotText_SelectADayAnHour_dayAndHourText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
mBatteryChartPreferenceController.mDailyChartIndex = 1;
mBatteryChartPreferenceController.mHourlyChartIndex = 8;
@@ -347,7 +348,7 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void selectedSlotText_selectFirstSlot_withMinuteText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
mBatteryChartPreferenceController.mDailyChartIndex = 0;
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
@@ -357,7 +358,7 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void selectedSlotText_selectLastSlot_withNowText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
mBatteryChartPreferenceController.mDailyChartIndex = 0;
mBatteryChartPreferenceController.mHourlyChartIndex = 3;
@@ -367,7 +368,7 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void selectedSlotText_selectOnlySlot_withMinuteAndNowText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(1));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(1));
mBatteryChartPreferenceController.mDailyChartIndex = 0;
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
@@ -388,7 +389,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mHourlyChartIndex = -1;
mBatteryChartPreferenceController.onCreate(bundle);
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(25));
+ mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(25));
assertThat(mBatteryChartPreferenceController.mDailyChartIndex)
.isEqualTo(expectedDailyIndex);
@@ -398,9 +399,7 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void getTotalHours_getExpectedResult() {
- Map> batteryHistoryMap = createBatteryHistoryMap(60);
- BatteryLevelData batteryLevelData =
- DataProcessManager.getBatteryLevelData(mContext, null, batteryHistoryMap, null);
+ BatteryLevelData batteryLevelData = createBatteryLevelData(60);
final int totalHour = BatteryChartPreferenceController.getTotalHours(batteryLevelData);
@@ -413,37 +412,26 @@ public final class BatteryChartPreferenceControllerTest {
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
}
- private static Map> createBatteryHistoryMap(
- int numOfHours) {
- final Map> batteryHistoryMap = new HashMap<>();
- for (int index = 0; index < numOfHours; index++) {
- final ContentValues values = new ContentValues();
- final DeviceBatteryState deviceBatteryState =
- DeviceBatteryState
- .newBuilder()
- .setBatteryLevel(100 - index)
- .build();
- final BatteryInformation batteryInformation =
- BatteryInformation
- .newBuilder()
- .setDeviceBatteryState(deviceBatteryState)
- .setConsumePower(100 - index)
- .build();
- values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
- ConvertUtils.convertBatteryInformationToString(batteryInformation));
- values.put(BatteryHistEntry.KEY_PACKAGE_NAME, "package" + index);
- final BatteryHistEntry entry = new BatteryHistEntry(values);
- final Map entryMap = new HashMap<>();
- entryMap.put("fake_entry_key" + index, entry);
- long timestamp = generateTimestamp(index);
+ private static BatteryLevelData createBatteryLevelData(int numOfHours) {
+ Map batteryLevelMap = new ArrayMap<>();
+ for (int index = 0; index < numOfHours; index += 2) {
+ final Integer level = 100 - index;
+ Long timestamp = generateTimestamp(index);
if (index == 0) {
timestamp += DateUtils.MINUTE_IN_MILLIS;
+ index--;
}
- batteryHistoryMap.put(timestamp, entryMap);
+ batteryLevelMap.put(timestamp, level);
}
- DataProcessor.sTestCurrentTimeMillis =
- generateTimestamp(numOfHours - 1) + DateUtils.MINUTE_IN_MILLIS * 2;
- return batteryHistoryMap;
+ long current = generateTimestamp(numOfHours - 1) + DateUtils.MINUTE_IN_MILLIS * 2;
+ batteryLevelMap.put(current, 66);
+ DataProcessor.sTestCurrentTimeMillis = current;
+ return new BatteryLevelData(batteryLevelMap);
+ }
+
+ private static Map> getEmptyBatteryUsageMap() {
+ return Map.of(SELECTED_INDEX_ALL, Map.of(SELECTED_INDEX_ALL, new BatteryDiffData(
+ null, 0, 0, 0, 0, 0, List.of(), List.of(), Set.of(), Set.of(), false)));
}
private BatteryChartPreferenceController createController() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffDataTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffDataTest.java
index 27539a58a54..d4bae2952de 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffDataTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffDataTest.java
@@ -147,6 +147,14 @@ public class BatteryDiffDataTest {
/*foregroundUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L, isHidden);
return new BatteryDiffEntry(
context,
+ batteryHistEntry.mUid,
+ batteryHistEntry.mUserId,
+ batteryHistEntry.getKey(),
+ batteryHistEntry.mIsHidden,
+ batteryHistEntry.mDrainType,
+ batteryHistEntry.mPackageName,
+ batteryHistEntry.mAppLabel,
+ batteryHistEntry.mConsumerType,
/*foregroundUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
/*screenOnTimeInMs=*/ 0,
@@ -154,8 +162,7 @@ public class BatteryDiffDataTest {
/*foregroundUsageConsumePower=*/ 0,
/*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0,
- /*cachedUsageConsumePower=*/ 0,
- batteryHistEntry);
+ /*cachedUsageConsumePower=*/ 0);
}
private static BatteryHistEntry createBatteryHistEntry(
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
index 655f1e41869..9bb4b73a658 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
@@ -95,6 +95,14 @@ public final class BatteryDiffEntryTest {
final BatteryDiffEntry entry =
new BatteryDiffEntry(
mContext,
+ /*uid=*/ 0,
+ /*userId=*/ 0,
+ /*key=*/ "key",
+ /*isHidden=*/ false,
+ /*componentId=*/ -1,
+ /*legacyPackageName=*/ null,
+ /*legacyLabel=*/ null,
+ /*consumerType*/ ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*foregroundUsageTimeInMs=*/ 10001L,
/*backgroundUsageTimeInMs=*/ 20002L,
/*screenOnTimeInMs=*/ 30003L,
@@ -102,8 +110,7 @@ public final class BatteryDiffEntryTest {
/*foregroundUsageConsumePower=*/ 10.0,
/*foregroundServiceUsageConsumePower=*/ 10.0,
/*backgroundUsageConsumePower=*/ 1.0,
- /*cachedUsageConsumePower=*/ 1.0,
- /*batteryHistEntry=*/ null);
+ /*cachedUsageConsumePower=*/ 1.0);
entry.setTotalConsumePower(100.0);
assertThat(entry.getPercentage()).isEqualTo(22.0);
@@ -114,6 +121,14 @@ public final class BatteryDiffEntryTest {
final BatteryDiffEntry entry =
new BatteryDiffEntry(
mContext,
+ /*uid=*/ 0,
+ /*userId=*/ 0,
+ /*key=*/ "key",
+ /*isHidden=*/ false,
+ /*componentId=*/ -1,
+ /*legacyPackageName=*/ null,
+ /*legacyLabel=*/ null,
+ /*consumerType*/ ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*foregroundUsageTimeInMs=*/ 10001L,
/*backgroundUsageTimeInMs=*/ 20002L,
/*screenOnTimeInMs=*/ 30003L,
@@ -121,8 +136,7 @@ public final class BatteryDiffEntryTest {
/*foregroundUsageConsumePower=*/ 10.0,
/*foregroundServiceUsageConsumePower=*/ 10.0,
/*backgroundUsageConsumePower=*/ 1.0,
- /*cachedUsageConsumePower=*/ 1.0,
- /*batteryHistEntry=*/ null);
+ /*cachedUsageConsumePower=*/ 1.0);
entry.setTotalConsumePower(0);
assertThat(entry.getPercentage()).isEqualTo(0);
@@ -133,7 +147,24 @@ public final class BatteryDiffEntryTest {
final List entryList = new ArrayList<>();
// Generates fake testing data.
BatteryDiffEntry systemAppsBatteryDiffEntry =
- new BatteryDiffEntry.SystemAppsBatteryDiffEntry(mContext);
+ new BatteryDiffEntry(
+ mContext,
+ /*uid=*/ 0,
+ /*userId=*/ 0,
+ /*key=*/ BatteryDiffEntry.SYSTEM_APPS_KEY,
+ /*isHidden=*/ false,
+ /*componentId=*/ -1,
+ /*legacyPackageName=*/ null,
+ /*legacyLabel=*/ BatteryDiffEntry.SYSTEM_APPS_KEY,
+ /*consumerType*/ ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
+ /*foregroundUsageTimeInMs=*/ 0,
+ /*backgroundUsageTimeInMs=*/ 0,
+ /*screenOnTimeInMs=*/ 0,
+ /*consumePower=*/ 0,
+ /*foregroundUsageConsumePower=*/ 0,
+ /*foregroundServiceUsageConsumePower=*/ 0,
+ /*backgroundUsageConsumePower=*/ 0,
+ /*cachedUsageConsumePower=*/ 0);
systemAppsBatteryDiffEntry.mConsumePower = 16;
systemAppsBatteryDiffEntry.setTotalConsumePower(100);
entryList.add(systemAppsBatteryDiffEntry);
@@ -448,17 +479,16 @@ public final class BatteryDiffEntryTest {
private BatteryDiffEntry createBatteryDiffEntry(
int consumerType, long uid, boolean isHidden) {
- final ContentValues values = getContentValuesWithType(consumerType);
- final BatteryInformation batteryInformation =
- BatteryInformation
- .newBuilder()
- .setIsHidden(isHidden)
- .build();
- values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
- ConvertUtils.convertBatteryInformationToString(batteryInformation));
- values.put(BatteryHistEntry.KEY_UID, uid);
return new BatteryDiffEntry(
mContext,
+ /*uid=*/ uid,
+ /*userId=*/ 0,
+ /*key=*/ "key",
+ /*isHidden=*/ isHidden,
+ /*componentId=*/ -1,
+ /*legacyPackageName=*/ null,
+ /*legacyLabel=*/ null,
+ /*consumerType*/ consumerType,
/*foregroundUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
/*screenOnTimeInMs=*/ 0,
@@ -466,14 +496,21 @@ public final class BatteryDiffEntryTest {
/*foregroundUsageConsumePower=*/ 0,
/*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0,
- /*cachedUsageConsumePower=*/ 0,
- new BatteryHistEntry(values));
+ /*cachedUsageConsumePower=*/ 0);
}
private BatteryDiffEntry createBatteryDiffEntry(
double consumePower, BatteryHistEntry batteryHistEntry) {
final BatteryDiffEntry entry = new BatteryDiffEntry(
mContext,
+ batteryHistEntry.mUid,
+ batteryHistEntry.mUserId,
+ batteryHistEntry.getKey(),
+ batteryHistEntry.mIsHidden,
+ batteryHistEntry.mDrainType,
+ batteryHistEntry.mPackageName,
+ batteryHistEntry.mAppLabel,
+ batteryHistEntry.mConsumerType,
/*foregroundUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
/*screenOnTimeInMs=*/ 0,
@@ -481,8 +518,7 @@ public final class BatteryDiffEntryTest {
/*foregroundUsageConsumePower=*/ 0,
/*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0,
- /*cachedUsageConsumePower=*/ 0,
- batteryHistEntry);
+ /*cachedUsageConsumePower=*/ 0);
entry.setTotalConsumePower(100.0);
return entry;
}
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 96677609241..609f2fc8d25 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
@@ -15,6 +15,10 @@
*/
package com.android.settings.fuelgauge.batteryusage;
+import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.isSystemConsumer;
+import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.isUidConsumer;
+import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.isUserConsumer;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@@ -147,32 +151,32 @@ public final class BatteryHistEntryTest {
@Test
public void testIsAppEntry_returnExpectedResult() {
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isAppEntry())
- .isFalse();
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isAppEntry())
- .isFalse();
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isAppEntry())
- .isTrue();
+ assertThat(isUidConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).mConsumerType)).isFalse();
+ assertThat(isUidConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).mConsumerType)).isFalse();
+ assertThat(isUidConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).mConsumerType)).isTrue();
}
@Test
public void testIsUserEntry_returnExpectedResult() {
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isUserEntry())
- .isFalse();
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isUserEntry())
- .isTrue();
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isUserEntry())
- .isFalse();
+ assertThat(isUserConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).mConsumerType)).isFalse();
+ assertThat(isUserConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).mConsumerType)).isTrue();
+ assertThat(isUserConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).mConsumerType)).isFalse();
}
@Test
public void testIsSystemEntry_returnExpectedResult() {
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isSystemEntry())
- .isTrue();
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isSystemEntry())
- .isFalse();
- assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isSystemEntry())
- .isFalse();
+ assertThat(isSystemConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).mConsumerType)).isTrue();
+ assertThat(isSystemConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).mConsumerType)).isFalse();
+ assertThat(isSystemConsumer(
+ createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).mConsumerType)).isFalse();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreferenceTest.java
index e14ead51bb7..9155c6607a9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreferenceTest.java
@@ -27,7 +27,6 @@ import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
-import com.android.settings.fuelgauge.BatteryInfo;
import org.junit.Before;
import org.junit.Test;
@@ -42,8 +41,6 @@ public class BatteryHistoryPreferenceTest {
@Mock
private PreferenceViewHolder mViewHolder;
@Mock
- private BatteryInfo mBatteryInfo;
- @Mock
private TextView mTextView;
@Mock
private BatteryChartView mDailyChartView;
@@ -59,7 +56,6 @@ public class BatteryHistoryPreferenceTest {
LayoutInflater.from(context).inflate(R.layout.battery_chart_graph, null);
mBatteryHistoryPreference = new BatteryHistoryPreference(context, null);
- mBatteryHistoryPreference.mBatteryInfo = mBatteryInfo;
mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(itemView));
when(mViewHolder.findViewById(R.id.daily_battery_chart)).thenReturn(mDailyChartView);
when(mViewHolder.findViewById(R.id.hourly_battery_chart)).thenReturn(mHourlyChartView);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelDataTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelDataTest.java
new file mode 100644
index 00000000000..13d60bb6c12
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryLevelDataTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+@RunWith(RobolectricTestRunner.class)
+public class BatteryLevelDataTest {
+
+ @Before
+ public void setUp() {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
+ }
+
+ @Test
+ public void getDailyTimestamps_allDataInOneHour_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1640970006000L, // 2022-01-01 01:00:06
+ 1640973608000L // 2022-01-01 01:00:08
+ );
+
+ final List expectedTimestamps = List.of(
+ 1640970006000L, // 2022-01-01 01:00:06
+ 1640973608000L // 2022-01-01 01:00:08
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void getDailyTimestamps_OneHourDataPerDay_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1641049200000L, // 2022-01-01 23:00:00
+ 1641052800000L, // 2022-01-02 00:00:00
+ 1641056400000L // 2022-01-02 01:00:00
+ );
+
+ final List expectedTimestamps = List.of(
+ 1641049200000L, // 2022-01-01 23:00:00
+ 1641052800000L, // 2022-01-02 00:00:00
+ 1641056400000L // 2022-01-02 01:00:00
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void getDailyTimestamps_OneDayData_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1640966400000L, // 2022-01-01 00:00:00
+ 1640970000000L, // 2022-01-01 01:00:00
+ 1640973600000L, // 2022-01-01 02:00:00
+ 1640977200000L, // 2022-01-01 03:00:00
+ 1640980800000L // 2022-01-01 04:00:00
+ );
+
+ final List expectedTimestamps = List.of(
+ 1640966400000L, // 2022-01-01 00:00:00
+ 1640980800000L // 2022-01-01 04:00:00
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void getDailyTimestamps_MultipleDaysData_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1641045600000L, // 2022-01-01 22:00:00
+ 1641060000000L, // 2022-01-02 02:00:00
+ 1641160800000L, // 2022-01-03 06:00:00
+ 1641232800000L // 2022-01-04 02:00:00
+ );
+
+ final List expectedTimestamps = List.of(
+ 1641045600000L, // 2022-01-01 22:00:00
+ 1641052800000L, // 2022-01-02 00:00:00
+ 1641139200000L, // 2022-01-03 00:00:00
+ 1641225600000L, // 2022-01-04 00:00:00
+ 1641232800000L // 2022-01-04 02:00:00
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void getDailyTimestamps_FirstDayOneHourData_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1641049200000L, // 2022-01-01 23:00:00
+ 1641060000000L, // 2022-01-02 02:00:00
+ 1641160800000L, // 2022-01-03 06:00:00
+ 1641254400000L // 2022-01-04 08:00:00
+ );
+
+ final List expectedTimestamps = List.of(
+ 1641049200000L, // 2022-01-01 23:00:00
+ 1641052800000L, // 2022-01-02 00:00:00
+ 1641139200000L, // 2022-01-03 00:00:00
+ 1641225600000L, // 2022-01-04 00:00:00
+ 1641254400000L // 2022-01-04 08:00:00
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void getDailyTimestamps_LastDayNoData_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1640988000000L, // 2022-01-01 06:00:00
+ 1641060000000L, // 2022-01-02 02:00:00
+ 1641160800000L, // 2022-01-03 06:00:00
+ 1641225600000L // 2022-01-04 00:00:00
+ );
+
+ final List expectedTimestamps = List.of(
+ 1640988000000L, // 2022-01-01 06:00:00
+ 1641052800000L, // 2022-01-02 00:00:00
+ 1641139200000L, // 2022-01-03 00:00:00
+ 1641225600000L // 2022-01-04 00:00:00
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void getDailyTimestamps_LastDayOneHourData_returnExpectedList() {
+ // Timezone GMT+8
+ final List timestamps = List.of(
+ 1640988000000L, // 2022-01-01 06:00:00
+ 1641060000000L, // 2022-01-02 02:00:00
+ 1641160800000L, // 2022-01-03 06:00:00
+ 1641229200000L // 2022-01-04 01:00:00
+ );
+
+ final List expectedTimestamps = List.of(
+ 1640988000000L, // 2022-01-01 06:00:00
+ 1641052800000L, // 2022-01-02 00:00:00
+ 1641139200000L, // 2022-01-03 00:00:00
+ 1641225600000L, // 2022-01-04 00:00:00
+ 1641229200000L // 2022-01-04 01:00:00
+ );
+ assertThat(BatteryLevelData.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
+ }
+
+ @Test
+ public void combine_normalFlow_returnExpectedResult() {
+ final BatteryLevelData batteryLevelData =
+ new BatteryLevelData(Map.of(1691596800000L, 90, 1691604000000L, 80));
+ final List batteryLevelRecordEvents = List.of(
+ BatteryEvent.newBuilder().setTimestamp(1691586000166L).setBatteryLevel(100)
+ .setType(BatteryEventType.FULL_CHARGED).build(),
+ BatteryEvent.newBuilder().setTimestamp(1691589600000L).setBatteryLevel(98)
+ .setType(BatteryEventType.EVEN_HOUR).build());
+
+ BatteryLevelData result =
+ BatteryLevelData.combine(batteryLevelData, batteryLevelRecordEvents);
+
+ assertThat(result.getDailyBatteryLevels().getTimestamps())
+ .isEqualTo(List.of(1691586000166L, 1691596800000L, 1691604000000L));
+ assertThat(result.getDailyBatteryLevels().getLevels())
+ .isEqualTo(List.of(100, 90, 80));
+ assertThat(result.getHourlyBatteryLevelsPerDay())
+ .hasSize(2);
+ assertThat(result.getHourlyBatteryLevelsPerDay().get(0).getTimestamps())
+ .isEqualTo(List.of(1691586000166L, 1691589600000L, 1691596800000L));
+ assertThat(result.getHourlyBatteryLevelsPerDay().get(0).getLevels())
+ .isEqualTo(List.of(100, 98, 90));
+ assertThat(result.getHourlyBatteryLevelsPerDay().get(1).getTimestamps())
+ .isEqualTo(List.of(1691596800000L, 1691604000000L));
+ assertThat(result.getHourlyBatteryLevelsPerDay().get(1).getLevels())
+ .isEqualTo(List.of(90, 80));
+ }
+
+ @Test
+ public void combine_existingBatteryLevelDataIsNull_returnExpectedResult() {
+ final List batteryLevelRecordEvents = List.of(
+ BatteryEvent.newBuilder().setTimestamp(1691586000166L).setBatteryLevel(100)
+ .setType(BatteryEventType.FULL_CHARGED).build(),
+ BatteryEvent.newBuilder().setTimestamp(1691589600000L).setBatteryLevel(98)
+ .setType(BatteryEventType.EVEN_HOUR).build());
+
+ BatteryLevelData result =
+ BatteryLevelData.combine(null, batteryLevelRecordEvents);
+
+ assertThat(result.getHourlyBatteryLevelsPerDay())
+ .hasSize(1);
+ assertThat(result.getHourlyBatteryLevelsPerDay().get(0).getTimestamps())
+ .isEqualTo(List.of(1691586000166L, 1691589600000L));
+ assertThat(result.getHourlyBatteryLevelsPerDay().get(0).getLevels())
+ .isEqualTo(List.of(100, 98));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
index 3a9ce2b4c52..d89c06b1150 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -96,6 +96,14 @@ public final class BatteryUsageBreakdownControllerTest {
mBatteryUsageBreakdownController.mAppListPreferenceGroup = mAppListPreferenceGroup;
mBatteryDiffEntry = new BatteryDiffEntry(
mContext,
+ /*uid=*/ 0L,
+ /*userId=*/ 0L,
+ /*key=*/ "key",
+ /*isHidden=*/ false,
+ /*componentId=*/ -1,
+ /*legacyPackageName=*/ null,
+ /*legacyLabel=*/ null,
+ /*consumerType=*/ ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*foregroundUsageTimeInMs=*/ 1,
/*backgroundUsageTimeInMs=*/ 2,
/*screenOnTimeInMs=*/ 0,
@@ -103,13 +111,14 @@ public final class BatteryUsageBreakdownControllerTest {
/*foregroundUsageConsumePower=*/ 0,
/*foregroundServiceUsageConsumePower=*/ 1,
/*backgroundUsageConsumePower=*/ 2,
- /*cachedUsageConsumePower=*/ 0,
- mBatteryHistEntry);
+ /*cachedUsageConsumePower=*/ 0);
mBatteryDiffEntry = spy(mBatteryDiffEntry);
mBatteryUsageBreakdownController.mBatteryDiffData =
- new BatteryDiffData(mContext, /* screenOnTime= */ 0L,
- Arrays.asList(mBatteryDiffEntry), Arrays.asList(), Set.of(), Set.of(),
- /* isAccumulated= */ false);
+ new BatteryDiffData(mContext, /* startTimestamp= */ 0L, /* endTimestamp= */ 0L,
+ /* startBatteryLevel= */ 0, /* endBatteryLevel= */ 0,
+ /* screenOnTime= */ 0L, Arrays.asList(mBatteryDiffEntry), Arrays.asList(),
+ Set.of(), Set.of(), /* isAccumulated= */ false);
+ BatteryDiffEntry.clearCache();
// Adds fake testing data.
BatteryDiffEntry.sResourceCache.put(
"fakeBatteryDiffEntryKey",
@@ -140,7 +149,7 @@ public final class BatteryUsageBreakdownControllerTest {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(PREF_KEY).when(mBatteryDiffEntry).getKey();
doReturn(null).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
doReturn(false).when(mBatteryDiffEntry).validForRestriction();
@@ -168,7 +177,7 @@ public final class BatteryUsageBreakdownControllerTest {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(PREF_KEY).when(mBatteryDiffEntry).getKey();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
mBatteryUsageBreakdownController.addAllPreferences();
@@ -197,7 +206,7 @@ public final class BatteryUsageBreakdownControllerTest {
public void removeAndCacheAllUnusedPreferences_keepPref_KeepAllPreference() {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(PREF_KEY).when(mBatteryDiffEntry).getKey();
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
// Ensures the testing data is correct.
@@ -222,7 +231,7 @@ public final class BatteryUsageBreakdownControllerTest {
@Test
public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
- doReturn(false).when(mBatteryHistEntry).isAppEntry();
+ mBatteryDiffEntry.mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
assertThat(mBatteryUsageBreakdownController.handlePreferenceTreeClick(
@@ -238,7 +247,7 @@ public final class BatteryUsageBreakdownControllerTest {
@Test
public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
- doReturn(true).when(mBatteryHistEntry).isAppEntry();
+ mBatteryDiffEntry.mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
assertThat(mBatteryUsageBreakdownController.handlePreferenceTreeClick(
@@ -394,10 +403,23 @@ public final class BatteryUsageBreakdownControllerTest {
contentValues.put(BatteryHistEntry.KEY_USER_ID, Integer.valueOf(1001));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(contentValues);
return new BatteryDiffEntry(
- mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs, screenOnTimeInMs,
- /*consumePower=*/ 0, /*foregroundUsageConsumePower=*/ 0,
- /*foregroundServiceUsageConsumePower=*/ 0, /*backgroundUsageConsumePower=*/ 0,
- /*cachedUsageConsumePower=*/ 0, batteryHistEntry);
+ mContext,
+ batteryHistEntry.mUid,
+ batteryHistEntry.mUserId,
+ batteryHistEntry.getKey(),
+ batteryHistEntry.mIsHidden,
+ batteryHistEntry.mDrainType,
+ batteryHistEntry.mPackageName,
+ batteryHistEntry.mAppLabel,
+ batteryHistEntry.mConsumerType,
+ foregroundUsageTimeInMs,
+ backgroundUsageTimeInMs,
+ screenOnTimeInMs,
+ /*consumePower=*/ 0,
+ /*foregroundUsageConsumePower=*/ 0,
+ /*foregroundServiceUsageConsumePower=*/ 0,
+ /*backgroundUsageConsumePower=*/ 0,
+ /*cachedUsageConsumePower=*/ 0);
}
private BatteryUsageBreakdownController createController() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
index 05a6f2bc89c..999a9217112 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
@@ -20,11 +20,9 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
-import android.app.Application;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
-import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@@ -34,6 +32,7 @@ import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity;
import com.android.settings.fuelgauge.batteryusage.db.BatteryState;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
+import com.android.settings.fuelgauge.batteryusage.db.BatteryUsageSlotEntity;
import com.android.settings.testutils.BatteryTestUtils;
import com.android.settings.testutils.FakeClock;
@@ -41,12 +40,10 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.Shadows;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/** Tests for {@link BatteryUsageContentProvider}. */
@@ -126,11 +123,29 @@ public final class BatteryUsageContentProviderTest {
() -> mProvider.insert(uri, /*contentValues=*/ null));
}
+ @Test
+ public void query_getLastFullChargeTimestamp_returnsExpectedResult() throws Exception {
+ mProvider.onCreate();
+ ContentValues values = new ContentValues();
+ values.put(BatteryEventEntity.KEY_TIMESTAMP, 10001L);
+ values.put(BatteryEventEntity.KEY_BATTERY_EVENT_TYPE,
+ BatteryEventType.FULL_CHARGED.getNumber());
+ values.put(BatteryEventEntity.KEY_BATTERY_LEVEL, 100);
+ mProvider.insert(DatabaseUtils.BATTERY_EVENT_URI, values);
+
+ final Cursor cursor = getCursorOfLastFullChargeTimestamp();
+
+ assertThat(cursor.getCount()).isEqualTo(1);
+ cursor.moveToFirst();
+ final long lastFullChargeTimestamp = cursor.getLong(0);
+ assertThat(lastFullChargeTimestamp).isEqualTo(10001L);
+ }
+
@Test
public void query_batteryState_returnsExpectedResult() throws Exception {
mProvider.onCreate();
final Duration currentTime = Duration.ofHours(52);
- final long expiredTimeCutoff = currentTime.toMillis() - 3;
+ final long expiredTimeCutoff = currentTime.toMillis() - 8;
final Cursor cursor = insertBatteryState(currentTime, Long.toString(expiredTimeCutoff));
@@ -150,19 +165,13 @@ public final class BatteryUsageContentProviderTest {
final String actualPackageName3 = cursor.getString(packageNameIndex);
assertThat(actualPackageName3).isEqualTo(PACKAGE_NAME3);
cursor.close();
- // Verifies the broadcast intent.
- TimeUnit.SECONDS.sleep(1);
- final List intents = Shadows.shadowOf((Application) mContext).getBroadcastIntents();
- assertThat(intents).hasSize(1);
- assertThat(intents.get(0).getAction()).isEqualTo(
- BootBroadcastReceiver.ACTION_PERIODIC_JOB_RECHECK);
}
@Test
public void query_batteryStateTimestamp_returnsExpectedResult() throws Exception {
mProvider.onCreate();
final Duration currentTime = Duration.ofHours(52);
- final long expiredTimeCutoff = currentTime.toMillis() - 1;
+ final long expiredTimeCutoff = currentTime.toMillis() - 2;
final Cursor cursor = insertBatteryState(currentTime, Long.toString(expiredTimeCutoff));
@@ -178,12 +187,25 @@ public final class BatteryUsageContentProviderTest {
final String actualPackageName2 = cursor.getString(packageNameIndex);
assertThat(actualPackageName2).isEqualTo(PACKAGE_NAME3);
cursor.close();
- // Verifies the broadcast intent.
- TimeUnit.SECONDS.sleep(1);
- final List intents = Shadows.shadowOf((Application) mContext).getBroadcastIntents();
- assertThat(intents).hasSize(1);
- assertThat(intents.get(0).getAction()).isEqualTo(
- BootBroadcastReceiver.ACTION_PERIODIC_JOB_RECHECK);
+ }
+
+ @Test
+ public void query_getBatteryStateLatestTimestamp_returnsExpectedResult() throws Exception {
+ mProvider.onCreate();
+ final Duration currentTime = Duration.ofHours(52);
+ insertBatteryState(currentTime, Long.toString(currentTime.toMillis()));
+
+ final Cursor cursor1 = getCursorOfBatteryStateLatestTimestamp(currentTime.toMillis() - 5);
+ assertThat(cursor1.getCount()).isEqualTo(1);
+ cursor1.moveToFirst();
+ final long latestTimestamp1 = cursor1.getLong(0);
+ assertThat(latestTimestamp1).isEqualTo(currentTime.toMillis() - 6);
+
+ final Cursor cursor2 = getCursorOfBatteryStateLatestTimestamp(currentTime.toMillis() - 2);
+ assertThat(cursor2.getCount()).isEqualTo(1);
+ cursor2.moveToFirst();
+ final long latestTimestamp2 = cursor2.getLong(0);
+ assertThat(latestTimestamp2).isEqualTo(currentTime.toMillis() - 2);
}
@Test
@@ -355,7 +377,7 @@ public final class BatteryUsageContentProviderTest {
}
@Test
- public void insert_batteryEvent_returnsExpectedResult() {
+ public void insertAndQuery_batteryEvent_returnsExpectedResult() {
mProvider.onCreate();
ContentValues values = new ContentValues();
values.put(BatteryEventEntity.KEY_TIMESTAMP, 10001L);
@@ -366,7 +388,7 @@ public final class BatteryUsageContentProviderTest {
final Uri uri = mProvider.insert(DatabaseUtils.BATTERY_EVENT_URI, values);
assertThat(uri).isEqualTo(DatabaseUtils.BATTERY_EVENT_URI);
- // Verifies the AppUsageEventEntity content.
+ // Verifies the BatteryEventEntity content.
final List entities =
BatteryStateDatabase.getInstance(mContext).batteryEventDao().getAll();
assertThat(entities).hasSize(1);
@@ -374,6 +396,50 @@ public final class BatteryUsageContentProviderTest {
assertThat(entities.get(0).batteryEventType).isEqualTo(
BatteryEventType.POWER_CONNECTED.getNumber());
assertThat(entities.get(0).batteryLevel).isEqualTo(66);
+
+ final Cursor cursor1 = getCursorOfBatteryEvents(
+ 0L, List.of(BatteryEventType.POWER_CONNECTED.getNumber()));
+ assertThat(cursor1.getCount()).isEqualTo(1);
+ cursor1.moveToFirst();
+ assertThat(cursor1.getLong(cursor1.getColumnIndex(BatteryEventEntity.KEY_TIMESTAMP)))
+ .isEqualTo(10001L);
+ assertThat(
+ cursor1.getInt(cursor1.getColumnIndex(BatteryEventEntity.KEY_BATTERY_EVENT_TYPE)))
+ .isEqualTo(BatteryEventType.POWER_CONNECTED.getNumber());
+ assertThat(cursor1.getInt(cursor1.getColumnIndex(BatteryEventEntity.KEY_BATTERY_LEVEL)))
+ .isEqualTo(66);
+
+ final Cursor cursor2 = getCursorOfBatteryEvents(
+ 0L, List.of(BatteryEventType.POWER_DISCONNECTED.getNumber()));
+ assertThat(cursor2.getCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void insertAndQuery_batteryUsageSlot_returnsExpectedResult() {
+ mProvider.onCreate();
+ ContentValues values = new ContentValues();
+ values.put(BatteryUsageSlotEntity.KEY_TIMESTAMP, 10001L);
+ values.put(BatteryUsageSlotEntity.KEY_BATTERY_USAGE_SLOT, "TEST_STRING");
+
+ final Uri uri = mProvider.insert(DatabaseUtils.BATTERY_USAGE_SLOT_URI, values);
+ // Verifies the BatteryUsageSlotEntity content.
+ assertThat(uri).isEqualTo(DatabaseUtils.BATTERY_USAGE_SLOT_URI);
+ final List entities =
+ BatteryStateDatabase.getInstance(mContext).batteryUsageSlotDao().getAll();
+ assertThat(entities).hasSize(1);
+ assertThat(entities.get(0).timestamp).isEqualTo(10001L);
+ assertThat(entities.get(0).batteryUsageSlot).isEqualTo("TEST_STRING");
+
+ final Cursor cursor1 = getCursorOfBatteryUsageSlots(10001L);
+ assertThat(cursor1.getCount()).isEqualTo(1);
+ cursor1.moveToFirst();
+ assertThat(cursor1.getLong(cursor1.getColumnIndex(BatteryUsageSlotEntity.KEY_TIMESTAMP)))
+ .isEqualTo(10001L);
+ assertThat(cursor1.getString(cursor1.getColumnIndex(
+ BatteryUsageSlotEntity.KEY_BATTERY_USAGE_SLOT))).isEqualTo("TEST_STRING");
+
+ final Cursor cursor2 = getCursorOfBatteryUsageSlots(10002L);
+ assertThat(cursor2.getCount()).isEqualTo(0);
}
@Test
@@ -404,10 +470,10 @@ public final class BatteryUsageContentProviderTest {
final long currentTimestamp = currentTime.toMillis();
// Inserts some valid testing data.
BatteryTestUtils.insertDataToBatteryStateTable(
- mContext, currentTimestamp - 2, PACKAGE_NAME1,
+ mContext, currentTimestamp - 6, PACKAGE_NAME1,
/*isFullChargeStart=*/ true);
BatteryTestUtils.insertDataToBatteryStateTable(
- mContext, currentTimestamp - 1, PACKAGE_NAME2);
+ mContext, currentTimestamp - 2, PACKAGE_NAME2);
BatteryTestUtils.insertDataToBatteryStateTable(
mContext, currentTimestamp, PACKAGE_NAME3);
@@ -420,17 +486,35 @@ public final class BatteryUsageContentProviderTest {
DatabaseUtils.QUERY_KEY_TIMESTAMP, queryTimestamp)
.build();
- final Cursor cursor =
- mProvider.query(
- batteryStateQueryContentUri,
- /*strings=*/ null,
- /*s=*/ null,
- /*strings1=*/ null,
- /*s1=*/ null);
+ final Cursor cursor = query(batteryStateQueryContentUri);
return cursor;
}
+ private Cursor getCursorOfLastFullChargeTimestamp() {
+ final Uri lastFullChargeTimestampContentUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(DatabaseUtils.AUTHORITY)
+ .appendPath(DatabaseUtils.LAST_FULL_CHARGE_TIMESTAMP_PATH)
+ .build();
+
+ return query(lastFullChargeTimestampContentUri);
+ }
+
+ private Cursor getCursorOfBatteryStateLatestTimestamp(final long queryTimestamp) {
+ final Uri batteryStateLatestTimestampUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(DatabaseUtils.AUTHORITY)
+ .appendPath(DatabaseUtils.BATTERY_STATE_LATEST_TIMESTAMP_PATH)
+ .appendQueryParameter(
+ DatabaseUtils.QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+ .build();
+
+ return query(batteryStateLatestTimestampUri);
+ }
+
private void insertAppUsageEvent() {
mProvider.onCreate();
// Inserts some valid testing data.
@@ -452,12 +536,7 @@ public final class BatteryUsageContentProviderTest {
DatabaseUtils.QUERY_KEY_USERID, Long.toString(userId))
.build();
- return mProvider.query(
- appUsageLatestTimestampQueryContentUri,
- /*strings=*/ null,
- /*s=*/ null,
- /*strings1=*/ null,
- /*s1=*/ null);
+ return query(appUsageLatestTimestampQueryContentUri);
}
private Cursor getCursorOfAppUsage(final List userIds, final long queryTimestamp) {
@@ -474,7 +553,43 @@ public final class BatteryUsageContentProviderTest {
.appendQueryParameter(DatabaseUtils.QUERY_KEY_USERID, queryUserIdString)
.build();
+ return query(appUsageEventUri);
+ }
+
+ private Cursor getCursorOfBatteryEvents(
+ final long queryTimestamp, final List batteryEventTypes) {
+ final String batteryEventTypesString = batteryEventTypes.stream()
+ .map(type -> String.valueOf(type))
+ .collect(Collectors.joining(","));
+ final Uri batteryEventUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(DatabaseUtils.AUTHORITY)
+ .appendPath(DatabaseUtils.BATTERY_EVENT_TABLE)
+ .appendQueryParameter(
+ DatabaseUtils.QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+ .appendQueryParameter(
+ DatabaseUtils.QUERY_BATTERY_EVENT_TYPE, batteryEventTypesString)
+ .build();
+
+ return query(batteryEventUri);
+ }
+
+ private Cursor getCursorOfBatteryUsageSlots(final long queryTimestamp) {
+ final Uri batteryUsageSlotUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(DatabaseUtils.AUTHORITY)
+ .appendPath(DatabaseUtils.BATTERY_USAGE_SLOT_TABLE)
+ .appendQueryParameter(
+ DatabaseUtils.QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+ .build();
+
+ return query(batteryUsageSlotUri);
+ }
+
+ private Cursor query(Uri uri) {
return mProvider.query(
- appUsageEventUri, /*strings=*/ null, /*s=*/ null, /*strings1=*/ null, /*s1=*/ null);
+ uri, /*strings=*/ null, /*s=*/ null, /*strings1=*/ null, /*s1=*/ null);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java
index 9aeff794907..f3965fd48cd 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoaderTest.java
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
@@ -31,6 +32,7 @@ import android.content.pm.PackageManager;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
+import android.os.UserManager;
import org.junit.Before;
import org.junit.Test;
@@ -43,6 +45,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@@ -56,6 +59,8 @@ public final class BatteryUsageDataLoaderTest {
@Mock
private PackageManager mPackageManager;
@Mock
+ private UserManager mUserManager;
+ @Mock
private BatteryUsageStats mBatteryUsageStats;
@Mock
private BatteryEntry mMockBatteryEntry;
@@ -70,6 +75,7 @@ public final class BatteryUsageDataLoaderTest {
doReturn(mBatteryStatsManager).when(mContext).getSystemService(
Context.BATTERY_STATS_SERVICE);
doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
doReturn(mMockContentResolver).when(mContext).getContentResolver();
doReturn(new Intent()).when(mContext).registerReceiver(any(), any());
}
@@ -82,7 +88,7 @@ public final class BatteryUsageDataLoaderTest {
.thenReturn(mBatteryUsageStats);
BatteryUsageDataLoader.sFakeBatteryEntryListSupplier = () -> batteryEntryList;
- BatteryUsageDataLoader.loadUsageData(mContext, /*isFullChargeStart=*/ false);
+ BatteryUsageDataLoader.loadBatteryStatsData(mContext, /*isFullChargeStart=*/ false);
final int queryFlags = mStatsQueryCaptor.getValue().getFlags();
assertThat(queryFlags
@@ -97,7 +103,7 @@ public final class BatteryUsageDataLoaderTest {
.thenReturn(mBatteryUsageStats);
BatteryUsageDataLoader.sFakeBatteryEntryListSupplier = () -> null;
- BatteryUsageDataLoader.loadUsageData(mContext, /*isFullChargeStart=*/ false);
+ BatteryUsageDataLoader.loadBatteryStatsData(mContext, /*isFullChargeStart=*/ false);
verify(mMockContentResolver).insert(any(), any());
}
@@ -108,8 +114,51 @@ public final class BatteryUsageDataLoaderTest {
.thenReturn(mBatteryUsageStats);
BatteryUsageDataLoader.sFakeBatteryEntryListSupplier = () -> new ArrayList<>();
- BatteryUsageDataLoader.loadUsageData(mContext, /*isFullChargeStart=*/ false);
+ BatteryUsageDataLoader.loadBatteryStatsData(mContext, /*isFullChargeStart=*/ false);
verify(mMockContentResolver).insert(any(), any());
}
+
+ @Test
+ public void loadAppUsageData_withData_insertFakeDataIntoProvider() {
+ final List AppUsageEventList = new ArrayList<>();
+ final AppUsageEvent appUsageEvent = AppUsageEvent.newBuilder().setUid(0).build();
+ AppUsageEventList.add(appUsageEvent);
+ BatteryUsageDataLoader.sFakeAppUsageEventsSupplier = () -> new HashMap<>();
+ BatteryUsageDataLoader.sFakeUsageEventsListSupplier = () -> AppUsageEventList;
+
+ BatteryUsageDataLoader.loadAppUsageData(mContext);
+
+ verify(mMockContentResolver).bulkInsert(any(), any());
+ verify(mMockContentResolver).notifyChange(any(), any());
+ }
+
+ @Test
+ public void loadAppUsageData_nullAppUsageEvents_notInsertDataIntoProvider() {
+ BatteryUsageDataLoader.sFakeAppUsageEventsSupplier = () -> null;
+
+ BatteryUsageDataLoader.loadAppUsageData(mContext);
+
+ verifyNoMoreInteractions(mMockContentResolver);
+ }
+
+ @Test
+ public void loadAppUsageData_nullUsageEventsList_notInsertDataIntoProvider() {
+ BatteryUsageDataLoader.sFakeAppUsageEventsSupplier = () -> new HashMap<>();
+ BatteryUsageDataLoader.sFakeUsageEventsListSupplier = () -> null;
+
+ BatteryUsageDataLoader.loadAppUsageData(mContext);
+
+ verifyNoMoreInteractions(mMockContentResolver);
+ }
+
+ @Test
+ public void loadAppUsageData_emptyUsageEventsList_notInsertDataIntoProvider() {
+ BatteryUsageDataLoader.sFakeAppUsageEventsSupplier = () -> new HashMap<>();
+ BatteryUsageDataLoader.sFakeUsageEventsListSupplier = () -> new ArrayList<>();
+
+ BatteryUsageDataLoader.loadAppUsageData(mContext);
+
+ verifyNoMoreInteractions(mMockContentResolver);
+ }
}
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 e9108bc7efe..f06dc634005 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -39,6 +39,7 @@ import android.os.UserHandle;
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity;
+import com.android.settings.fuelgauge.batteryusage.db.BatteryUsageSlotEntity;
import org.junit.Before;
import org.junit.Test;
@@ -48,7 +49,10 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class)
@@ -212,6 +216,22 @@ public final class ConvertUtilsTest {
assertThat(values.getAsInteger(BatteryEventEntity.KEY_BATTERY_LEVEL)).isEqualTo(66);
}
+ @Test
+ public void convertBatteryUsageSlotToContentValues_normalCase_returnsExpectedContentValues() {
+ final BatteryUsageSlot batteryUsageSlot =
+ BatteryUsageSlot.newBuilder()
+ .setStartTimestamp(10001L)
+ .setEndTimestamp(30003L)
+ .setStartBatteryLevel(88)
+ .setEndBatteryLevel(66)
+ .setScreenOnTime(123L)
+ .build();
+ final ContentValues values =
+ ConvertUtils.convertBatteryUsageSlotToContentValues(batteryUsageSlot);
+ assertThat(values.getAsLong(BatteryUsageSlotEntity.KEY_TIMESTAMP)).isEqualTo(10001L);
+ assertThat(BatteryUsageSlotEntity.KEY_BATTERY_USAGE_SLOT).isNotEmpty();
+ }
+
@Test
public void convertToBatteryHistEntry_returnsExpectedResult() {
final int expectedType = 3;
@@ -363,7 +383,7 @@ public final class ConvertUtilsTest {
}
@Test
- public void convertToAppUsageEventFromCursor_returnExpectedResult() {
+ public void convertToAppUsageEvent_returnExpectedResult() {
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
@@ -384,7 +404,7 @@ public final class ConvertUtilsTest {
100001L});
cursor.moveToFirst();
- final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEventFromCursor(cursor);
+ final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(cursor);
assertThat(appUsageEvent.getUid()).isEqualTo(101L);
assertThat(appUsageEvent.getUserId()).isEqualTo(1001L);
@@ -396,7 +416,7 @@ public final class ConvertUtilsTest {
}
@Test
- public void convertToAppUsageEventFromCursor_emptyInstanceIdAndRootName_returnExpectedResult() {
+ public void convertToAppUsageEvent_emptyInstanceIdAndRootName_returnExpectedResult() {
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
@@ -413,7 +433,7 @@ public final class ConvertUtilsTest {
AppUsageEventType.DEVICE_SHUTDOWN.getNumber()});
cursor.moveToFirst();
- final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEventFromCursor(cursor);
+ final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(cursor);
assertThat(appUsageEvent.getUid()).isEqualTo(101L);
assertThat(appUsageEvent.getUserId()).isEqualTo(1001L);
@@ -433,6 +453,42 @@ public final class ConvertUtilsTest {
assertThat(batteryEvent.getBatteryLevel()).isEqualTo(88);
}
+ @Test
+ public void convertToBatteryEventList_normalCase_returnsExpectedResult() {
+ final BatteryLevelData batteryLevelData = new BatteryLevelData(Map.of(
+ 1691589600000L, 98, 1691596800000L, 90, 1691596812345L, 80));
+
+ final List batteryEventList =
+ ConvertUtils.convertToBatteryEventList(batteryLevelData);
+
+ assertThat(batteryEventList).hasSize(2);
+ assertThat(batteryEventList.get(0).getTimestamp()).isEqualTo(1691589600000L);
+ assertThat(batteryEventList.get(0).getType()).isEqualTo(BatteryEventType.EVEN_HOUR);
+ assertThat(batteryEventList.get(0).getBatteryLevel()).isEqualTo(98);
+ assertThat(batteryEventList.get(1).getTimestamp()).isEqualTo(1691596800000L);
+ assertThat(batteryEventList.get(1).getType()).isEqualTo(BatteryEventType.EVEN_HOUR);
+ assertThat(batteryEventList.get(1).getBatteryLevel()).isEqualTo(90);
+ }
+
+ @Test
+ public void convertToBatteryUsageSlotList_normalCase_returnsExpectedResult() {
+ BatteryDiffData batteryDiffData1 = new BatteryDiffData(
+ mContext, 11L, 12L, 13, 14, 15, List.of(), List.of(), Set.of(), Set.of(), false);
+ BatteryDiffData batteryDiffData2 = new BatteryDiffData(
+ mContext, 21L, 22L, 23, 24, 25, List.of(), List.of(), Set.of(), Set.of(), false);
+ BatteryDiffData batteryDiffData3 = new BatteryDiffData(
+ mContext, 31L, 32L, 33, 34, 35, List.of(), List.of(), Set.of(), Set.of(), false);
+ final Map batteryDiffDataMap = Map.of(
+ 11L, batteryDiffData1, 21L, batteryDiffData2, 31L, batteryDiffData3);
+
+ final List batteryUsageSlotList =
+ ConvertUtils.convertToBatteryUsageSlotList(batteryDiffDataMap);
+
+ assertThat(batteryUsageSlotList).hasSize(3);
+ assertThat(batteryUsageSlotList.stream().map((s) -> s.getScreenOnTime()).sorted().toList())
+ .isEqualTo(List.of(15L, 25L, 35L));
+ }
+
@Test
public void getLocale_nullContext_returnDefaultLocale() {
assertThat(ConvertUtils.getLocale(/*context=*/ null))
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
index b610cfbf289..94fa00fddd9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
@@ -30,8 +30,12 @@ import android.app.usage.UsageEvents;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.database.Cursor;
import android.database.MatrixCursor;
import android.os.BatteryManager;
+import android.os.BatteryStatsManager;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserManager;
@@ -39,9 +43,12 @@ import android.text.format.DateUtils;
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -52,6 +59,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
@RunWith(RobolectricTestRunner.class)
public final class DataProcessManagerTest {
@@ -65,7 +73,13 @@ public final class DataProcessManagerTest {
@Mock
private UserManager mUserManager;
@Mock
+ private BatteryStatsManager mBatteryStatsManager;
+ @Mock
+ private BatteryUsageStats mBatteryUsageStats;
+ @Mock
private Intent mIntent;
+ @Captor
+ private ArgumentCaptor mBatteryUsageStatsQueryCaptor;
@Before
public void setUp() {
@@ -77,22 +91,32 @@ public final class DataProcessManagerTest {
doReturn(mUserManager)
.when(mContext)
.getSystemService(UserManager.class);
+ doReturn(mBatteryStatsManager).when(mContext).getSystemService(
+ Context.BATTERY_STATS_SERVICE);
+ doReturn(mBatteryUsageStats).when(
+ mBatteryStatsManager).getBatteryUsageStats(mBatteryUsageStatsQueryCaptor.capture());
doReturn(mIntent).when(mContext).registerReceiver(any(), any());
doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
doReturn(66).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_LEVEL), anyInt());
mDataProcessManager = new DataProcessManager(
mContext, /*handler=*/ null, /*rawStartTimestamp=*/ 0L,
- /*callbackFunction=*/ null, /*hourlyBatteryLevelsPerDay=*/ new ArrayList<>(),
+ /*lastFullChargeTimestamp=*/ 0L, /*callbackFunction=*/ null,
+ /*hourlyBatteryLevelsPerDay=*/ new ArrayList<>(),
/*batteryHistoryMap=*/ new HashMap<>());
}
+ @After
+ public void cleanUp() {
+ DatabaseUtils.sFakeSupplier = null;
+ DataProcessManager.sFakeBatteryHistoryMap = null;
+ }
+
@Test
public void constructor_noLevelData() {
final DataProcessManager dataProcessManager =
new DataProcessManager(mContext, /*handler=*/ null, /*callbackFunction=*/ null);
assertThat(dataProcessManager.getShowScreenOnTime()).isFalse();
- assertThat(dataProcessManager.getShowBatteryLevel()).isFalse();
}
@Test
@@ -122,16 +146,18 @@ public final class DataProcessManagerTest {
final String packageName = "package";
// Adds the day 1 data.
final List timestamps1 = List.of(2L, 3L, 4L);
- final List levels1 = List.of(100, 100, 100);
+ final Map batteryLevelMap1 =
+ Map.of(timestamps1.get(0), 100, timestamps1.get(1), 100, timestamps1.get(2), 100);
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps1, levels1));
+ new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap1, timestamps1));
// Adds the day 2 data.
hourlyBatteryLevelsPerDay.add(null);
// Adds the day 3 data.
final List timestamps2 = List.of(5L, 6L);
- final List levels2 = List.of(100, 100);
+ final Map batteryLevelMap2 =
+ Map.of(timestamps2.get(0), 100, timestamps2.get(1), 100);
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps2, levels2));
+ new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap2, timestamps2));
// Fake current usage data.
final UsageEvents.Event event1 =
getUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, /*timestamp=*/ 1, packageName);
@@ -171,10 +197,18 @@ public final class DataProcessManagerTest {
cursor.addRow(new Object[] {
AppUsageEventType.ACTIVITY_STOPPED.getNumber(), /*timestamp=*/ 6, /*userId=*/ 1,
/*instanceId=*/ 2, packageName});
- DatabaseUtils.sFakeSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = new Supplier<>() {
+ private int mTimes = 0;
+ @Override
+ public Cursor get() {
+ mTimes++;
+ return mTimes <= 2 ? null : cursor;
+ }
+ };
final DataProcessManager dataProcessManager = new DataProcessManager(
- mContext, /*handler=*/ null, /*rawStartTimestamp=*/ 2L, /*callbackFunction=*/ null,
+ mContext, /*handler=*/ null, /*rawStartTimestamp=*/ 2L,
+ /*lastFullChargeTimestamp=*/ 1L, /*callbackFunction=*/ null,
hourlyBatteryLevelsPerDay, /*batteryHistoryMap=*/ new HashMap<>());
dataProcessManager.start();
@@ -254,12 +288,13 @@ public final class DataProcessManagerTest {
assertThat(DataProcessManager.getBatteryLevelData(
mContext,
/*handler=*/ null,
- /*batteryHistoryMap=*/ null,
- /*asyncResponseDelegate=*/ null))
- .isNull();
+ /*isFromPeriodJob=*/ false,
+ /*asyncResponseDelegate=*/ null)).isNull();
assertThat(DataProcessManager.getBatteryLevelData(
- mContext, /*handler=*/ null, new HashMap<>(), /*asyncResponseDelegate=*/ null))
- .isNull();
+ mContext,
+ /*handler=*/ null,
+ /*isFromPeriodJob=*/ true,
+ /*asyncResponseDelegate=*/ null)).isNull();
}
@Test
@@ -270,18 +305,16 @@ public final class DataProcessManagerTest {
DateUtils.HOUR_IN_MILLIS * 2 - 200L,
DateUtils.HOUR_IN_MILLIS * 2 - 100L};
final int[] levels = {100, 99, 98};
- final Map> batteryHistoryMap =
- createHistoryMap(timestamps, levels);
+ DataProcessManager.sFakeBatteryHistoryMap = createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessManager.getBatteryLevelData(
mContext,
/*handler=*/ null,
- batteryHistoryMap,
+ /*isFromPeriodJob=*/ false,
/*asyncResponseDelegate=*/ null);
-
final List expectedDailyTimestamps = List.of(
DateUtils.HOUR_IN_MILLIS * 2 - 300L,
DateUtils.HOUR_IN_MILLIS * 2 - 100L);
@@ -301,15 +334,14 @@ public final class DataProcessManagerTest {
// Timezone GMT+8: 2022-01-01 00:00:00, 2022-01-01 01:00:00
final long[] timestamps = {1640966400000L, 1640970000000L};
final int[] levels = {100, 99};
- final Map> batteryHistoryMap =
- createHistoryMap(timestamps, levels);
+ DataProcessManager.sFakeBatteryHistoryMap = createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessManager.getBatteryLevelData(
mContext,
/*handler=*/ null,
- batteryHistoryMap,
+ /*isFromPeriodJob=*/ false,
/*asyncResponseDelegate=*/ null);
final List expectedDailyTimestamps = List.of(
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 c9b635eeb0e..c4394f76130 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -16,6 +16,9 @@
package com.android.settings.fuelgauge.batteryusage;
+import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.FAKE_PACKAGE_NAME;
+import static com.android.settingslib.fuelgauge.BatteryStatus.BATTERY_LEVEL_UNKNOWN;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.anyInt;
@@ -42,6 +45,7 @@ import android.os.BatteryUsageStats;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserManager;
+import android.util.ArrayMap;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -188,16 +192,18 @@ public final class DataProcessorTest {
final String packageName = "com.android.settings";
// Adds the day 1 data.
final List timestamps1 = List.of(14400000L, 18000000L, 21600000L);
- final List levels1 = List.of(100, 100, 100);
+ final Map batteryLevelMap1 =
+ Map.of(timestamps1.get(0), 100, timestamps1.get(1), 100, timestamps1.get(2), 100);
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps1, levels1));
+ new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap1, timestamps1));
// Adds the day 2 data.
hourlyBatteryLevelsPerDay.add(null);
// Adds the day 3 data.
final List timestamps2 = List.of(45200000L, 48800000L);
- final List levels2 = List.of(100, 100);
+ final Map batteryLevelMap2 =
+ Map.of(timestamps2.get(0), 100, timestamps2.get(1), 100);
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps2, levels2));
+ new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap2, timestamps2));
final List appUsageEventList = new ArrayList<>();
// Adds some events before the start timestamp.
appUsageEventList.add(buildAppUsageEvent(
@@ -285,7 +291,7 @@ public final class DataProcessorTest {
final List hourlyBatteryLevelsPerDay =
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
+ new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
assertThat(DataProcessor.generateAppUsagePeriodMap(
mContext, hourlyBatteryLevelsPerDay, new ArrayList<>(), new ArrayList<>()))
.isNull();
@@ -370,19 +376,6 @@ public final class DataProcessorTest {
DataProcessor.CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER)).isTrue();
}
- @Test
- public void getLevelDataThroughProcessedHistoryMap_notEnoughData_returnNull() {
- final long[] timestamps = {100L};
- final int[] levels = {100};
- final Map> batteryHistoryMap =
- createHistoryMap(timestamps, levels);
- DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
-
- assertThat(
- DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap))
- .isNull();
- }
-
@Test
public void getLevelDataThroughProcessedHistoryMap_OneDayData_returnExpectedResult() {
// Timezone GMT+8
@@ -441,7 +434,7 @@ public final class DataProcessorTest {
);
final List expectedDailyLevels = new ArrayList<>();
expectedDailyLevels.add(100);
- expectedDailyLevels.add(null);
+ expectedDailyLevels.add(BATTERY_LEVEL_UNKNOWN);
expectedDailyLevels.add(82);
final List> expectedHourlyTimestamps = List.of(
List.of(
@@ -459,13 +452,13 @@ public final class DataProcessorTest {
);
final List expectedHourlyLevels1 = new ArrayList<>();
expectedHourlyLevels1.add(100);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
final List expectedHourlyLevels2 = new ArrayList<>();
- expectedHourlyLevels2.add(null);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
expectedHourlyLevels2.add(94);
expectedHourlyLevels2.add(90);
- expectedHourlyLevels2.add(null);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
expectedHourlyLevels2.add(82);
final List> expectedHourlyLevels = List.of(
expectedHourlyLevels1,
@@ -503,8 +496,8 @@ public final class DataProcessorTest {
);
final List expectedDailyLevels = new ArrayList<>();
expectedDailyLevels.add(100);
- expectedDailyLevels.add(null);
- expectedDailyLevels.add(null);
+ expectedDailyLevels.add(BATTERY_LEVEL_UNKNOWN);
+ expectedDailyLevels.add(BATTERY_LEVEL_UNKNOWN);
expectedDailyLevels.add(88);
final List> expectedHourlyTimestamps = List.of(
List.of(
@@ -542,32 +535,32 @@ public final class DataProcessorTest {
);
final List expectedHourlyLevels1 = new ArrayList<>();
expectedHourlyLevels1.add(100);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
- expectedHourlyLevels1.add(null);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
final List expectedHourlyLevels2 = new ArrayList<>();
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
final List expectedHourlyLevels3 = new ArrayList<>();
- expectedHourlyLevels3.add(null);
- expectedHourlyLevels3.add(null);
- expectedHourlyLevels3.add(null);
+ expectedHourlyLevels3.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels3.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels3.add(BATTERY_LEVEL_UNKNOWN);
expectedHourlyLevels3.add(88);
final List> expectedHourlyLevels = List.of(
expectedHourlyLevels1,
@@ -606,8 +599,8 @@ public final class DataProcessorTest {
);
final List expectedDailyLevels = new ArrayList<>();
expectedDailyLevels.add(100);
- expectedDailyLevels.add(null);
- expectedDailyLevels.add(null);
+ expectedDailyLevels.add(BATTERY_LEVEL_UNKNOWN);
+ expectedDailyLevels.add(BATTERY_LEVEL_UNKNOWN);
expectedDailyLevels.add(88);
final List> expectedHourlyTimestamps = List.of(
List.of(
@@ -638,25 +631,25 @@ public final class DataProcessorTest {
);
final List expectedHourlyLevels1 = new ArrayList<>();
expectedHourlyLevels1.add(100);
- expectedHourlyLevels1.add(null);
+ expectedHourlyLevels1.add(BATTERY_LEVEL_UNKNOWN);
final List expectedHourlyLevels2 = new ArrayList<>();
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
- expectedHourlyLevels2.add(null);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels2.add(BATTERY_LEVEL_UNKNOWN);
final List expectedHourlyLevels3 = new ArrayList<>();
- expectedHourlyLevels3.add(null);
- expectedHourlyLevels3.add(null);
- expectedHourlyLevels3.add(null);
+ expectedHourlyLevels3.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels3.add(BATTERY_LEVEL_UNKNOWN);
+ expectedHourlyLevels3.add(BATTERY_LEVEL_UNKNOWN);
expectedHourlyLevels3.add(88);
final List> expectedHourlyLevels = List.of(
expectedHourlyLevels1,
@@ -734,141 +727,6 @@ public final class DataProcessorTest {
verifyExpectedTimestampSlots(startTimestamp, endTimestamp, expectedTimestamps);
}
- @Test
- public void getDailyTimestamps_notEnoughData_returnEmptyList() {
- assertThat(DataProcessor.getDailyTimestamps(new ArrayList<>())).isEmpty();
- assertThat(DataProcessor.getDailyTimestamps(List.of(100L))).isEmpty();
- }
-
- @Test
- public void getDailyTimestamps_allDataInOneHour_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1640970006000L, // 2022-01-01 01:00:06
- 1640973608000L // 2022-01-01 01:00:08
- );
-
- final List expectedTimestamps = List.of(
- 1640970006000L, // 2022-01-01 01:00:06
- 1640973608000L // 2022-01-01 01:00:08
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
- @Test
- public void getDailyTimestamps_OneHourDataPerDay_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1641049200000L, // 2022-01-01 23:00:00
- 1641052800000L, // 2022-01-02 00:00:00
- 1641056400000L // 2022-01-02 01:00:00
- );
-
- final List expectedTimestamps = List.of(
- 1641049200000L, // 2022-01-01 23:00:00
- 1641052800000L, // 2022-01-02 00:00:00
- 1641056400000L // 2022-01-02 01:00:00
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
- @Test
- public void getDailyTimestamps_OneDayData_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1640966400000L, // 2022-01-01 00:00:00
- 1640970000000L, // 2022-01-01 01:00:00
- 1640973600000L, // 2022-01-01 02:00:00
- 1640977200000L, // 2022-01-01 03:00:00
- 1640980800000L // 2022-01-01 04:00:00
- );
-
- final List expectedTimestamps = List.of(
- 1640966400000L, // 2022-01-01 00:00:00
- 1640980800000L // 2022-01-01 04:00:00
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
- @Test
- public void getDailyTimestamps_MultipleDaysData_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1641045600000L, // 2022-01-01 22:00:00
- 1641060000000L, // 2022-01-02 02:00:00
- 1641160800000L, // 2022-01-03 06:00:00
- 1641232800000L // 2022-01-04 02:00:00
- );
-
- final List expectedTimestamps = List.of(
- 1641045600000L, // 2022-01-01 22:00:00
- 1641052800000L, // 2022-01-02 00:00:00
- 1641139200000L, // 2022-01-03 00:00:00
- 1641225600000L, // 2022-01-04 00:00:00
- 1641232800000L // 2022-01-04 02:00:00
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
- @Test
- public void getDailyTimestamps_FirstDayOneHourData_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1641049200000L, // 2022-01-01 23:00:00
- 1641060000000L, // 2022-01-02 02:00:00
- 1641160800000L, // 2022-01-03 06:00:00
- 1641254400000L // 2022-01-04 08:00:00
- );
-
- final List expectedTimestamps = List.of(
- 1641049200000L, // 2022-01-01 23:00:00
- 1641052800000L, // 2022-01-02 00:00:00
- 1641139200000L, // 2022-01-03 00:00:00
- 1641225600000L, // 2022-01-04 00:00:00
- 1641254400000L // 2022-01-04 08:00:00
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
- @Test
- public void getDailyTimestamps_LastDayNoData_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1640988000000L, // 2022-01-01 06:00:00
- 1641060000000L, // 2022-01-02 02:00:00
- 1641160800000L, // 2022-01-03 06:00:00
- 1641225600000L // 2022-01-04 00:00:00
- );
-
- final List expectedTimestamps = List.of(
- 1640988000000L, // 2022-01-01 06:00:00
- 1641052800000L, // 2022-01-02 00:00:00
- 1641139200000L, // 2022-01-03 00:00:00
- 1641225600000L // 2022-01-04 00:00:00
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
- @Test
- public void getDailyTimestamps_LastDayOneHourData_returnExpectedList() {
- // Timezone GMT+8
- final List timestamps = List.of(
- 1640988000000L, // 2022-01-01 06:00:00
- 1641060000000L, // 2022-01-02 02:00:00
- 1641160800000L, // 2022-01-03 06:00:00
- 1641229200000L // 2022-01-04 01:00:00
- );
-
- final List expectedTimestamps = List.of(
- 1640988000000L, // 2022-01-01 06:00:00
- 1641052800000L, // 2022-01-02 00:00:00
- 1641139200000L, // 2022-01-03 00:00:00
- 1641225600000L, // 2022-01-04 00:00:00
- 1641229200000L // 2022-01-04 01:00:00
- );
- assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
- }
-
@Test
public void isFromFullCharge_emptyData_returnFalse() {
assertThat(DataProcessor.isFromFullCharge(null)).isFalse();
@@ -916,20 +774,53 @@ public final class DataProcessorTest {
}
@Test
- public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
+ public void getBatteryDiffDataMap_emptyHistoryMap_returnEmpty() {
final List hourlyBatteryLevelsPerDay =
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
+ new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
- assertThat(DataProcessor.getBatteryUsageMap(
- mContext, hourlyBatteryLevelsPerDay, new HashMap<>(), /*appUsagePeriodMap=*/ null))
- .isNull();
+ assertThat(DataProcessor.getBatteryDiffDataMap(mContext, hourlyBatteryLevelsPerDay,
+ new HashMap<>(), /*appUsagePeriodMap=*/ null, Set.of(), Set.of())).isEmpty();
}
@Test
- public void getBatteryUsageMap_returnsExpectedResult() {
+ public void getBatteryDiffDataMap_normalFlow_returnExpectedResult() {
+ final int userId = mContext.getUserId();
+ 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
+ };
+ final Map> batteryHistoryMap = Map.of(
+ batteryHistoryKeys[0], Map.of(FAKE_PACKAGE_NAME, createBatteryHistEntry(
+ FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 0, 0, 0,
+ 0, 0, 0L, userId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, 0L, 0L, false)),
+ batteryHistoryKeys[1], Map.of(FAKE_PACKAGE_NAME, createBatteryHistEntry(
+ FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 5, 0, 0,
+ 0, 0, 0L, userId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, 0L, 0L, false)),
+ batteryHistoryKeys[2], Map.of(FAKE_PACKAGE_NAME, createBatteryHistEntry(
+ FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 16, 0, 0,
+ 0, 0, 0L, userId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, 0L, 0L, false)));
+ final BatteryLevelData batteryLevelData = generateBatteryLevelData(batteryHistoryKeys);
+ final Map>>>>
+ appUsagePeriodMap = Map.of(0, Map.of(0, Map.of(Long.valueOf(userId), Map.of(
+ FAKE_PACKAGE_NAME, List.of(buildAppUsagePeriod(0, 6))))));
+
+ Map batteryDiffDataMap = DataProcessor.getBatteryDiffDataMap(
+ mContext, batteryLevelData.getHourlyBatteryLevelsPerDay(), batteryHistoryMap,
+ appUsagePeriodMap, Set.of(), Set.of());
+
+ assertThat(batteryDiffDataMap).hasSize(1);
+ assertThat(batteryDiffDataMap).containsKey(batteryHistoryKeys[0]);
+ BatteryDiffData batteryDiffData = batteryDiffDataMap.get(batteryHistoryKeys[0]);
+ assertThat(batteryDiffData.getStartTimestamp()).isEqualTo(batteryHistoryKeys[0]);
+ assertThat(batteryDiffData.getEndTimestamp()).isEqualTo(batteryHistoryKeys[2]);
+ }
+
+ @Test
+ public void generateBatteryUsageMap_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641045600000L, // 2022-01-01 22:00:00
1641049200000L, // 2022-01-01 23:00:00
@@ -940,7 +831,7 @@ public final class DataProcessorTest {
final Map> batteryHistoryMap = new HashMap<>();
final int currentUserId = mContext.getUserId();
final BatteryHistEntry fakeEntry = createBatteryHistEntry(
- ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 0,
+ FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
@@ -1030,19 +921,7 @@ public final class DataProcessorTest {
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[4], entryMap);
- final List hourlyBatteryLevelsPerDay =
- new ArrayList<>();
- // Adds the day 1 data.
- List timestamps =
- List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
- final List 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 BatteryLevelData batteryLevelData = generateBatteryLevelData(batteryHistoryKeys);
// Adds app usage data to test screen on time.
final Map>>>>
appUsagePeriodMap = new HashMap<>();
@@ -1066,8 +945,12 @@ public final class DataProcessorTest {
appUsagePeriodMap.get(1).put(0, appUsageMap);
final Map> resultMap =
- DataProcessor.getBatteryUsageMap(
- mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap, appUsagePeriodMap);
+ DataProcessor.generateBatteryUsageMap(
+ mContext,
+ DataProcessor.getBatteryDiffDataMap(mContext,
+ batteryLevelData.getHourlyBatteryLevelsPerDay(), batteryHistoryMap,
+ appUsagePeriodMap, Set.of(), Set.of()),
+ batteryLevelData);
BatteryDiffData resultDiffData =
resultMap
@@ -1128,7 +1011,7 @@ public final class DataProcessorTest {
}
@Test
- public void getBatteryUsageMap_multipleUsers_returnsExpectedResult() {
+ public void generateBatteryUsageMap_multipleUsers_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
@@ -1217,17 +1100,15 @@ public final class DataProcessorTest {
/*backgroundUsageTimeInMs=*/ 30L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
- final List hourlyBatteryLevelsPerDay =
- new ArrayList<>();
- List timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
- final List levels = List.of(100, 100);
- hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
+ final BatteryLevelData batteryLevelData = generateBatteryLevelData(batteryHistoryKeys);
final Map> resultMap =
- DataProcessor.getBatteryUsageMap(
- mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap,
- /*appUsagePeriodMap=*/ null);
+ DataProcessor.generateBatteryUsageMap(
+ mContext,
+ DataProcessor.getBatteryDiffDataMap(mContext,
+ batteryLevelData.getHourlyBatteryLevelsPerDay(), batteryHistoryMap,
+ /*appUsagePeriodMap=*/ null, Set.of(), Set.of()),
+ batteryLevelData);
final BatteryDiffData resultDiffData =
resultMap
@@ -1247,7 +1128,7 @@ public final class DataProcessorTest {
}
@Test
- public void getBatteryUsageMap_usageTimeExceed_returnsExpectedResult() {
+ public void generateBatteryUsageMap_usageTimeExceed_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
@@ -1288,12 +1169,7 @@ public final class DataProcessorTest {
/*backgroundUsageTimeInMs=*/ 7200000L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
- final List hourlyBatteryLevelsPerDay =
- new ArrayList<>();
- List timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
- final List levels = List.of(100, 100);
- hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
+ final BatteryLevelData batteryLevelData = generateBatteryLevelData(batteryHistoryKeys);
// Adds app usage data to test screen on time.
final Map>>>>
@@ -1307,8 +1183,12 @@ public final class DataProcessorTest {
appUsagePeriodMap.get(0).put(0, appUsageMap);
final Map> resultMap =
- DataProcessor.getBatteryUsageMap(
- mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap, appUsagePeriodMap);
+ DataProcessor.generateBatteryUsageMap(
+ mContext,
+ DataProcessor.getBatteryDiffDataMap(mContext,
+ batteryLevelData.getHourlyBatteryLevelsPerDay(), batteryHistoryMap,
+ appUsagePeriodMap, Set.of(), Set.of()),
+ batteryLevelData);
final BatteryDiffData resultDiffData =
resultMap
@@ -1338,7 +1218,7 @@ public final class DataProcessorTest {
}
@Test
- public void getBatteryUsageMap_hideApplicationEntries_returnsExpectedResult() {
+ public void generateBatteryUsageMap_hideApplicationEntries_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
@@ -1403,19 +1283,17 @@ public final class DataProcessorTest {
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
- final List hourlyBatteryLevelsPerDay =
- new ArrayList<>();
- List timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
- final List levels = List.of(100, 100);
- hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
+ final BatteryLevelData batteryLevelData = generateBatteryLevelData(batteryHistoryKeys);
when(mPowerUsageFeatureProvider.getHideApplicationSet())
.thenReturn(Set.of("package1"));
final Map> resultMap =
- DataProcessor.getBatteryUsageMap(
- mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap,
- /*appUsagePeriodMap=*/ null);
+ DataProcessor.generateBatteryUsageMap(
+ mContext,
+ DataProcessor.getBatteryDiffDataMap(mContext,
+ batteryLevelData.getHourlyBatteryLevelsPerDay(), batteryHistoryMap,
+ /*appUsagePeriodMap=*/ null, Set.of(), Set.of()),
+ batteryLevelData);
final BatteryDiffData resultDiffData =
resultMap
@@ -1431,7 +1309,7 @@ public final class DataProcessorTest {
}
@Test
- public void getBatteryUsageMap_hideBackgroundUsageTime_returnsExpectedResult() {
+ public void generateBatteryUsageMap_hideBackgroundUsageTime_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
@@ -1496,19 +1374,17 @@ public final class DataProcessorTest {
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
- final List hourlyBatteryLevelsPerDay =
- new ArrayList<>();
- List timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
- final List levels = List.of(100, 100);
- hourlyBatteryLevelsPerDay.add(
- new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
+ final BatteryLevelData batteryLevelData = generateBatteryLevelData(batteryHistoryKeys);
when(mPowerUsageFeatureProvider.getHideBackgroundUsageTimeSet())
.thenReturn(new HashSet(Arrays.asList((CharSequence) "package2")));
final Map> resultMap =
- DataProcessor.getBatteryUsageMap(
- mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap,
- /*appUsagePeriodMap=*/ null);
+ DataProcessor.generateBatteryUsageMap(
+ mContext,
+ DataProcessor.getBatteryDiffDataMap(mContext,
+ batteryLevelData.getHourlyBatteryLevelsPerDay(), batteryHistoryMap,
+ /*appUsagePeriodMap=*/ null, Set.of(), Set.of()),
+ batteryLevelData);
final BatteryDiffData resultDiffData =
resultMap
@@ -1523,7 +1399,10 @@ public final class DataProcessorTest {
@Test
public void generateBatteryDiffData_emptyBatteryEntryList_returnNull() {
assertThat(DataProcessor.generateBatteryDiffData(mContext,
- DataProcessor.convertToBatteryHistEntry(null, mBatteryUsageStats))).isNull();
+ System.currentTimeMillis(),
+ DataProcessor.convertToBatteryHistEntry(null, mBatteryUsageStats),
+ /* systemAppsPackageNames= */ Set.of(),
+ /* systemAppsUids= */ Set.of())).isNull();
}
@Test
@@ -1574,7 +1453,10 @@ public final class DataProcessorTest {
.when(mMockBatteryEntry4).getPowerComponentId();
final BatteryDiffData batteryDiffData = DataProcessor.generateBatteryDiffData(mContext,
- DataProcessor.convertToBatteryHistEntry(batteryEntryList, mBatteryUsageStats));
+ System.currentTimeMillis(),
+ DataProcessor.convertToBatteryHistEntry(batteryEntryList, mBatteryUsageStats),
+ /* systemAppsPackageNames= */ Set.of(),
+ /* systemAppsUids= */ Set.of());
assertBatteryDiffEntry(
batteryDiffData.getAppDiffEntryList().get(0), 0, /*uid=*/ 2L,
@@ -2041,9 +1923,9 @@ public final class DataProcessorTest {
final double backgroundUsageConsumePower, final double cachedUsageConsumePower,
final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs,
final long screenOnTimeInMs) {
- assertThat(entry.mBatteryHistEntry.mUserId).isEqualTo(userId);
- assertThat(entry.mBatteryHistEntry.mUid).isEqualTo(uid);
- assertThat(entry.mBatteryHistEntry.mConsumerType).isEqualTo(consumerType);
+ assertThat(entry.mUserId).isEqualTo(userId);
+ assertThat(entry.mUid).isEqualTo(uid);
+ assertThat(entry.mConsumerType).isEqualTo(consumerType);
assertThat(entry.getPercentage()).isEqualTo(consumePercentage);
assertThat(entry.mForegroundUsageConsumePower).isEqualTo(foregroundUsageConsumePower);
assertThat(entry.mForegroundServiceUsageConsumePower)
@@ -2054,4 +1936,12 @@ public final class DataProcessorTest {
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
assertThat(entry.mScreenOnTimeInMs).isEqualTo(screenOnTimeInMs);
}
+
+ private BatteryLevelData generateBatteryLevelData(long[] timestamps) {
+ Map batteryLevelMap = new ArrayMap<>();
+ for (long timestamp : timestamps) {
+ batteryLevelMap.put(timestamp, 100);
+ }
+ return new BatteryLevelData(batteryLevelMap);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
index 8a1ba137958..f72b333b570 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
@@ -173,8 +173,8 @@ public final class DatabaseUtilsTest {
doReturn(null).when(mContext).registerReceiver(any(), any());
assertThat(
DatabaseUtils.sendBatteryEntryData(
- mContext, /*batteryEntryList=*/ null, mBatteryUsageStats,
- /*isFullChargeStart=*/ false))
+ mContext, System.currentTimeMillis(), /*batteryEntryList=*/ null,
+ mBatteryUsageStats, /*isFullChargeStart=*/ false))
.isNull();
}
@@ -193,7 +193,10 @@ public final class DatabaseUtilsTest {
final List valuesList =
DatabaseUtils.sendBatteryEntryData(
- mContext, batteryEntryList, mBatteryUsageStats,
+ mContext,
+ System.currentTimeMillis(),
+ batteryEntryList,
+ mBatteryUsageStats,
/*isFullChargeStart=*/ false);
assertThat(valuesList).hasSize(2);
@@ -216,6 +219,7 @@ public final class DatabaseUtilsTest {
final List valuesList =
DatabaseUtils.sendBatteryEntryData(
mContext,
+ System.currentTimeMillis(),
new ArrayList<>(),
mBatteryUsageStats,
/*isFullChargeStart=*/ false);
@@ -235,6 +239,7 @@ public final class DatabaseUtilsTest {
final List valuesList =
DatabaseUtils.sendBatteryEntryData(
mContext,
+ System.currentTimeMillis(),
/*batteryEntryList=*/ null,
mBatteryUsageStats,
/*isFullChargeStart=*/ false);
@@ -254,6 +259,7 @@ public final class DatabaseUtilsTest {
final List valuesList =
DatabaseUtils.sendBatteryEntryData(
mContext,
+ System.currentTimeMillis(),
/*batteryEntryList=*/ null,
/*batteryUsageStats=*/ null,
/*isFullChargeStart=*/ false);
@@ -359,7 +365,7 @@ public final class DatabaseUtilsTest {
}
@Test
- public void getHistoryMapSinceLastFullCharge_emptyCursorContent_returnEmptyMap() {
+ public void getHistoryMap_emptyCursorContent_returnEmptyMap() {
final MatrixCursor cursor = new MatrixCursor(
new String[] {
BatteryHistEntry.KEY_UID,
@@ -367,36 +373,33 @@ public final class DatabaseUtilsTest {
BatteryHistEntry.KEY_TIMESTAMP});
DatabaseUtils.sFakeSupplier = () -> cursor;
- assertThat(DatabaseUtils.getHistoryMapSinceLastFullCharge(
- mContext, /*calendar=*/ null)).isEmpty();
+ assertThat(DatabaseUtils.getHistoryMapSinceQueryTimestamp(mContext, 0)).isEmpty();
}
@Test
- public void getHistoryMapSinceLastFullCharge_nullCursor_returnEmptyMap() {
+ public void getHistoryMap_nullCursor_returnEmptyMap() {
DatabaseUtils.sFakeSupplier = () -> null;
- assertThat(DatabaseUtils.getHistoryMapSinceLastFullCharge(
- mContext, /*calendar=*/ null)).isEmpty();
+ assertThat(DatabaseUtils.getHistoryMapSinceQueryTimestamp(mContext, 0)).isEmpty();
}
@Test
- public void getHistoryMapSinceLastFullCharge_returnExpectedMap() {
+ public void getHistoryMap_returnExpectedMap() {
final Long timestamp1 = Long.valueOf(1001L);
final Long timestamp2 = Long.valueOf(1002L);
final MatrixCursor cursor = getMatrixCursor();
// Adds fake data into the cursor.
cursor.addRow(new Object[] {
- "app name1", timestamp1, 1, ConvertUtils.CONSUMER_TYPE_UID_BATTERY});
+ "app name1", timestamp1, 1, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, true});
cursor.addRow(new Object[] {
- "app name2", timestamp2, 2, ConvertUtils.CONSUMER_TYPE_UID_BATTERY});
+ "app name2", timestamp2, 2, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, false});
cursor.addRow(new Object[] {
- "app name3", timestamp2, 3, ConvertUtils.CONSUMER_TYPE_UID_BATTERY});
+ "app name3", timestamp2, 3, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, false});
cursor.addRow(new Object[] {
- "app name4", timestamp2, 4, ConvertUtils.CONSUMER_TYPE_UID_BATTERY});
+ "app name4", timestamp2, 4, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, false});
DatabaseUtils.sFakeSupplier = () -> cursor;
final Map> batteryHistMap =
- DatabaseUtils.getHistoryMapSinceLastFullCharge(
- mContext, /*calendar=*/ null);
+ DatabaseUtils.getHistoryMapSinceQueryTimestamp(mContext, timestamp1);
assertThat(batteryHistMap).hasSize(2);
// Verifies the BatteryHistEntry data for timestamp1.
@@ -412,7 +415,7 @@ public final class DatabaseUtilsTest {
}
@Test
- public void getHistoryMapSinceLastFullCharge_withWorkProfile_returnExpectedMap()
+ public void getHistoryMap_withWorkProfile_returnExpectedMap()
throws PackageManager.NameNotFoundException {
doReturn("com.fake.package").when(mContext).getPackageName();
doReturn(mMockContext).when(mContext).createPackageContextAsUser(
@@ -425,8 +428,7 @@ public final class DatabaseUtilsTest {
DatabaseUtils.sFakeSupplier = () -> getMatrixCursor();
final Map> batteryHistMap =
- DatabaseUtils.getHistoryMapSinceLastFullCharge(
- mContext, /*calendar=*/ null);
+ DatabaseUtils.getHistoryMapSinceQueryTimestamp(mContext, 0);
assertThat(batteryHistMap).isEmpty();
}
@@ -571,6 +573,7 @@ public final class DatabaseUtilsTest {
BatteryHistEntry.KEY_PACKAGE_NAME,
BatteryHistEntry.KEY_TIMESTAMP,
BatteryHistEntry.KEY_UID,
- BatteryHistEntry.KEY_CONSUMER_TYPE});
+ BatteryHistEntry.KEY_CONSUMER_TYPE,
+ BatteryHistEntry.KEY_IS_FULL_CHARGE_CYCLE_START});
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java
index 6ed10cd2b9b..68766e69dac 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java
@@ -134,11 +134,6 @@ public class PowerUsageBaseTest {
return 0;
}
- @Override
- protected boolean isBatteryHistoryNeeded() {
- return false;
- }
-
@Override
protected void refreshUi(int refreshType) {
// Do nothing
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDaoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDaoTest.java
index 941f444e552..84628670af1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDaoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDaoTest.java
@@ -16,6 +16,10 @@
package com.android.settings.fuelgauge.batteryusage.db;
+import static com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity.KEY_BATTERY_EVENT_TYPE;
+import static com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity.KEY_BATTERY_LEVEL;
+import static com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity.KEY_TIMESTAMP;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
@@ -31,9 +35,14 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
+import java.util.List;
+
/** Tests for {@link BatteryEventDao}. */
@RunWith(RobolectricTestRunner.class)
public final class BatteryEventDaoTest {
+ private static final long TIMESTAMP1 = System.currentTimeMillis();
+ private static final long TIMESTAMP2 = TIMESTAMP1 + 2;
+
private Context mContext;
private BatteryStateDatabase mDatabase;
private BatteryEventDao mBatteryEventDao;
@@ -51,8 +60,44 @@ public final class BatteryEventDaoTest {
BatteryStateDatabase.setBatteryStateDatabase(/*database=*/ null);
}
+
@Test
- public void getAllAfter_returnExpectedResult() {
+ public void getLastFullChargeTimestamp_normalFlow_expectedBehavior() throws Exception {
+ mBatteryEventDao.insert(BatteryEventEntity.newBuilder()
+ .setTimestamp(TIMESTAMP1)
+ .setBatteryEventType(3)
+ .setBatteryLevel(100)
+ .build());
+ mBatteryEventDao.insert(BatteryEventEntity.newBuilder()
+ .setTimestamp(TIMESTAMP2)
+ .setBatteryEventType(4)
+ .setBatteryLevel(96)
+ .build());
+
+ final Cursor cursor = mBatteryEventDao.getLastFullChargeTimestamp();
+ assertThat(cursor.getCount()).isEqualTo(1);
+ cursor.moveToFirst();
+ assertThat(cursor.getLong(0)).isEqualTo(TIMESTAMP1);
+ }
+
+ @Test
+ public void getLastFullChargeTimestamp_noLastFullChargeTime_returns0() throws Exception {
+ mBatteryEventDao.clearAll();
+ mBatteryEventDao.insert(BatteryEventEntity.newBuilder()
+ .setTimestamp(TIMESTAMP2)
+ .setBatteryEventType(4)
+ .setBatteryLevel(96)
+ .build());
+
+ final Cursor cursor = mBatteryEventDao.getLastFullChargeTimestamp();
+
+ assertThat(cursor.getCount()).isEqualTo(1);
+ cursor.moveToFirst();
+ assertThat(cursor.getLong(0)).isEqualTo(0L);
+ }
+
+ @Test
+ public void getAllAfter_normalFlow_returnExpectedResult() {
mBatteryEventDao.insert(BatteryEventEntity.newBuilder()
.setTimestamp(100L)
.setBatteryEventType(1)
@@ -64,17 +109,44 @@ public final class BatteryEventDaoTest {
.setBatteryLevel(88)
.build());
- final Cursor cursor = mBatteryEventDao.getAllAfter(160L);
+ final Cursor cursor = mBatteryEventDao.getAllAfter(160L, List.of(1, 2));
assertThat(cursor.getCount()).isEqualTo(1);
cursor.moveToFirst();
- assertThat(cursor.getLong(cursor.getColumnIndex(BatteryEventEntity.KEY_TIMESTAMP)))
+ assertThat(cursor.getLong(cursor.getColumnIndex(KEY_TIMESTAMP)))
.isEqualTo(200L);
- assertThat(cursor.getInt(cursor.getColumnIndex(BatteryEventEntity.KEY_BATTERY_EVENT_TYPE)))
+ assertThat(cursor.getInt(cursor.getColumnIndex(KEY_BATTERY_EVENT_TYPE)))
.isEqualTo(2);
- assertThat(cursor.getInt(cursor.getColumnIndex(BatteryEventEntity.KEY_BATTERY_LEVEL)))
+ assertThat(cursor.getInt(cursor.getColumnIndex(KEY_BATTERY_LEVEL)))
.isEqualTo(88);
mBatteryEventDao.clearAll();
assertThat(mBatteryEventDao.getAll()).isEmpty();
}
+
+ @Test
+ public void getAllAfter_filterBatteryTypes_returnExpectedResult() {
+ mBatteryEventDao.insert(BatteryEventEntity.newBuilder()
+ .setTimestamp(100L)
+ .setBatteryEventType(1)
+ .setBatteryLevel(66)
+ .build());
+ mBatteryEventDao.insert(BatteryEventEntity.newBuilder()
+ .setTimestamp(200L)
+ .setBatteryEventType(2)
+ .setBatteryLevel(88)
+ .build());
+
+ final Cursor cursor = mBatteryEventDao.getAllAfter(0L, List.of(1));
+ assertThat(cursor.getCount()).isEqualTo(1);
+ cursor.moveToFirst();
+ assertThat(cursor.getLong(cursor.getColumnIndex(KEY_TIMESTAMP)))
+ .isEqualTo(100L);
+ assertThat(cursor.getInt(cursor.getColumnIndex(KEY_BATTERY_EVENT_TYPE)))
+ .isEqualTo(1);
+ assertThat(cursor.getInt(cursor.getColumnIndex(KEY_BATTERY_LEVEL)))
+ .isEqualTo(66);
+
+ mBatteryEventDao.clearAll();
+ assertThat(mBatteryEventDao.getAll()).isEmpty();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDaoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDaoTest.java
index 57cf648c07a..b3dba4e56da 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDaoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDaoTest.java
@@ -37,9 +37,10 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public final class BatteryStateDaoTest {
private static final int CURSOR_COLUMN_SIZE = 9;
- private static final long TIMESTAMP1 = System.currentTimeMillis();
- private static final long TIMESTAMP2 = System.currentTimeMillis() + 2;
- private static final long TIMESTAMP3 = System.currentTimeMillis() + 4;
+ private static final long CURRENT = System.currentTimeMillis();
+ private static final long TIMESTAMP1 = CURRENT;
+ private static final long TIMESTAMP2 = CURRENT + 2;
+ private static final long TIMESTAMP3 = CURRENT + 4;
private static final String PACKAGE_NAME1 = "com.android.apps.settings";
private static final String PACKAGE_NAME2 = "com.android.apps.calendar";
private static final String PACKAGE_NAME3 = "com.android.apps.gmail";
@@ -67,7 +68,7 @@ public final class BatteryStateDaoTest {
}
@Test
- public void batteryStateDao_insertAll() throws Exception {
+ public void insertAll_normalFlow_expectedBehavior() throws Exception {
final List states = mBatteryStateDao.getAllAfter(TIMESTAMP1);
assertThat(states).hasSize(2);
// Verifies the queried battery states.
@@ -76,8 +77,26 @@ public final class BatteryStateDaoTest {
}
@Test
- public void batteryStateDao_getCursorSinceLastFullCharge() throws Exception {
- final Cursor cursor1 = mBatteryStateDao.getCursorSinceLastFullCharge(TIMESTAMP1);
+ public void getLatestTimestamp_normalFlow_expectedBehavior() throws Exception {
+ final Cursor cursor1 = mBatteryStateDao.getLatestTimestampBefore(TIMESTAMP1 - 1);
+ assertThat(cursor1.getCount()).isEqualTo(1);
+ cursor1.moveToFirst();
+ assertThat(cursor1.getLong(0)).isEqualTo(0L);
+
+ final Cursor cursor2 = mBatteryStateDao.getLatestTimestampBefore(TIMESTAMP2);
+ assertThat(cursor2.getCount()).isEqualTo(1);
+ cursor2.moveToFirst();
+ assertThat(cursor2.getLong(0)).isEqualTo(TIMESTAMP2);
+
+ final Cursor cursor3 = mBatteryStateDao.getLatestTimestampBefore(TIMESTAMP3 + 1);
+ assertThat(cursor3.getCount()).isEqualTo(1);
+ cursor3.moveToFirst();
+ assertThat(cursor3.getLong(0)).isEqualTo(TIMESTAMP3);
+ }
+
+ @Test
+ public void getBatteryStatesAfter_normalFlow_expectedBehavior() throws Exception {
+ final Cursor cursor1 = mBatteryStateDao.getBatteryStatesAfter(TIMESTAMP1);
assertThat(cursor1.getCount()).isEqualTo(3);
assertThat(cursor1.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
// Verifies the queried first battery state.
@@ -90,7 +109,7 @@ public final class BatteryStateDaoTest {
cursor1.moveToNext();
assertThat(cursor1.getString(3 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
- final Cursor cursor2 = mBatteryStateDao.getCursorSinceLastFullCharge(TIMESTAMP3);
+ final Cursor cursor2 = mBatteryStateDao.getBatteryStatesAfter(TIMESTAMP3);
assertThat(cursor2.getCount()).isEqualTo(1);
assertThat(cursor2.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
// Verifies the queried first battery state.
@@ -99,25 +118,7 @@ public final class BatteryStateDaoTest {
}
@Test
- public void batteryStateDao_getCursorSinceLastFullCharge_noFullChargeData_returnSevenDaysData()
- throws Exception {
- mBatteryStateDao.clearAll();
- BatteryTestUtils.insertDataToBatteryStateTable(mContext, TIMESTAMP3, PACKAGE_NAME3);
- BatteryTestUtils.insertDataToBatteryStateTable(mContext, TIMESTAMP2, PACKAGE_NAME2);
- BatteryTestUtils.insertDataToBatteryStateTable(mContext, TIMESTAMP1, PACKAGE_NAME1);
- final Cursor cursor = mBatteryStateDao.getCursorSinceLastFullCharge(TIMESTAMP2);
- assertThat(cursor.getCount()).isEqualTo(2);
- assertThat(cursor.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
- // Verifies the queried first battery state.
- cursor.moveToFirst();
- assertThat(cursor.getString(3 /*packageName*/)).isEqualTo(PACKAGE_NAME2);
- // Verifies the queried third battery state.
- cursor.moveToNext();
- assertThat(cursor.getString(3 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
- }
-
- @Test
- public void batteryStateDao_clearAllBefore() throws Exception {
+ public void clearAllBefore_normalFlow_expectedBehavior() throws Exception {
mBatteryStateDao.clearAllBefore(TIMESTAMP2);
final List states = mBatteryStateDao.getAllAfter(0);
@@ -127,20 +128,20 @@ public final class BatteryStateDaoTest {
}
@Test
- public void batteryStateDao_clearAll() throws Exception {
+ public void clearAll_normalFlow_expectedBehavior() throws Exception {
assertThat(mBatteryStateDao.getAllAfter(0)).hasSize(3);
mBatteryStateDao.clearAll();
assertThat(mBatteryStateDao.getAllAfter(0)).isEmpty();
}
@Test
- public void getInstance_createNewInstance() throws Exception {
+ public void getInstance_createNewInstance_returnsExpectedResult() throws Exception {
BatteryStateDatabase.setBatteryStateDatabase(/*database=*/ null);
assertThat(BatteryStateDatabase.getInstance(mContext)).isNotNull();
}
@Test
- public void getDistinctTimestampCount_returnsExpectedResult() {
+ public void getDistinctTimestampCount_normalFlow_returnsExpectedResult() {
assertThat(mBatteryStateDao.getDistinctTimestampCount(/*timestamp=*/ 0))
.isEqualTo(3);
assertThat(mBatteryStateDao.getDistinctTimestampCount(TIMESTAMP1))
@@ -148,7 +149,7 @@ public final class BatteryStateDaoTest {
}
@Test
- public void getDistinctTimestamps_returnsExpectedResult() {
+ public void getDistinctTimestamps_normalFlow_returnsExpectedResult() {
final List timestamps =
mBatteryStateDao.getDistinctTimestamps(/*timestamp=*/ 0);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDaoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDaoTest.java
new file mode 100644
index 00000000000..6f739546a5f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDaoTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage.db;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.database.Cursor;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.testutils.BatteryTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+/** Tests for {@link BatteryUsageSlotDao}. */
+@RunWith(RobolectricTestRunner.class)
+public final class BatteryUsageSlotDaoTest {
+ private static final int CURSOR_COLUMN_SIZE = 3;
+ private static final long CURRENT = System.currentTimeMillis();
+ private static final long TIMESTAMP1 = CURRENT;
+ private static final long TIMESTAMP2 = CURRENT + 2;
+ private static final String BATTERY_USAGE_SLOT_STRING1 = "BATTERY_USAGE_SLOT_STRING1";
+ private static final String BATTERY_USAGE_SLOT_STRING2 = "BATTERY_USAGE_SLOT_STRING2";
+
+ private Context mContext;
+ private BatteryStateDatabase mDatabase;
+ private BatteryUsageSlotDao mBatteryUsageSlotDao;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mDatabase = BatteryTestUtils.setUpBatteryStateDatabase(mContext);
+ mBatteryUsageSlotDao = mDatabase.batteryUsageSlotDao();
+ mBatteryUsageSlotDao.insert(
+ new BatteryUsageSlotEntity(TIMESTAMP1, BATTERY_USAGE_SLOT_STRING1));
+ mBatteryUsageSlotDao.insert(
+ new BatteryUsageSlotEntity(TIMESTAMP2, BATTERY_USAGE_SLOT_STRING2));
+ }
+
+ @After
+ public void closeDb() {
+ mDatabase.close();
+ BatteryStateDatabase.setBatteryStateDatabase(/*database=*/ null);
+ }
+
+ @Test
+ public void getAll_normalFlow_expectedBehavior() throws Exception {
+ final List entities = mBatteryUsageSlotDao.getAll();
+ assertThat(entities).hasSize(2);
+ assertThat(entities.get(0).timestamp).isEqualTo(TIMESTAMP1);
+ assertThat(entities.get(0).batteryUsageSlot).isEqualTo(BATTERY_USAGE_SLOT_STRING1);
+ assertThat(entities.get(1).timestamp).isEqualTo(TIMESTAMP2);
+ assertThat(entities.get(1).batteryUsageSlot).isEqualTo(BATTERY_USAGE_SLOT_STRING2);
+ }
+
+ @Test
+ public void getAllAfter_normalFlow_expectedBehavior() throws Exception {
+ final Cursor cursor1 = mBatteryUsageSlotDao.getAllAfter(TIMESTAMP1);
+ assertThat(cursor1.getCount()).isEqualTo(2);
+ assertThat(cursor1.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
+ cursor1.moveToFirst();
+ assertThat(cursor1.getLong(1 /*timestamp*/)).isEqualTo(TIMESTAMP1);
+ cursor1.moveToNext();
+ assertThat(cursor1.getLong(1 /*timestamp*/)).isEqualTo(TIMESTAMP2);
+
+ final Cursor cursor2 = mBatteryUsageSlotDao.getAllAfter(TIMESTAMP1 + 1);
+ assertThat(cursor2.getCount()).isEqualTo(1);
+ assertThat(cursor2.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
+ cursor2.moveToFirst();
+ assertThat(cursor2.getLong(1 /*timestamp*/)).isEqualTo(TIMESTAMP2);
+ }
+
+ @Test
+ public void clearAllBefore_normalFlow_expectedBehavior() throws Exception {
+ mBatteryUsageSlotDao.clearAllBefore(TIMESTAMP1);
+
+ final List entities = mBatteryUsageSlotDao.getAll();
+ assertThat(entities).hasSize(1);
+ assertThat(entities.get(0).timestamp).isEqualTo(TIMESTAMP2);
+ assertThat(entities.get(0).batteryUsageSlot).isEqualTo(BATTERY_USAGE_SLOT_STRING2);
+ }
+
+ @Test
+ public void clearAll_normalFlow_expectedBehavior() throws Exception {
+ mBatteryUsageSlotDao.clearAll();
+
+ assertThat(mBatteryUsageSlotDao.getAll()).isEmpty();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotEntityTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotEntityTest.java
new file mode 100644
index 00000000000..ef276eb186e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotEntityTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage.db;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link BatteryUsageSlotEntity}. */
+@RunWith(RobolectricTestRunner.class)
+public final class BatteryUsageSlotEntityTest {
+
+ @Test
+ public void testBuilder_returnsExpectedResult() {
+ final long timestamp = 10001L;
+ final String batteryUsageSlotString = "batteryUsageSlotString";
+
+ BatteryUsageSlotEntity entity = BatteryUsageSlotEntity
+ .newBuilder()
+ .setTimestamp(timestamp)
+ .setBatteryUsageSlot(batteryUsageSlotString)
+ .build();
+
+ // Verifies the app relative information.
+ assertThat(entity.timestamp).isEqualTo(timestamp);
+ assertThat(entity.batteryUsageSlot).isEqualTo(batteryUsageSlotString);
+ }
+}