Exclude screen on time in battery usage page when the device is in charging.

Bug: 265751163
Fix: 265751163
Test: manual
Change-Id: I4ed71e1d6fad56a7cbfc9cd47ed4d791f45261ce
This commit is contained in:
Zaiyue Xue
2023-02-27 16:29:04 +08:00
parent 39dd52d468
commit ff11b8e307
20 changed files with 809 additions and 52 deletions

View File

@@ -94,6 +94,14 @@ public final class DataProcessor {
@VisibleForTesting
static final int SELECTED_INDEX_ALL = BatteryChartViewModel.SELECTED_INDEX_ALL;
@VisibleForTesting
static final Comparator<AppUsageEvent> APP_USAGE_EVENT_TIMESTAMP_COMPARATOR =
Comparator.comparing(AppUsageEvent::getTimestamp);
@VisibleForTesting
static final Comparator<BatteryEvent> BATTERY_EVENT_TIMESTAMP_COMPARATOR =
Comparator.comparing(BatteryEvent::getTimestamp);
@VisibleForTesting
static boolean sDebug = false;
@@ -110,8 +118,6 @@ public final class DataProcessor {
public static final String CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER =
"CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER";
public static final Comparator<AppUsageEvent> TIMESTAMP_COMPARATOR =
Comparator.comparing(AppUsageEvent::getTimestamp);
/** A callback listener when battery usage loading async task is executed. */
public interface UsageMapAsyncResponse {
@@ -266,14 +272,16 @@ public final class DataProcessor {
generateAppUsagePeriodMap(
final long rawStartTimestamp,
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
final List<AppUsageEvent> appUsageEventList) {
final List<AppUsageEvent> appUsageEventList,
final List<BatteryEvent> batteryEventList) {
if (appUsageEventList.isEmpty()) {
Log.w(TAG, "appUsageEventList is empty");
return null;
}
// Sorts the appUsageEventList in ascending order based on the timestamp before
// distribution.
Collections.sort(appUsageEventList, TIMESTAMP_COMPARATOR);
// Sorts the appUsageEventList and batteryEventList in ascending order based on the
// timestamp before distribution.
Collections.sort(appUsageEventList, APP_USAGE_EVENT_TIMESTAMP_COMPARATOR);
Collections.sort(batteryEventList, BATTERY_EVENT_TIMESTAMP_COMPARATOR);
final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>> resultMap =
new ArrayMap<>();
@@ -309,8 +317,8 @@ public final class DataProcessor {
// The value could be null when there is no data in the hourly slot.
dailyMap.put(
hourlyIndex,
buildAppUsagePeriodList(
hourlyAppUsageEventList, startTimestamp, endTimestamp));
buildAppUsagePeriodList(hourlyAppUsageEventList, batteryEventList,
startTimestamp, endTimestamp));
}
}
return resultMap;
@@ -717,7 +725,8 @@ public final class DataProcessor {
@VisibleForTesting
@Nullable
static Map<Long, Map<String, List<AppUsagePeriod>>> buildAppUsagePeriodList(
final List<AppUsageEvent> allAppUsageEvents, final long startTime, final long endTime) {
final List<AppUsageEvent> allAppUsageEvents, final List<BatteryEvent> batteryEventList,
final long startTime, final long endTime) {
if (allAppUsageEvents.isEmpty()) {
return null;
}
@@ -763,12 +772,14 @@ public final class DataProcessor {
usageEvents.addAll(deviceEvents);
// Sorts the usageEvents in ascending order based on the timestamp before computing the
// period.
Collections.sort(usageEvents, TIMESTAMP_COMPARATOR);
Collections.sort(usageEvents, APP_USAGE_EVENT_TIMESTAMP_COMPARATOR);
// A package might have multiple instances. Computes the usage period per instance id
// and then merges them into the same user-package map.
final List<AppUsagePeriod> usagePeriodList =
buildAppUsagePeriodListPerInstance(usageEvents, startTime, endTime);
excludePowerConnectedTimeFromAppUsagePeriodList(
buildAppUsagePeriodListPerInstance(usageEvents, startTime, endTime),
batteryEventList);
if (!usagePeriodList.isEmpty()) {
addToUsagePeriodMap(allUsagePeriods, usagePeriodList, eventUserId, packageName);
}
@@ -836,6 +847,53 @@ public final class DataProcessor {
return usagePeriodList;
}
@VisibleForTesting
static List<AppUsagePeriod> excludePowerConnectedTimeFromAppUsagePeriodList(
final List<AppUsagePeriod> usagePeriodList,
final List<BatteryEvent> batteryEventList) {
final List<AppUsagePeriod> resultList = new ArrayList<>();
for (AppUsagePeriod inputPeriod : usagePeriodList) {
long lastStartTime = inputPeriod.getStartTime();
for (BatteryEvent batteryEvent : batteryEventList) {
if (batteryEvent.getTimestamp() < inputPeriod.getStartTime()) {
// Because the batteryEventList has been sorted, here is to mark the power
// connection state when the usage period starts. If power is connected when
// the usage period starts, the starting period will be ignored; otherwise it
// will be added.
if (batteryEvent.getType() == BatteryEventType.POWER_CONNECTED) {
lastStartTime = 0;
} else if (batteryEvent.getType() == BatteryEventType.POWER_DISCONNECTED) {
lastStartTime = inputPeriod.getStartTime();
}
continue;
}
if (batteryEvent.getTimestamp() > inputPeriod.getEndTime()) {
// Because the batteryEventList has been sorted, if any event is already after
// the end time, all the following events should be able to drop directly.
break;
}
if (batteryEvent.getType() == BatteryEventType.POWER_CONNECTED
&& lastStartTime != 0) {
resultList.add(AppUsagePeriod.newBuilder()
.setStartTime(lastStartTime)
.setEndTime(batteryEvent.getTimestamp())
.build());
lastStartTime = 0;
} else if (batteryEvent.getType() == BatteryEventType.POWER_DISCONNECTED) {
lastStartTime = batteryEvent.getTimestamp();
}
}
if (lastStartTime != 0) {
resultList.add(AppUsagePeriod.newBuilder()
.setStartTime(lastStartTime)
.setEndTime(inputPeriod.getEndTime())
.build());
}
}
return resultList;
}
@VisibleForTesting
static long getScreenOnTime(
final Map<Long, Map<String, List<AppUsagePeriod>>> appUsageMap,