diff options
author | Adam Lesinski <adamlesinski@google.com> | 2014-09-05 15:38:05 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2014-09-05 23:57:42 +0000 |
commit | 37a46b48dcb7e34ee3669cfb2ed78af08bfca3c7 (patch) | |
tree | e6e9012966c56f386d6fb496ceb9d3bd2dd8707e /services/usage/java/com/android/server | |
parent | cd922b29b5448c5c884d4b06bf9d1f3e7bb7bce0 (diff) | |
download | frameworks_base-37a46b48dcb7e34ee3669cfb2ed78af08bfca3c7.zip frameworks_base-37a46b48dcb7e34ee3669cfb2ed78af08bfca3c7.tar.gz frameworks_base-37a46b48dcb7e34ee3669cfb2ed78af08bfca3c7.tar.bz2 |
Store time offsets for UsageStats XML
This will make adjusting for time changes easier
in the future.
Change-Id: I49d2dda4cc6dcb1378a58c814849924f585e0417
Diffstat (limited to 'services/usage/java/com/android/server')
6 files changed, 122 insertions, 87 deletions
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java index 6c80a65..5f639ab 100644 --- a/services/usage/java/com/android/server/usage/IntervalStats.java +++ b/services/usage/java/com/android/server/usage/IntervalStats.java @@ -23,13 +23,11 @@ import android.content.res.Configuration; import android.util.ArrayMap; import android.util.ArraySet; -import java.util.ArrayList; - class IntervalStats { public long beginTime; public long endTime; public long lastTimeSaved; - public final ArrayMap<String, UsageStats> stats = new ArrayMap<>(); + public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>(); public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>(); public Configuration activeConfiguration; public TimeSparseArray<UsageEvents.Event> events; @@ -44,13 +42,13 @@ class IntervalStats { * Gets the UsageStats object for the given package, or creates one and adds it internally. */ UsageStats getOrCreateUsageStats(String packageName) { - UsageStats usageStats = stats.get(packageName); + UsageStats usageStats = packageStats.get(packageName); if (usageStats == null) { usageStats = new UsageStats(); usageStats.mPackageName = getCachedStringRef(packageName); usageStats.mBeginTimeStamp = beginTime; usageStats.mEndTimeStamp = endTime; - stats.put(usageStats.mPackageName, usageStats); + packageStats.put(usageStats.mPackageName, usageStats); } return usageStats; } diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java index 6c5fa78..62a7ec0 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java +++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java @@ -35,7 +35,7 @@ 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 int CURRENT_VERSION = 2; private static final String TAG = "UsageStatsDatabase"; private static final boolean DEBUG = UsageStatsService.DEBUG; @@ -90,7 +90,8 @@ class UsageStatsDatabase { } for (File f : files) { - mSortedStatFiles[i].put(Long.parseLong(f.getName()), new AtomicFile(f)); + final AtomicFile af = new AtomicFile(f); + mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af); } } } @@ -107,7 +108,7 @@ class UsageStatsDatabase { if (version != CURRENT_VERSION) { Slog.i(TAG, "Upgrading from version " + version + " to " + CURRENT_VERSION); - doUpgradeLocked(version, CURRENT_VERSION); + doUpgradeLocked(version); try (BufferedWriter writer = new BufferedWriter(new FileWriter(mVersionFile))) { writer.write(Integer.toString(CURRENT_VERSION)); @@ -118,8 +119,8 @@ class UsageStatsDatabase { } } - private void doUpgradeLocked(int thisVersion, int nextVersion) { - if (thisVersion == 0) { + private void doUpgradeLocked(int thisVersion) { + if (thisVersion < 2) { // 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"); diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 8aa3d66..2dcdcc4 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -38,6 +38,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.util.ArraySet; @@ -76,6 +77,8 @@ public class UsageStatsService extends SystemService implements private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private File mUsageStatsDir; + long mRealTimeSnapshot; + long mSystemTimeSnapshot; public UsageStatsService(Context context) { super(context); @@ -102,6 +105,9 @@ public class UsageStatsService extends SystemService implements cleanUpRemovedUsersLocked(); } + mRealTimeSnapshot = SystemClock.elapsedRealtime(); + mSystemTimeSnapshot = System.currentTimeMillis(); + publishLocalService(UsageStatsManagerInternal.class, new LocalService()); publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); } @@ -380,6 +386,14 @@ public class UsageStatsService extends SystemService implements */ private class LocalService extends UsageStatsManagerInternal { + /** + * The system may have its time change, so at least make sure the events + * are monotonic in order. + */ + private long computeMonotonicSystemTime(long realTime) { + return (realTime - mRealTimeSnapshot) + mSystemTimeSnapshot; + } + @Override public void reportEvent(ComponentName component, int userId, int eventType) { if (component == null) { @@ -390,7 +404,7 @@ public class UsageStatsService extends SystemService implements UsageEvents.Event event = new UsageEvents.Event(); event.mPackage = component.getPackageName(); event.mClass = component.getClassName(); - event.mTimeStamp = System.currentTimeMillis(); + event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime()); event.mEventType = eventType; mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); } @@ -404,7 +418,7 @@ public class UsageStatsService extends SystemService implements UsageEvents.Event event = new UsageEvents.Event(); event.mPackage = "android"; - event.mTimeStamp = System.currentTimeMillis(); + event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime()); event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE; event.mConfiguration = new Configuration(config); mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java index 48881d0..9ce6d63 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsXml.java +++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java @@ -37,10 +37,15 @@ public class UsageStatsXml { private static final String USAGESTATS_TAG = "usagestats"; private static final String VERSION_ATTR = "version"; + public static long parseBeginTime(AtomicFile file) { + return Long.parseLong(file.getBaseFile().getName()); + } + public static void read(AtomicFile file, IntervalStats statsOut) throws IOException { try { FileInputStream in = file.openRead(); try { + statsOut.beginTime = parseBeginTime(file); read(in, statsOut); statsOut.lastTimeSaved = file.getLastModifiedTime(); } finally { diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java index 6529950..ef95a7b 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java +++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java @@ -15,7 +15,6 @@ */ package com.android.server.usage; -import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -26,44 +25,52 @@ import android.app.usage.ConfigurationStats; import android.app.usage.TimeSparseArray; import android.app.usage.UsageEvents; import android.app.usage.UsageStats; -import android.content.ComponentName; import android.content.res.Configuration; import java.io.IOException; import java.net.ProtocolException; -import java.util.Locale; /** * UsageStats reader/writer for version 1 of the XML format. */ final class UsageStatsXmlV1 { + private static final String PACKAGES_TAG = "packages"; private static final String PACKAGE_TAG = "package"; - private static final String CONFIGURATION_TAG = "config"; + + private static final String CONFIGURATIONS_TAG = "configurations"; + private static final String CONFIG_TAG = "config"; + private static final String EVENT_LOG_TAG = "event-log"; + private static final String EVENT_TAG = "event"; - private static final String BEGIN_TIME_ATTR = "beginTime"; - private static final String END_TIME_ATTR = "endTime"; - private static final String NAME_ATTR = "name"; + // Attributes private static final String PACKAGE_ATTR = "package"; private static final String CLASS_ATTR = "class"; - private static final String TOTAL_TIME_ACTIVE_ATTR = "totalTimeActive"; - private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive"; + private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive"; private static final String COUNT_ATTR = "count"; private static final String ACTIVE_ATTR = "active"; private static final String LAST_EVENT_ATTR = "lastEvent"; private static final String TYPE_ATTR = "type"; + + // Time attributes stored as an offset of the beginTime. + private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive"; + private static final String END_TIME_ATTR = "endTime"; private static final String TIME_ATTR = "time"; private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut) throws XmlPullParserException, IOException { - final String name = parser.getAttributeValue(null, NAME_ATTR); - if (name == null) { - throw new ProtocolException("no " + NAME_ATTR + " attribute present"); + final String pkg = parser.getAttributeValue(null, PACKAGE_ATTR); + if (pkg == null) { + throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present"); } - UsageStats stats = statsOut.getOrCreateUsageStats(name); + final UsageStats stats = statsOut.getOrCreateUsageStats(pkg); + + // Apply the offset to the beginTime to find the absolute time. + stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute( + parser, LAST_TIME_ACTIVE_ATTR); + stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR); - stats.mLastTimeUsed = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR); stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR); } @@ -72,8 +79,12 @@ final class UsageStatsXmlV1 { final Configuration config = new Configuration(); Configuration.readXmlAttrs(parser, config); - ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config); - configStats.mLastTimeActive = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR); + final ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config); + + // Apply the offset to the beginTime to find the absolute time. + configStats.mLastTimeActive = statsOut.beginTime + XmlUtils.readLongAttribute( + parser, LAST_TIME_ACTIVE_ATTR); + configStats.mTotalTimeActive = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR); configStats.mActivationCount = XmlUtils.readIntAttribute(parser, COUNT_ATTR); if (XmlUtils.readBooleanAttribute(parser, ACTIVE_ATTR)) { @@ -83,30 +94,19 @@ final class UsageStatsXmlV1 { private static void loadEvent(XmlPullParser parser, IntervalStats statsOut) throws XmlPullParserException, IOException { - String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR); - String className; + final String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR); if (packageName == null) { - // Try getting the component name if it exists. - final String componentName = XmlUtils.readStringAttribute(parser, NAME_ATTR); - if (componentName == null) { - throw new ProtocolException("no " + NAME_ATTR + " or " + PACKAGE_ATTR + - " attribute present"); - } - ComponentName component = ComponentName.unflattenFromString(componentName); - if (component == null) { - throw new ProtocolException("ComponentName " + componentName + " is invalid"); - } - - packageName = component.getPackageName(); - className = component.getClassName(); - } else { - className = XmlUtils.readStringAttribute(parser, CLASS_ATTR); + throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present"); } - UsageEvents.Event event = statsOut.buildEvent(packageName, className); - event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR); - event.mTimeStamp = XmlUtils.readLongAttribute(parser, TIME_ATTR); + final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR); + final UsageEvents.Event event = statsOut.buildEvent(packageName, className); + + // Apply the offset to the beginTime to find the absolute time of this event. + event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR); + + event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR); if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) { event.mConfiguration = new Configuration(); Configuration.readXmlAttrs(parser, event.mConfiguration); @@ -118,48 +118,60 @@ final class UsageStatsXmlV1 { statsOut.events.put(event.mTimeStamp, event); } - private static void writeUsageStats(XmlSerializer xml, final UsageStats stats) - throws IOException { + private static void writeUsageStats(XmlSerializer xml, final IntervalStats stats, + final UsageStats usageStats) throws IOException { xml.startTag(null, PACKAGE_TAG); - XmlUtils.writeStringAttribute(xml, NAME_ATTR, stats.mPackageName); - XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, stats.mTotalTimeInForeground); - XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, stats.mLastTimeUsed); - XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, stats.mLastEvent); + + // Write the time offset. + XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, + usageStats.mLastTimeUsed - stats.beginTime); + + XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName); + XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground); + XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent); + xml.endTag(null, PACKAGE_TAG); } - private static void writeConfigStats(XmlSerializer xml, final ConfigurationStats stats, - boolean isActive) throws IOException { - xml.startTag(null, CONFIGURATION_TAG); - XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, stats.mLastTimeActive); - XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, stats.mTotalTimeActive); - XmlUtils.writeIntAttribute(xml, COUNT_ATTR, stats.mActivationCount); + private static void writeConfigStats(XmlSerializer xml, final IntervalStats stats, + final ConfigurationStats configStats, boolean isActive) throws IOException { + xml.startTag(null, CONFIG_TAG); + + // Write the time offset. + XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, + configStats.mLastTimeActive - stats.beginTime); + + XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, configStats.mTotalTimeActive); + XmlUtils.writeIntAttribute(xml, COUNT_ATTR, configStats.mActivationCount); if (isActive) { XmlUtils.writeBooleanAttribute(xml, ACTIVE_ATTR, true); } // Now write the attributes representing the configuration object. - Configuration.writeXmlAttrs(xml, stats.mConfiguration); + Configuration.writeXmlAttrs(xml, configStats.mConfiguration); - xml.endTag(null, CONFIGURATION_TAG); + xml.endTag(null, CONFIG_TAG); } - private static void writeEvent(XmlSerializer xml, final UsageEvents.Event event) - throws IOException { - xml.startTag(null, EVENT_LOG_TAG); + private static void writeEvent(XmlSerializer xml, final IntervalStats stats, + final UsageEvents.Event event) throws IOException { + xml.startTag(null, EVENT_TAG); + + // Store the time offset. + XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp - stats.beginTime); + XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, event.mPackage); if (event.mClass != null) { XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass); } XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType); - XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp); if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE && event.mConfiguration != null) { Configuration.writeXmlAttrs(xml, event.mConfiguration); } - xml.endTag(null, EVENT_LOG_TAG); + xml.endTag(null, EVENT_TAG); } /** @@ -171,7 +183,7 @@ final class UsageStatsXmlV1 { */ public static void read(XmlPullParser parser, IntervalStats statsOut) throws XmlPullParserException, IOException { - statsOut.stats.clear(); + statsOut.packageStats.clear(); statsOut.configurations.clear(); statsOut.activeConfiguration = null; @@ -179,7 +191,6 @@ final class UsageStatsXmlV1 { statsOut.events.clear(); } - statsOut.beginTime = XmlUtils.readLongAttribute(parser, BEGIN_TIME_ATTR); statsOut.endTime = XmlUtils.readLongAttribute(parser, END_TIME_ATTR); int eventCode; @@ -196,11 +207,11 @@ final class UsageStatsXmlV1 { loadUsageStats(parser, statsOut); break; - case CONFIGURATION_TAG: + case CONFIG_TAG: loadConfigStats(parser, statsOut); break; - case EVENT_LOG_TAG: + case EVENT_TAG: loadEvent(parser, statsOut); break; } @@ -208,32 +219,38 @@ final class UsageStatsXmlV1 { } /** - * Writes the stats object to an XML file. The {@link FastXmlSerializer} + * Writes the stats object to an XML file. The {@link XmlSerializer} * has already written the <code><usagestats></code> tag, but attributes may still * be added. * - * @param serializer The serializer to which to write the stats data. + * @param xml The serializer to which to write the packageStats data. * @param stats The stats object to write to the XML file. */ - public static void write(FastXmlSerializer serializer, IntervalStats stats) throws IOException { - serializer.attribute(null, BEGIN_TIME_ATTR, Long.toString(stats.beginTime)); - serializer.attribute(null, END_TIME_ATTR, Long.toString(stats.endTime)); + public static void write(XmlSerializer xml, IntervalStats stats) throws IOException { + XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime); - final int statsCount = stats.stats.size(); + xml.startTag(null, PACKAGES_TAG); + final int statsCount = stats.packageStats.size(); for (int i = 0; i < statsCount; i++) { - writeUsageStats(serializer, stats.stats.valueAt(i)); + writeUsageStats(xml, stats, stats.packageStats.valueAt(i)); } + xml.endTag(null, PACKAGES_TAG); + + xml.startTag(null, CONFIGURATIONS_TAG); final int configCount = stats.configurations.size(); for (int i = 0; i < configCount; i++) { boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i)); - writeConfigStats(serializer, stats.configurations.valueAt(i), active); + writeConfigStats(xml, stats, stats.configurations.valueAt(i), active); } + xml.endTag(null, CONFIGURATIONS_TAG); + xml.startTag(null, EVENT_LOG_TAG); final int eventCount = stats.events != null ? stats.events.size() : 0; for (int i = 0; i < eventCount; i++) { - writeEvent(serializer, stats.events.valueAt(i)); + writeEvent(xml, stats, stats.events.valueAt(i)); } + xml.endTag(null, EVENT_LOG_TAG); } private UsageStatsXmlV1() { diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 8876495..2769666 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -108,9 +108,9 @@ class UserUsageStatsService { // Now close off any events that were open at the time this was saved. for (IntervalStats stat : mCurrentStats) { - final int pkgCount = stat.stats.size(); + final int pkgCount = stat.packageStats.size(); for (int i = 0; i < pkgCount; i++) { - UsageStats pkgStats = stat.stats.valueAt(i); + UsageStats pkgStats = stat.packageStats.valueAt(i); if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND || pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) { stat.update(pkgStats.mPackageName, stat.lastTimeSaved, @@ -168,13 +168,13 @@ class UserUsageStatsService { public void combine(IntervalStats stats, boolean mutable, List<UsageStats> accResult) { if (!mutable) { - accResult.addAll(stats.stats.values()); + accResult.addAll(stats.packageStats.values()); return; } - final int statCount = stats.stats.size(); + final int statCount = stats.packageStats.size(); for (int i = 0; i < statCount; i++) { - accResult.add(new UsageStats(stats.stats.valueAt(i))); + accResult.add(new UsageStats(stats.packageStats.valueAt(i))); } } }; @@ -340,9 +340,9 @@ class UserUsageStatsService { mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration; ArraySet<String> continuePreviousDay = new ArraySet<>(); for (IntervalStats stat : mCurrentStats) { - final int pkgCount = stat.stats.size(); + final int pkgCount = stat.packageStats.size(); for (int i = 0; i < pkgCount; i++) { - UsageStats pkgStats = stat.stats.valueAt(i); + UsageStats pkgStats = stat.packageStats.valueAt(i); if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND || pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) { continuePreviousDay.add(pkgStats.mPackageName); |