Merge "UsageStatsService: Fix app idle issue at rollover time" into mnc-dr1.5-dev am: 15df80f069

am: 1f1cbc01c1

* commit '1f1cbc01c1c137892da86b969dd54d7bc0809280':
  UsageStatsService: Fix app idle issue at rollover time
This commit is contained in:
Adam Lesinski
2016-01-12 00:56:22 +00:00
committed by android-build-merger

View File

@@ -59,6 +59,7 @@ class UserUsageStatsService {
private final Context mContext; private final Context mContext;
private final UsageStatsDatabase mDatabase; private final UsageStatsDatabase mDatabase;
private final IntervalStats[] mCurrentStats; private final IntervalStats[] mCurrentStats;
private IntervalStats mAppIdleRollingWindow;
private boolean mStatsChanged = false; private boolean mStatsChanged = false;
private final UnixCalendar mDailyExpiryDate; private final UnixCalendar mDailyExpiryDate;
private final StatsUpdatedListener mListener; private final StatsUpdatedListener mListener;
@@ -138,6 +139,8 @@ class UserUsageStatsService {
initializeDefaultsForApps(currentTimeMillis, deviceUsageTime, initializeDefaultsForApps(currentTimeMillis, deviceUsageTime,
mDatabase.isFirstUpdate()); mDatabase.isFirstUpdate());
} }
refreshAppIdleRollingWindow(currentTimeMillis);
} }
/** /**
@@ -171,6 +174,7 @@ class UserUsageStatsService {
persistActiveStats(); persistActiveStats();
mDatabase.onTimeChanged(newTime - oldTime); mDatabase.onTimeChanged(newTime - oldTime);
loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime);
refreshAppIdleRollingWindow(newTime);
} }
void reportEvent(UsageEvents.Event event, long deviceUsageTime) { void reportEvent(UsageEvents.Event event, long deviceUsageTime) {
@@ -212,6 +216,11 @@ class UserUsageStatsService {
} }
} }
if (event.mEventType != Event.CONFIGURATION_CHANGE) {
mAppIdleRollingWindow.update(event.mPackage, event.mTimeStamp, event.mEventType);
mAppIdleRollingWindow.updateBeginIdleTime(event.mPackage, deviceUsageTime);
}
notifyStatsChanged(); notifyStatsChanged();
} }
@@ -223,6 +232,7 @@ class UserUsageStatsService {
for (IntervalStats stats : mCurrentStats) { for (IntervalStats stats : mCurrentStats) {
stats.updateBeginIdleTime(packageName, beginIdleTime); stats.updateBeginIdleTime(packageName, beginIdleTime);
} }
mAppIdleRollingWindow.updateBeginIdleTime(packageName, beginIdleTime);
notifyStatsChanged(); notifyStatsChanged();
} }
@@ -230,6 +240,7 @@ class UserUsageStatsService {
for (IntervalStats stats : mCurrentStats) { for (IntervalStats stats : mCurrentStats) {
stats.updateSystemLastUsedTime(packageName, lastUsedTime); stats.updateSystemLastUsedTime(packageName, lastUsedTime);
} }
mAppIdleRollingWindow.updateSystemLastUsedTime(packageName, lastUsedTime);
notifyStatsChanged(); notifyStatsChanged();
} }
@@ -388,9 +399,8 @@ class UserUsageStatsService {
} }
long getBeginIdleTime(String packageName) { long getBeginIdleTime(String packageName) {
final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
UsageStats packageUsage; UsageStats packageUsage;
if ((packageUsage = yearly.packageStats.get(packageName)) == null) { if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) {
return -1; return -1;
} else { } else {
return packageUsage.getBeginIdleTime(); return packageUsage.getBeginIdleTime();
@@ -398,9 +408,8 @@ class UserUsageStatsService {
} }
long getSystemLastUsedTime(String packageName) { long getSystemLastUsedTime(String packageName) {
final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
UsageStats packageUsage; UsageStats packageUsage;
if ((packageUsage = yearly.packageStats.get(packageName)) == null) { if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) {
return -1; return -1;
} else { } else {
return packageUsage.getLastTimeSystemUsed(); return packageUsage.getLastTimeSystemUsed();
@@ -462,6 +471,8 @@ class UserUsageStatsService {
} }
persistActiveStats(); persistActiveStats();
refreshAppIdleRollingWindow(currentTimeMillis);
final long totalTime = SystemClock.elapsedRealtime() - startTime; final long totalTime = SystemClock.elapsedRealtime() - startTime;
Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime
+ " milliseconds"); + " milliseconds");
@@ -521,6 +532,7 @@ class UserUsageStatsService {
} }
} }
} }
mStatsChanged = false; mStatsChanged = false;
mDailyExpiryDate.setTimeInMillis(currentTimeMillis); mDailyExpiryDate.setTimeInMillis(currentTimeMillis);
mDailyExpiryDate.addDays(1); mDailyExpiryDate.addDays(1);
@@ -530,6 +542,68 @@ class UserUsageStatsService {
tempCal.getTimeInMillis() + ")"); tempCal.getTimeInMillis() + ")");
} }
private static void mergePackageStats(IntervalStats dst, IntervalStats src) {
dst.endTime = Math.max(dst.endTime, src.endTime);
final int srcPackageCount = src.packageStats.size();
for (int i = 0; i < srcPackageCount; i++) {
final String packageName = src.packageStats.keyAt(i);
final UsageStats srcStats = src.packageStats.valueAt(i);
final UsageStats dstStats = dst.packageStats.get(packageName);
if (dstStats == null) {
dst.packageStats.put(packageName, new UsageStats(srcStats));
} else {
dstStats.add(src.packageStats.valueAt(i));
}
}
}
/**
* Merges all the stats into the first element of the resulting list.
*/
private static final StatCombiner<IntervalStats> sPackageStatsMerger =
new StatCombiner<IntervalStats>() {
@Override
public void combine(IntervalStats stats, boolean mutable,
List<IntervalStats> accumulatedResult) {
IntervalStats accum;
if (accumulatedResult.isEmpty()) {
accum = new IntervalStats();
accum.beginTime = stats.beginTime;
accumulatedResult.add(accum);
} else {
accum = accumulatedResult.get(0);
}
mergePackageStats(accum, stats);
}
};
/**
* App idle operates on a rolling window of time. When we roll over time, we end up with a
* period of time where in-memory stats are empty and we don't hit the disk for older stats
* for performance reasons. Suddenly all apps will become idle.
*
* Instead, at times we do a deep query to find all the apps that have run in the past few
* days and keep the cached data up to date.
*
* @param currentTimeMillis
*/
void refreshAppIdleRollingWindow(long currentTimeMillis) {
// Start the rolling window for AppIdle requests.
List<IntervalStats> stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
currentTimeMillis - (1000 * 60 * 60 * 24 * 2), currentTimeMillis,
sPackageStatsMerger);
if (stats == null || stats.isEmpty()) {
mAppIdleRollingWindow = new IntervalStats();
mergePackageStats(mAppIdleRollingWindow,
mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]);
} else {
mAppIdleRollingWindow = stats.get(0);
}
}
// //
// -- DUMP related methods -- // -- DUMP related methods --
// //
@@ -552,6 +626,9 @@ class UserUsageStatsService {
pw.println(" stats"); pw.println(" stats");
printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true); printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true);
} }
pw.println("AppIdleRollingWindow cache");
printIntervalStats(pw, mAppIdleRollingWindow, screenOnTime, true);
} }
private String formatDateTime(long dateTime, boolean pretty) { private String formatDateTime(long dateTime, boolean pretty) {