Merge "UsageStats: Fix issue where initializing data for first time would cause crash" into mnc-dr1.5-dev

This commit is contained in:
Adam Lesinski
2016-01-13 01:48:45 +00:00
committed by Android (Google) Code Review
2 changed files with 42 additions and 36 deletions

View File

@@ -547,7 +547,8 @@ public class UsageStatsService extends SystemService implements
final int userCount = mUserState.size(); final int userCount = mUserState.size();
for (int i = 0; i < userCount; i++) { for (int i = 0; i < userCount; i++) {
final UserUsageStatsService service = mUserState.valueAt(i); final UserUsageStatsService service = mUserState.valueAt(i);
service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime); service.onTimeChanged(expectedSystemTime, actualSystemTime, mScreenOnTime,
resetBeginIdleTime);
} }
mRealTimeSnapshot = actualRealtime; mRealTimeSnapshot = actualRealtime;
mSystemTimeSnapshot = actualSystemTime; mSystemTimeSnapshot = actualSystemTime;

View File

@@ -135,12 +135,12 @@ class UserUsageStatsService {
stat.updateConfigurationStats(null, stat.lastTimeSaved); stat.updateConfigurationStats(null, stat.lastTimeSaved);
} }
refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime);
if (mDatabase.isNewUpdate()) { if (mDatabase.isNewUpdate()) {
initializeDefaultsForApps(currentTimeMillis, deviceUsageTime, initializeDefaultsForApps(currentTimeMillis, deviceUsageTime,
mDatabase.isFirstUpdate()); mDatabase.isFirstUpdate());
} }
refreshAppIdleRollingWindow(currentTimeMillis);
} }
/** /**
@@ -162,19 +162,23 @@ class UserUsageStatsService {
for (IntervalStats stats : mCurrentStats) { for (IntervalStats stats : mCurrentStats) {
stats.update(packageName, currentTimeMillis, Event.SYSTEM_INTERACTION); stats.update(packageName, currentTimeMillis, Event.SYSTEM_INTERACTION);
stats.updateBeginIdleTime(packageName, deviceUsageTime); stats.updateBeginIdleTime(packageName, deviceUsageTime);
mStatsChanged = true;
} }
mAppIdleRollingWindow.update(packageName, currentTimeMillis,
Event.SYSTEM_INTERACTION);
mAppIdleRollingWindow.updateBeginIdleTime(packageName, deviceUsageTime);
mStatsChanged = true;
} }
} }
// Persist the new OTA-related access stats. // Persist the new OTA-related access stats.
persistActiveStats(); persistActiveStats();
} }
void onTimeChanged(long oldTime, long newTime, boolean resetBeginIdleTime) { void onTimeChanged(long oldTime, long newTime, long deviceUsageTime,
boolean resetBeginIdleTime) {
persistActiveStats(); persistActiveStats();
mDatabase.onTimeChanged(newTime - oldTime); mDatabase.onTimeChanged(newTime - oldTime);
loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime);
refreshAppIdleRollingWindow(newTime); refreshAppIdleRollingWindow(newTime, deviceUsageTime);
} }
void reportEvent(UsageEvents.Event event, long deviceUsageTime) { void reportEvent(UsageEvents.Event event, long deviceUsageTime) {
@@ -186,7 +190,7 @@ class UserUsageStatsService {
if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) { if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
// Need to rollover // Need to rollover
rolloverStats(event.mTimeStamp); rolloverStats(event.mTimeStamp, deviceUsageTime);
} }
final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY]; final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY];
@@ -430,7 +434,7 @@ class UserUsageStatsService {
} }
} }
private void rolloverStats(final long currentTimeMillis) { private void rolloverStats(final long currentTimeMillis, final long deviceUsageTime) {
final long startTime = SystemClock.elapsedRealtime(); final long startTime = SystemClock.elapsedRealtime();
Slog.i(TAG, mLogPrefix + "Rolling over usage stats"); Slog.i(TAG, mLogPrefix + "Rolling over usage stats");
@@ -471,7 +475,7 @@ class UserUsageStatsService {
} }
persistActiveStats(); persistActiveStats();
refreshAppIdleRollingWindow(currentTimeMillis); refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime);
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
@@ -542,43 +546,29 @@ class UserUsageStatsService {
tempCal.getTimeInMillis() + ")"); tempCal.getTimeInMillis() + ")");
} }
private static void mergePackageStats(IntervalStats dst, IntervalStats src) { private static void mergePackageStats(IntervalStats dst, IntervalStats src,
final long deviceUsageTime) {
dst.endTime = Math.max(dst.endTime, src.endTime); dst.endTime = Math.max(dst.endTime, src.endTime);
final int srcPackageCount = src.packageStats.size(); final int srcPackageCount = src.packageStats.size();
for (int i = 0; i < srcPackageCount; i++) { for (int i = 0; i < srcPackageCount; i++) {
final String packageName = src.packageStats.keyAt(i); final String packageName = src.packageStats.keyAt(i);
final UsageStats srcStats = src.packageStats.valueAt(i); final UsageStats srcStats = src.packageStats.valueAt(i);
final UsageStats dstStats = dst.packageStats.get(packageName); UsageStats dstStats = dst.packageStats.get(packageName);
if (dstStats == null) { if (dstStats == null) {
dst.packageStats.put(packageName, new UsageStats(srcStats)); dstStats = new UsageStats(srcStats);
dst.packageStats.put(packageName, dstStats);
} else { } else {
dstStats.add(src.packageStats.valueAt(i)); dstStats.add(src.packageStats.valueAt(i));
} }
// App idle times can not begin in the future. This happens if we had a time change.
if (dstStats.mBeginIdleTime > deviceUsageTime) {
dstStats.mBeginIdleTime = deviceUsageTime;
}
} }
} }
/**
* 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 * 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 * period of time where in-memory stats are empty and we don't hit the disk for older stats
@@ -589,16 +579,31 @@ class UserUsageStatsService {
* *
* @param currentTimeMillis * @param currentTimeMillis
*/ */
void refreshAppIdleRollingWindow(long currentTimeMillis) { void refreshAppIdleRollingWindow(final long currentTimeMillis, final long deviceUsageTime) {
// Start the rolling window for AppIdle requests. // Start the rolling window for AppIdle requests.
List<IntervalStats> stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, List<IntervalStats> stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
currentTimeMillis - (1000 * 60 * 60 * 24 * 2), currentTimeMillis, currentTimeMillis - (1000 * 60 * 60 * 24 * 2), currentTimeMillis,
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, deviceUsageTime);
}
});
if (stats == null || stats.isEmpty()) { if (stats == null || stats.isEmpty()) {
mAppIdleRollingWindow = new IntervalStats(); mAppIdleRollingWindow = new IntervalStats();
mergePackageStats(mAppIdleRollingWindow, mergePackageStats(mAppIdleRollingWindow,
mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]); mCurrentStats[UsageStatsManager.INTERVAL_YEARLY], deviceUsageTime);
} else { } else {
mAppIdleRollingWindow = stats.get(0); mAppIdleRollingWindow = stats.get(0);
} }