Loading services/usage/java/com/android/server/usage/UserUsageStatsService.java +81 −4 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ class UserUsageStatsService { private final Context mContext; private final UsageStatsDatabase mDatabase; private final IntervalStats[] mCurrentStats; private IntervalStats mAppIdleRollingWindow; private boolean mStatsChanged = false; private final UnixCalendar mDailyExpiryDate; private final StatsUpdatedListener mListener; Loading Loading @@ -138,6 +139,8 @@ class UserUsageStatsService { initializeDefaultsForApps(currentTimeMillis, deviceUsageTime, mDatabase.isFirstUpdate()); } refreshAppIdleRollingWindow(currentTimeMillis); } /** Loading Loading @@ -171,6 +174,7 @@ class UserUsageStatsService { persistActiveStats(); mDatabase.onTimeChanged(newTime - oldTime); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); refreshAppIdleRollingWindow(newTime); } void reportEvent(UsageEvents.Event event, long deviceUsageTime) { Loading Loading @@ -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(); } Loading @@ -223,6 +232,7 @@ class UserUsageStatsService { for (IntervalStats stats : mCurrentStats) { stats.updateBeginIdleTime(packageName, beginIdleTime); } mAppIdleRollingWindow.updateBeginIdleTime(packageName, beginIdleTime); notifyStatsChanged(); } Loading @@ -230,6 +240,7 @@ class UserUsageStatsService { for (IntervalStats stats : mCurrentStats) { stats.updateSystemLastUsedTime(packageName, lastUsedTime); } mAppIdleRollingWindow.updateSystemLastUsedTime(packageName, lastUsedTime); notifyStatsChanged(); } Loading Loading @@ -388,9 +399,8 @@ class UserUsageStatsService { } long getBeginIdleTime(String packageName) { final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]; UsageStats packageUsage; if ((packageUsage = yearly.packageStats.get(packageName)) == null) { if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) { return -1; } else { return packageUsage.getBeginIdleTime(); Loading @@ -398,9 +408,8 @@ class UserUsageStatsService { } long getSystemLastUsedTime(String packageName) { final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]; UsageStats packageUsage; if ((packageUsage = yearly.packageStats.get(packageName)) == null) { if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) { return -1; } else { return packageUsage.getLastTimeSystemUsed(); Loading Loading @@ -462,6 +471,8 @@ class UserUsageStatsService { } persistActiveStats(); refreshAppIdleRollingWindow(currentTimeMillis); final long totalTime = SystemClock.elapsedRealtime() - startTime; Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime + " milliseconds"); Loading Loading @@ -521,6 +532,7 @@ class UserUsageStatsService { } } } mStatsChanged = false; mDailyExpiryDate.setTimeInMillis(currentTimeMillis); mDailyExpiryDate.addDays(1); Loading @@ -530,6 +542,68 @@ class UserUsageStatsService { 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 -- // Loading @@ -552,6 +626,9 @@ class UserUsageStatsService { pw.println(" stats"); printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true); } pw.println("AppIdleRollingWindow cache"); printIntervalStats(pw, mAppIdleRollingWindow, screenOnTime, true); } private String formatDateTime(long dateTime, boolean pretty) { Loading Loading
services/usage/java/com/android/server/usage/UserUsageStatsService.java +81 −4 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ class UserUsageStatsService { private final Context mContext; private final UsageStatsDatabase mDatabase; private final IntervalStats[] mCurrentStats; private IntervalStats mAppIdleRollingWindow; private boolean mStatsChanged = false; private final UnixCalendar mDailyExpiryDate; private final StatsUpdatedListener mListener; Loading Loading @@ -138,6 +139,8 @@ class UserUsageStatsService { initializeDefaultsForApps(currentTimeMillis, deviceUsageTime, mDatabase.isFirstUpdate()); } refreshAppIdleRollingWindow(currentTimeMillis); } /** Loading Loading @@ -171,6 +174,7 @@ class UserUsageStatsService { persistActiveStats(); mDatabase.onTimeChanged(newTime - oldTime); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); refreshAppIdleRollingWindow(newTime); } void reportEvent(UsageEvents.Event event, long deviceUsageTime) { Loading Loading @@ -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(); } Loading @@ -223,6 +232,7 @@ class UserUsageStatsService { for (IntervalStats stats : mCurrentStats) { stats.updateBeginIdleTime(packageName, beginIdleTime); } mAppIdleRollingWindow.updateBeginIdleTime(packageName, beginIdleTime); notifyStatsChanged(); } Loading @@ -230,6 +240,7 @@ class UserUsageStatsService { for (IntervalStats stats : mCurrentStats) { stats.updateSystemLastUsedTime(packageName, lastUsedTime); } mAppIdleRollingWindow.updateSystemLastUsedTime(packageName, lastUsedTime); notifyStatsChanged(); } Loading Loading @@ -388,9 +399,8 @@ class UserUsageStatsService { } long getBeginIdleTime(String packageName) { final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]; UsageStats packageUsage; if ((packageUsage = yearly.packageStats.get(packageName)) == null) { if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) { return -1; } else { return packageUsage.getBeginIdleTime(); Loading @@ -398,9 +408,8 @@ class UserUsageStatsService { } long getSystemLastUsedTime(String packageName) { final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]; UsageStats packageUsage; if ((packageUsage = yearly.packageStats.get(packageName)) == null) { if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) { return -1; } else { return packageUsage.getLastTimeSystemUsed(); Loading Loading @@ -462,6 +471,8 @@ class UserUsageStatsService { } persistActiveStats(); refreshAppIdleRollingWindow(currentTimeMillis); final long totalTime = SystemClock.elapsedRealtime() - startTime; Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime + " milliseconds"); Loading Loading @@ -521,6 +532,7 @@ class UserUsageStatsService { } } } mStatsChanged = false; mDailyExpiryDate.setTimeInMillis(currentTimeMillis); mDailyExpiryDate.addDays(1); Loading @@ -530,6 +542,68 @@ class UserUsageStatsService { 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 -- // Loading @@ -552,6 +626,9 @@ class UserUsageStatsService { pw.println(" stats"); printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true); } pw.println("AppIdleRollingWindow cache"); printIntervalStats(pw, mAppIdleRollingWindow, screenOnTime, true); } private String formatDateTime(long dateTime, boolean pretty) { Loading