diff options
author | Adam Lesinski <adamlesinski@google.com> | 2014-09-03 16:49:59 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2014-09-05 23:09:27 +0000 |
commit | d26bea3a1498d1b327ae37cc796fb8cd67e9c977 (patch) | |
tree | 2de9bcb88f6f4bea0153bceaf9a86c838dd91991 /services | |
parent | 7f61e96db7c90c1f4418359672aa4656aebee500 (diff) | |
download | frameworks_base-d26bea3a1498d1b327ae37cc796fb8cd67e9c977.zip frameworks_base-d26bea3a1498d1b327ae37cc796fb8cd67e9c977.tar.gz frameworks_base-d26bea3a1498d1b327ae37cc796fb8cd67e9c977.tar.bz2 |
Returns UsageEvents from previous days
- Avoid writing to disk when querying UsageStats.
- Use new UnixCalendar to avoid issues with Locale and TimeZone.
Bug: 16951313
Change-Id: I2473b8ef8dc1e2f6be22d4c689b96e346bdcafd5
Diffstat (limited to 'services')
5 files changed, 301 insertions, 173 deletions
diff --git a/services/usage/java/com/android/server/usage/UnixCalendar.java b/services/usage/java/com/android/server/usage/UnixCalendar.java new file mode 100644 index 0000000..ce06a91 --- /dev/null +++ b/services/usage/java/com/android/server/usage/UnixCalendar.java @@ -0,0 +1,99 @@ +/** + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +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; + 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; + } + + public void addWeeks(int val) { + mTime += val * WEEK_IN_MILLIS; + } + + public void addMonths(int val) { + mTime += val * MONTH_IN_MILLIS; + } + + public void addYears(int val) { + mTime += val * YEAR_IN_MILLIS; + } + + public void setTimeInMillis(long time) { + mTime = time; + } + + 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); + } + } +} diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java index 37340a4..6c5fa78 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java +++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java @@ -21,24 +21,30 @@ import android.app.usage.UsageStatsManager; import android.util.AtomicFile; import android.util.Slog; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; /** * Provides an interface to query for UsageStat data from an XML database. */ class UsageStatsDatabase { + private static final int CURRENT_VERSION = 1; + private static final String TAG = "UsageStatsDatabase"; private static final boolean DEBUG = UsageStatsService.DEBUG; private final Object mLock = new Object(); private final File[] mIntervalDirs; private final TimeSparseArray<AtomicFile>[] mSortedStatFiles; - private final Calendar mCal; + private final UnixCalendar mCal; + private final File mVersionFile; public UsageStatsDatabase(File dir) { mIntervalDirs = new File[] { @@ -47,8 +53,9 @@ class UsageStatsDatabase { new File(dir, "monthly"), new File(dir, "yearly"), }; + mVersionFile = new File(dir, "version"); mSortedStatFiles = new TimeSparseArray[mIntervalDirs.length]; - mCal = Calendar.getInstance(); + mCal = new UnixCalendar(0); } /** @@ -64,6 +71,8 @@ class UsageStatsDatabase { } } + checkVersionLocked(); + final FilenameFilter backupFileFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { @@ -88,6 +97,43 @@ class UsageStatsDatabase { } } + private void checkVersionLocked() { + int version; + try (BufferedReader reader = new BufferedReader(new FileReader(mVersionFile))) { + version = Integer.parseInt(reader.readLine()); + } catch (NumberFormatException | IOException e) { + version = 0; + } + + if (version != CURRENT_VERSION) { + Slog.i(TAG, "Upgrading from version " + version + " to " + CURRENT_VERSION); + doUpgradeLocked(version, CURRENT_VERSION); + + try (BufferedWriter writer = new BufferedWriter(new FileWriter(mVersionFile))) { + writer.write(Integer.toString(CURRENT_VERSION)); + } catch (IOException e) { + Slog.e(TAG, "Failed to write new version"); + throw new RuntimeException(e); + } + } + } + + private void doUpgradeLocked(int thisVersion, int nextVersion) { + if (thisVersion == 0) { + // Delete all files if we are version 0. This is a pre-release version, + // so this is fine. + Slog.i(TAG, "Deleting all usage stats files"); + for (int i = 0; i < mIntervalDirs.length; i++) { + File[] files = mIntervalDirs[i].listFiles(); + if (files != null) { + for (File f : files) { + f.delete(); + } + } + } + } + } + /** * Get the latest stats that exist for this interval type. */ @@ -161,25 +207,48 @@ class UsageStatsDatabase { throw new IllegalArgumentException("Bad interval type " + intervalType); } - if (endTime < beginTime) { + final TimeSparseArray<AtomicFile> intervalStats = mSortedStatFiles[intervalType]; + + if (endTime <= beginTime) { + if (DEBUG) { + Slog.d(TAG, "endTime(" + endTime + ") <= beginTime(" + beginTime + ")"); + } return null; } - final int startIndex = mSortedStatFiles[intervalType].closestIndexOnOrBefore(beginTime); + int startIndex = intervalStats.closestIndexOnOrBefore(beginTime); if (startIndex < 0) { - return null; + // All the stats available have timestamps after beginTime, which means they all + // match. + startIndex = 0; } - int endIndex = mSortedStatFiles[intervalType].closestIndexOnOrAfter(endTime); + int endIndex = intervalStats.closestIndexOnOrBefore(endTime); if (endIndex < 0) { - endIndex = mSortedStatFiles[intervalType].size() - 1; + // All the stats start after this range ends, so nothing matches. + if (DEBUG) { + Slog.d(TAG, "No results for this range. All stats start after."); + } + return null; + } + + if (intervalStats.keyAt(endIndex) == endTime) { + // The endTime is exclusive, so if we matched exactly take the one before. + endIndex--; + if (endIndex < 0) { + // All the stats start after this range ends, so nothing matches. + if (DEBUG) { + Slog.d(TAG, "No results for this range. All stats start after."); + } + return null; + } } try { IntervalStats stats = new IntervalStats(); ArrayList<T> results = new ArrayList<>(); for (int i = startIndex; i <= endIndex; i++) { - final AtomicFile f = mSortedStatFiles[intervalType].valueAt(i); + final AtomicFile f = intervalStats.valueAt(i); if (DEBUG) { Slog.d(TAG, "Reading stat file " + f.getBaseFile().getAbsolutePath()); @@ -230,22 +299,22 @@ class UsageStatsDatabase { synchronized (mLock) { long timeNow = System.currentTimeMillis(); mCal.setTimeInMillis(timeNow); - mCal.add(Calendar.YEAR, -3); + mCal.addYears(-3); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_YEARLY], mCal.getTimeInMillis()); mCal.setTimeInMillis(timeNow); - mCal.add(Calendar.MONTH, -6); + mCal.addMonths(-6); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_MONTHLY], mCal.getTimeInMillis()); mCal.setTimeInMillis(timeNow); - mCal.add(Calendar.WEEK_OF_YEAR, -4); + mCal.addWeeks(-4); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_WEEKLY], mCal.getTimeInMillis()); mCal.setTimeInMillis(timeNow); - mCal.add(Calendar.DAY_OF_YEAR, -7); + mCal.addDays(-7); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_DAILY], mCal.getTimeInMillis()); } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index e77bf86..8aa3d66 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -62,9 +62,7 @@ public class UsageStatsService extends SystemService implements static final boolean DEBUG = false; private static final long TEN_SECONDS = 10 * 1000; private static final long TWENTY_MINUTES = 20 * 60 * 1000; - private static final long TWO_MINUTES = 2 * 60 * 1000; private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; - private static final long END_TIME_DELAY = DEBUG ? 0 : TWO_MINUTES; // Handler message types. static final int MSG_REPORT_EVENT = 0; @@ -178,7 +176,7 @@ public class UsageStatsService extends SystemService implements } /** - * Called by the Bunder stub + * Called by the Binder stub */ void shutdown() { synchronized (mLock) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsUtils.java b/services/usage/java/com/android/server/usage/UsageStatsUtils.java deleted file mode 100644 index dd5f3b9..0000000 --- a/services/usage/java/com/android/server/usage/UsageStatsUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.android.server.usage; - -import android.app.usage.UsageStatsManager; - -import java.util.Calendar; - -/** - * A collection of utility methods used by the UsageStatsService and accompanying classes. - */ -final class UsageStatsUtils { - private UsageStatsUtils() {} - - /** - * Truncates the date to the given UsageStats bucket. For example, if the bucket is - * {@link UsageStatsManager#INTERVAL_YEARLY}, the date is truncated to the 1st day of the year, - * with the time set to 00:00:00. - * - * @param bucket The UsageStats bucket to truncate to. - * @param cal The date to truncate. - */ - public static void truncateDateTo(int bucket, Calendar cal) { - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - - switch (bucket) { - case UsageStatsManager.INTERVAL_YEARLY: - cal.set(Calendar.DAY_OF_YEAR, 0); - break; - - case UsageStatsManager.INTERVAL_MONTHLY: - cal.set(Calendar.DAY_OF_MONTH, 0); - break; - - case UsageStatsManager.INTERVAL_WEEKLY: - cal.set(Calendar.DAY_OF_WEEK, 0); - break; - - case UsageStatsManager.INTERVAL_DAILY: - break; - - default: - throw new UnsupportedOperationException("Can't truncate date to bucket " + bucket); - } - } -} diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 7142a99..8876495 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -32,7 +32,6 @@ import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; import java.util.List; /** @@ -47,7 +46,7 @@ class UserUsageStatsService { private final UsageStatsDatabase mDatabase; private final IntervalStats[] mCurrentStats; private boolean mStatsChanged = false; - private final Calendar mDailyExpiryDate; + private final UnixCalendar mDailyExpiryDate; private final StatsUpdatedListener mListener; private final String mLogPrefix; @@ -56,7 +55,7 @@ class UserUsageStatsService { } UserUsageStatsService(int userId, File usageStatsDir, StatsUpdatedListener listener) { - mDailyExpiryDate = Calendar.getInstance(); + mDailyExpiryDate = new UnixCalendar(0); mDatabase = new UsageStatsDatabase(usageStatsDir); mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT]; mListener = listener; @@ -66,6 +65,7 @@ class UserUsageStatsService { void init() { mDatabase.init(); + final long timeNow = System.currentTimeMillis(); int nullCount = 0; for (int i = 0; i < mCurrentStats.length; i++) { mCurrentStats[i] = mDatabase.getLatestUsageStats(i); @@ -73,6 +73,11 @@ class UserUsageStatsService { // Find out how many intervals we don't have data for. // Ideally it should be all or none. nullCount++; + } else if (mCurrentStats[i].beginTime > timeNow) { + Slog.e(TAG, mLogPrefix + "Interval " + i + " has stat in the future " + + mCurrentStats[i].beginTime); + mCurrentStats[i] = null; + nullCount++; } } @@ -94,10 +99,11 @@ class UserUsageStatsService { // that is reported. mDailyExpiryDate.setTimeInMillis( mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime); - mDailyExpiryDate.add(Calendar.DAY_OF_YEAR, 1); - UsageStatsUtils.truncateDateTo(UsageStatsManager.INTERVAL_DAILY, mDailyExpiryDate); - Slog.i(TAG, mLogPrefix + "Rollover scheduled for " - + sDateFormat.format(mDailyExpiryDate.getTime())); + mDailyExpiryDate.addDays(1); + mDailyExpiryDate.truncateToDay(); + Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " + + sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + + "(" + mDailyExpiryDate.getTimeInMillis() + ")"); } // Now close off any events that were open at the time this was saved. @@ -195,49 +201,68 @@ class UserUsageStatsService { * and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner} * provided to select the stats to use from the IntervalStats object. */ - private <T> List<T> queryStats(int bucketType, long beginTime, long endTime, + private <T> List<T> queryStats(int intervalType, final long beginTime, final long endTime, StatCombiner<T> combiner) { - if (bucketType == UsageStatsManager.INTERVAL_BEST) { - bucketType = mDatabase.findBestFitBucket(beginTime, endTime); + if (intervalType == UsageStatsManager.INTERVAL_BEST) { + intervalType = mDatabase.findBestFitBucket(beginTime, endTime); + if (intervalType < 0) { + // Nothing saved to disk yet, so every stat is just as equal (no rollover has + // occurred. + intervalType = UsageStatsManager.INTERVAL_DAILY; + } } - if (bucketType < 0 || bucketType >= mCurrentStats.length) { + if (intervalType < 0 || intervalType >= mCurrentStats.length) { if (DEBUG) { - Slog.d(TAG, mLogPrefix + "Bad bucketType used " + bucketType); + Slog.d(TAG, mLogPrefix + "Bad intervalType used " + intervalType); } return null; } - if (beginTime >= mCurrentStats[bucketType].endTime) { + final IntervalStats currentStats = mCurrentStats[intervalType]; + + if (DEBUG) { + Slog.d(TAG, mLogPrefix + "SELECT * FROM " + intervalType + " WHERE beginTime >= " + + beginTime + " AND endTime < " + endTime); + } + + if (beginTime >= currentStats.endTime) { if (DEBUG) { Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is " - + mCurrentStats[bucketType].endTime); + + currentStats.endTime); } // Nothing newer available. return null; - - } else if (beginTime >= mCurrentStats[bucketType].beginTime) { - if (DEBUG) { - Slog.d(TAG, mLogPrefix + "Returning in-memory stats for bucket " + bucketType); - } - // Fast path for retrieving in-memory state. - ArrayList<T> results = new ArrayList<>(); - combiner.combine(mCurrentStats[bucketType], true, results); - return results; } - // Flush any changes that were made to disk before we do a disk query. - // If we're not grabbing the ongoing stats, no need to persist. - persistActiveStats(); + // Truncate the endTime to just before the in-memory stats. Then, we'll append the + // in-memory stats to the results (if necessary) so as to avoid writing to disk too + // often. + final long truncatedEndTime = Math.min(currentStats.beginTime, endTime); + // Get the stats from disk. + List<T> results = mDatabase.queryUsageStats(intervalType, beginTime, + truncatedEndTime, combiner); if (DEBUG) { - Slog.d(TAG, mLogPrefix + "SELECT * FROM " + bucketType + " WHERE beginTime >= " - + beginTime + " AND endTime < " + endTime); + Slog.d(TAG, "Got " + (results != null ? results.size() : 0) + " results from disk"); + Slog.d(TAG, "Current stats beginTime=" + currentStats.beginTime + + " endTime=" + currentStats.endTime); + } + + // Now check if the in-memory stats match the range and add them if they do. + if (beginTime < currentStats.endTime && endTime > currentStats.beginTime) { + if (DEBUG) { + Slog.d(TAG, mLogPrefix + "Returning in-memory stats"); + } + + if (results == null) { + results = new ArrayList<>(); + } + combiner.combine(currentStats, true, results); } - final List<T> results = mDatabase.queryUsageStats(bucketType, beginTime, endTime, combiner); if (DEBUG) { - Slog.d(TAG, mLogPrefix + "Results: " + (results == null ? 0 : results.size())); + Slog.d(TAG, mLogPrefix + "Results: " + (results != null ? results.size() : 0)); } return results; } @@ -250,44 +275,45 @@ class UserUsageStatsService { return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner); } - UsageEvents queryEvents(long beginTime, long endTime) { - if (endTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime) { - if (beginTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].endTime) { - return null; - } - - TimeSparseArray<UsageEvents.Event> events = - mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events; - if (events == null) { - return null; - } - - final int startIndex = events.closestIndexOnOrAfter(beginTime); - if (startIndex < 0) { - return null; - } + UsageEvents queryEvents(final long beginTime, final long endTime) { + final ArraySet<String> names = new ArraySet<>(); + List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY, + beginTime, endTime, new StatCombiner<UsageEvents.Event>() { + @Override + public void combine(IntervalStats stats, boolean mutable, + List<UsageEvents.Event> accumulatedResult) { + if (stats.events == null) { + return; + } + + final int startIndex = stats.events.closestIndexOnOrAfter(beginTime); + if (startIndex < 0) { + return; + } + + final int size = stats.events.size(); + for (int i = startIndex; i < size; i++) { + if (stats.events.keyAt(i) >= endTime) { + return; + } + + final UsageEvents.Event event = stats.events.valueAt(i); + names.add(event.mPackage); + if (event.mClass != null) { + names.add(event.mClass); + } + accumulatedResult.add(event); + } + } + }); - ArraySet<String> names = new ArraySet<>(); - ArrayList<UsageEvents.Event> results = new ArrayList<>(); - final int size = events.size(); - for (int i = startIndex; i < size; i++) { - if (events.keyAt(i) >= endTime) { - break; - } - final UsageEvents.Event event = events.valueAt(i); - names.add(event.mPackage); - if (event.mClass != null) { - names.add(event.mClass); - } - results.add(event); - } - String[] table = names.toArray(new String[names.size()]); - Arrays.sort(table); - return new UsageEvents(results, table); + if (results == null || results.isEmpty()) { + return null; } - // TODO(adamlesinski): Query the previous days. - return null; + String[] table = names.toArray(new String[names.size()]); + Arrays.sort(table); + return new UsageEvents(results, table); } void persistActiveStats() { @@ -360,54 +386,53 @@ class UserUsageStatsService { private void loadActiveStats() { final long timeNow = System.currentTimeMillis(); - Calendar tempCal = mDailyExpiryDate; - for (int bucketType = 0; bucketType < mCurrentStats.length; bucketType++) { + final UnixCalendar tempCal = mDailyExpiryDate; + for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) { tempCal.setTimeInMillis(timeNow); - UsageStatsUtils.truncateDateTo(bucketType, tempCal); + UnixCalendar.truncateTo(tempCal, intervalType); - if (mCurrentStats[bucketType] != null && - mCurrentStats[bucketType].beginTime == tempCal.getTimeInMillis()) { + if (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(bucketType); - if (lastBeginTime >= tempCal.getTimeInMillis()) { - if (DEBUG) { - Slog.d(TAG, mLogPrefix + "Loading existing stats (" + lastBeginTime + - ") for bucket " + bucketType); - } - mCurrentStats[bucketType] = mDatabase.getLatestUsageStats(bucketType); + final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(intervalType); + if (lastBeginTime > timeNow) { + Slog.e(TAG, mLogPrefix + "Latest usage stats for interval " + + intervalType + " begins in the future"); + mCurrentStats[intervalType] = null; + } else if (lastBeginTime >= tempCal.getTimeInMillis()) { if (DEBUG) { - if (mCurrentStats[bucketType] != null) { - Slog.d(TAG, mLogPrefix + "Found " + - (mCurrentStats[bucketType].events == null ? - 0 : mCurrentStats[bucketType].events.size()) + - " events"); - } + Slog.d(TAG, mLogPrefix + "Loading existing stats @ " + + sDateFormat.format(lastBeginTime) + "(" + lastBeginTime + + ") for interval " + intervalType); } + mCurrentStats[intervalType] = mDatabase.getLatestUsageStats(intervalType); } else { - mCurrentStats[bucketType] = null; + mCurrentStats[intervalType] = null; } - if (mCurrentStats[bucketType] == null) { + if (mCurrentStats[intervalType] == null) { if (DEBUG) { - Slog.d(TAG, "Creating new stats (" + tempCal.getTimeInMillis() + - ") for bucket " + bucketType); + Slog.d(TAG, "Creating new stats @ " + + sDateFormat.format(tempCal.getTimeInMillis()) + "(" + + tempCal.getTimeInMillis() + ") for interval " + intervalType); } - mCurrentStats[bucketType] = new IntervalStats(); - mCurrentStats[bucketType].beginTime = tempCal.getTimeInMillis(); - mCurrentStats[bucketType].endTime = timeNow; + mCurrentStats[intervalType] = new IntervalStats(); + mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis(); + mCurrentStats[intervalType].endTime = timeNow; } } mStatsChanged = false; mDailyExpiryDate.setTimeInMillis(timeNow); - mDailyExpiryDate.add(Calendar.DAY_OF_YEAR, 1); - UsageStatsUtils.truncateDateTo(UsageStatsManager.INTERVAL_DAILY, mDailyExpiryDate); - Slog.i(TAG, mLogPrefix + "Rollover scheduled for " - + sDateFormat.format(mDailyExpiryDate.getTime())); + mDailyExpiryDate.addDays(1); + mDailyExpiryDate.truncateToDay(); + Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " + + sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" + + tempCal.getTimeInMillis() + ")"); } |