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

Commit 21daba33 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "UsageStats: Fix time change handling"

parents 4dc0c15a 7cba1d46
Loading
Loading
Loading
Loading
+4 −46
Original line number Diff line number Diff line
@@ -15,40 +15,22 @@
 */
package com.android.server.usage;

import android.app.usage.UsageStatsManager;

/**
 * A handy calendar object that knows nothing of Locale's or TimeZones. This simplifies
 * interval book-keeping. It is *NOT* meant to be used as a user-facing calendar, as it has
 * no concept of Locale or TimeZone.
 */
public class UnixCalendar {
    private static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;
    private static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;
    private static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
    private static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;
    public static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;
    public static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;
    public static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
    public static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;
    private long mTime;

    public UnixCalendar(long time) {
        mTime = time;
    }

    public void truncateToDay() {
        mTime -= mTime % DAY_IN_MILLIS;
    }

    public void truncateToWeek() {
        mTime -= mTime % WEEK_IN_MILLIS;
    }

    public void truncateToMonth() {
        mTime -= mTime % MONTH_IN_MILLIS;
    }

    public void truncateToYear() {
        mTime -= mTime % YEAR_IN_MILLIS;
    }

    public void addDays(int val) {
        mTime += val * DAY_IN_MILLIS;
    }
@@ -72,28 +54,4 @@ public class UnixCalendar {
    public long getTimeInMillis() {
        return mTime;
    }

    public static void truncateTo(UnixCalendar calendar, int intervalType) {
        switch (intervalType) {
            case UsageStatsManager.INTERVAL_YEARLY:
                calendar.truncateToYear();
                break;

            case UsageStatsManager.INTERVAL_MONTHLY:
                calendar.truncateToMonth();
                break;

            case UsageStatsManager.INTERVAL_WEEKLY:
                calendar.truncateToWeek();
                break;

            case UsageStatsManager.INTERVAL_DAILY:
                calendar.truncateToDay();
                break;

            default:
                throw new UnsupportedOperationException("Can't truncate date to interval " +
                        intervalType);
        }
    }
}
+0 −17
Original line number Diff line number Diff line
@@ -349,23 +349,6 @@ class UsageStatsDatabase {
        return null;
    }

    /**
     * Get the time at which the latest stats begin for this interval type.
     */
    public long getLatestUsageStatsBeginTime(int intervalType) {
        synchronized (mLock) {
            if (intervalType < 0 || intervalType >= mIntervalDirs.length) {
                throw new IllegalArgumentException("Bad interval type " + intervalType);
            }

            final int statsFileCount = mSortedStatFiles[intervalType].size();
            if (statsFileCount > 0) {
                return mSortedStatFiles[intervalType].keyAt(statsFileCount - 1);
            }
            return -1;
        }
    }

    /**
     * Figures out what to extract from the given IntervalStats object.
     */
+30 −44
Original line number Diff line number Diff line
@@ -65,6 +65,11 @@ class UserUsageStatsService {
    private final String mLogPrefix;
    private final int mUserId;

    private static final long[] INTERVAL_LENGTH = new long[] {
            UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS,
            UnixCalendar.MONTH_IN_MILLIS, UnixCalendar.YEAR_IN_MILLIS
    };

    interface StatsUpdatedListener {
        void onStatsUpdated();
    }
@@ -104,18 +109,12 @@ class UserUsageStatsService {

            // By calling loadActiveStats, we will
            // generate new stats for each bucket.
            loadActiveStats(currentTimeMillis,/*force=*/ false, /*resetBeginIdleTime=*/ false);
            loadActiveStats(currentTimeMillis, /*resetBeginIdleTime=*/ false);
        } else {
            // Set up the expiry date to be one day from the latest daily stat.
            // This may actually be today and we will rollover on the first event
            // that is reported.
            mDailyExpiryDate.setTimeInMillis(
                    mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime);
            mDailyExpiryDate.addDays(1);
            mDailyExpiryDate.truncateToDay();
            Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
                    sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) +
                    "(" + mDailyExpiryDate.getTimeInMillis() + ")");
            updateRolloverDeadline();
        }

        // Now close off any events that were open at the time this was saved.
@@ -170,7 +169,7 @@ class UserUsageStatsService {
    void onTimeChanged(long oldTime, long newTime, boolean resetBeginIdleTime) {
        persistActiveStats();
        mDatabase.onTimeChanged(newTime - oldTime);
        loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime);
        loadActiveStats(newTime, resetBeginIdleTime);
    }

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

        persistActiveStats();
        mDatabase.prune(currentTimeMillis);
        loadActiveStats(currentTimeMillis, /*force=*/ false, /*resetBeginIdleTime=*/ false);
        loadActiveStats(currentTimeMillis, /*resetBeginIdleTime=*/ false);

        final int continueCount = continuePreviousDay.size();
        for (int i = 0; i < continueCount; i++) {
@@ -474,45 +473,28 @@ class UserUsageStatsService {
        }
    }

    /**
     * @param force To force all in-memory stats to be reloaded.
     */
    private void loadActiveStats(final long currentTimeMillis, boolean force,
            boolean resetBeginIdleTime) {
        final UnixCalendar tempCal = mDailyExpiryDate;
    private void loadActiveStats(final long currentTimeMillis, boolean resetBeginIdleTime) {
        for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
            tempCal.setTimeInMillis(currentTimeMillis);
            UnixCalendar.truncateTo(tempCal, intervalType);

            if (!force && mCurrentStats[intervalType] != null &&
                    mCurrentStats[intervalType].beginTime == tempCal.getTimeInMillis()) {
                // These are the same, no need to load them (in memory stats are always newer
                // than persisted stats).
                continue;
            }

            final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(intervalType);
            if (lastBeginTime >= tempCal.getTimeInMillis()) {
            final IntervalStats stats = mDatabase.getLatestUsageStats(intervalType);
            if (stats != null && currentTimeMillis - 500 >= stats.endTime &&
                    currentTimeMillis < stats.beginTime + INTERVAL_LENGTH[intervalType]) {
                if (DEBUG) {
                    Slog.d(TAG, mLogPrefix + "Loading existing stats @ " +
                            sDateFormat.format(lastBeginTime) + "(" + lastBeginTime +
                            sDateFormat.format(stats.beginTime) + "(" + stats.beginTime +
                            ") for interval " + intervalType);
                }
                mCurrentStats[intervalType] = mDatabase.getLatestUsageStats(intervalType);
                mCurrentStats[intervalType] = stats;
            } else {
                mCurrentStats[intervalType] = null;
            }

            if (mCurrentStats[intervalType] == null) {
                // No good fit remains.
                if (DEBUG) {
                    Slog.d(TAG, "Creating new stats @ " +
                            sDateFormat.format(tempCal.getTimeInMillis()) + "(" +
                            tempCal.getTimeInMillis() + ") for interval " + intervalType);

                            sDateFormat.format(currentTimeMillis) + "(" +
                            currentTimeMillis + ") for interval " + intervalType);
                }

                mCurrentStats[intervalType] = new IntervalStats();
                mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis();
                mCurrentStats[intervalType].endTime = currentTimeMillis;
                mCurrentStats[intervalType].beginTime = currentTimeMillis;
                mCurrentStats[intervalType].endTime = currentTimeMillis + 1;
            }

            if (resetBeginIdleTime) {
@@ -522,12 +504,16 @@ class UserUsageStatsService {
            }
        }
        mStatsChanged = false;
        mDailyExpiryDate.setTimeInMillis(currentTimeMillis);
        updateRolloverDeadline();
    }

    private void updateRolloverDeadline() {
        mDailyExpiryDate.setTimeInMillis(
                mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime);
        mDailyExpiryDate.addDays(1);
        mDailyExpiryDate.truncateToDay();
        Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
                sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" +
                tempCal.getTimeInMillis() + ")");
                mDailyExpiryDate.getTimeInMillis() + ")");
    }

    //