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:
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user