Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 112e2664 authored by Adam Lesinski's avatar Adam Lesinski Committed by android-build-merger
Browse files

Merge "UsageStats: Fix issue where initializing data for first time would...

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

* commit 'f2cc98bc':
  UsageStats: Fix issue where initializing data for first time would cause crash
parents 6222bb0f f2cc98bc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -547,7 +547,8 @@ public class UsageStatsService extends SystemService implements
            final int userCount = mUserState.size();
            for (int i = 0; i < userCount; i++) {
                final UserUsageStatsService service = mUserState.valueAt(i);
                service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime);
                service.onTimeChanged(expectedSystemTime, actualSystemTime, mScreenOnTime,
                        resetBeginIdleTime);
            }
            mRealTimeSnapshot = actualRealtime;
            mSystemTimeSnapshot = actualSystemTime;
+39 −34
Original line number Diff line number Diff line
@@ -135,12 +135,12 @@ class UserUsageStatsService {
            stat.updateConfigurationStats(null, stat.lastTimeSaved);
        }

        refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime);

        if (mDatabase.isNewUpdate()) {
            initializeDefaultsForApps(currentTimeMillis, deviceUsageTime,
                    mDatabase.isFirstUpdate());
        }

        refreshAppIdleRollingWindow(currentTimeMillis);
    }

    /**
@@ -162,19 +162,23 @@ class UserUsageStatsService {
                for (IntervalStats stats : mCurrentStats) {
                    stats.update(packageName, currentTimeMillis, Event.SYSTEM_INTERACTION);
                    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.
        persistActiveStats();
    }

    void onTimeChanged(long oldTime, long newTime, boolean resetBeginIdleTime) {
    void onTimeChanged(long oldTime, long newTime, long deviceUsageTime,
                       boolean resetBeginIdleTime) {
        persistActiveStats();
        mDatabase.onTimeChanged(newTime - oldTime);
        loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime);
        refreshAppIdleRollingWindow(newTime);
        refreshAppIdleRollingWindow(newTime, deviceUsageTime);
    }

    void reportEvent(UsageEvents.Event event, long deviceUsageTime) {
@@ -186,7 +190,7 @@ class UserUsageStatsService {

        if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
            // Need to rollover
            rolloverStats(event.mTimeStamp);
            rolloverStats(event.mTimeStamp, deviceUsageTime);
        }

        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();
        Slog.i(TAG, mLogPrefix + "Rolling over usage stats");

@@ -471,7 +475,7 @@ class UserUsageStatsService {
        }
        persistActiveStats();

        refreshAppIdleRollingWindow(currentTimeMillis);
        refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime);

        final long totalTime = SystemClock.elapsedRealtime() - startTime;
        Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime
@@ -542,26 +546,43 @@ class UserUsageStatsService {
                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);

        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);
            UsageStats dstStats = dst.packageStats.get(packageName);
            if (dstStats == null) {
                dst.packageStats.put(packageName, new UsageStats(srcStats));
                dstStats = new UsageStats(srcStats);
                dst.packageStats.put(packageName, dstStats);
            } else {
                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.
     * 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
     */
    private static final StatCombiner<IntervalStats> sPackageStatsMerger =
    void refreshAppIdleRollingWindow(final long currentTimeMillis, final long deviceUsageTime) {
        // Start the rolling window for AppIdle requests.
        List<IntervalStats> stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
                currentTimeMillis - (1000 * 60 * 60 * 24 * 2), currentTimeMillis,
                new StatCombiner<IntervalStats>() {
                    @Override
                    public void combine(IntervalStats stats, boolean mutable,
@@ -575,30 +596,14 @@ class UserUsageStatsService {
                            accum = accumulatedResult.get(0);
                        }

            mergePackageStats(accum, stats);
                        mergePackageStats(accum, stats, deviceUsageTime);
                    }
    };

    /**
     * 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]);
                    mCurrentStats[UsageStatsManager.INTERVAL_YEARLY], deviceUsageTime);
        } else {
            mAppIdleRollingWindow = stats.get(0);
        }