Skip to content

Commit

Permalink
[Usage] Fix detecting device shutdowns
Browse files Browse the repository at this point in the history
DEVICE_SHUTDOWN events set android as the default package which caused the
Android System package to be displayed in the App Usage page with unusual screen
time.

Signed-off-by: Muntashir Al-Islam <[email protected]>
  • Loading branch information
MuntashirAkon committed Dec 23, 2024
1 parent 7732d57 commit a39c3cf
Showing 1 changed file with 21 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class AppUsageStatsManager {
public static final class DataUsage extends Pair<Long, Long> implements Parcelable, Comparable<DataUsage> {
public static final DataUsage EMPTY = new DataUsage(0, 0);

public static DataUsage fromDataUsage(DataUsage ...dataUsages) {
public static DataUsage fromDataUsage(DataUsage... dataUsages) {
if (dataUsages == null) {
return EMPTY;
}
Expand Down Expand Up @@ -211,14 +211,22 @@ public PackageUsageInfo getUsageStatsForPackage(@NonNull String packageName,
PackageUsageInfo packageUsageInfo = new PackageUsageInfo(mContext, packageName, userId, applicationInfo);
PerPackageUsageInternal usage = new PerPackageUsageInternal(packageName);
List<UsageEvents.Event> events = UsageStatsManagerCompat.queryEventsSorted(range.getStartTime(), range.getEndTime(), userId, USUAL_ACTIVITY_EVENTS);
long lastShutdownTime = 0L;
for (UsageEvents.Event event : events) {
if (Objects.equals(packageName, event.getPackageName())) {
int eventType = event.getEventType();
int eventType = event.getEventType();
if (eventType == UsageEvents.Event.DEVICE_SHUTDOWN) {
lastShutdownTime = event.getTimeStamp();
} else if (Objects.equals(packageName, event.getPackageName())) {
// Queries are sorted in descending order, so a not-running activity should be paused
// or stopped first and then resumed (i.e., reversed logic)
if (isActivityClosed(eventType)) {
usage.setLastEndTime(event.getTimeStamp());
} else if (isActivityOpened(eventType)) {
if (lastShutdownTime != 0L) {
// The device was shutdown. Adding the shutdown time here as no impact if
// the event already has an end time.
usage.setLastEndTime(lastShutdownTime);
}
usage.setLastStartTime(event.getTimeStamp());
}
}
Expand Down Expand Up @@ -307,12 +315,15 @@ private List<PackageUsageInfo> getUsageStatsInternal(@UsageUtils.IntervalType in
// Get events
UsageUtils.TimeInterval interval = UsageUtils.getTimeInterval(usageInterval);
List<UsageEvents.Event> events = UsageStatsManagerCompat.queryEventsSorted(interval.getStartTime(), interval.getEndTime(), userId, USUAL_ACTIVITY_EVENTS);
long lastShutdownTime = 0L;
for (UsageEvents.Event event : events) {
int eventType = event.getEventType();
String packageName = event.getPackageName();
// Queries are sorted in descending order, so a not-running activity should be paused or
// stopped first and then resumed (i.e., reversed logic).
if (isActivityClosed(eventType)) {
if (eventType == UsageEvents.Event.DEVICE_SHUTDOWN) {
lastShutdownTime = event.getTimeStamp();
} else if (isActivityClosed(eventType)) {
PerPackageUsageInternal usage = perPackageUsageMap.get(packageName);
if (usage == null) {
usage = new PerPackageUsageInternal(packageName);
Expand All @@ -325,6 +336,11 @@ private List<PackageUsageInfo> getUsageStatsInternal(@UsageUtils.IntervalType in
usage = new PerPackageUsageInternal(packageName);
perPackageUsageMap.put(packageName, usage);
}
if (lastShutdownTime != 0L) {
// The device was shutdown. Adding the shutdown time here as no impact if the
// event already has an end time.
usage.setLastEndTime(lastShutdownTime);
}
usage.setLastStartTime(event.getTimeStamp());
}
}
Expand Down Expand Up @@ -354,8 +370,7 @@ private List<PackageUsageInfo> getUsageStatsInternal(@UsageUtils.IntervalType in
@SuppressLint("InlinedApi") // These are constant values, API compatibility does not apply
private static boolean isActivityClosed(int eventType) {
return eventType == UsageEvents.Event.ACTIVITY_STOPPED
|| eventType == UsageEvents.Event.ACTIVITY_PAUSED
|| eventType == UsageEvents.Event.DEVICE_SHUTDOWN;
|| eventType == UsageEvents.Event.ACTIVITY_PAUSED;
}

@SuppressLint("InlinedApi") // These are constant values, API compatibility does not apply
Expand Down

0 comments on commit a39c3cf

Please sign in to comment.