UsageStatsXmlV1.java revision 3516800b611a79339a3c188332d13a26e9086b09
13516800b611a79339a3c188332d13a26e9086b09Adam Lesinski/** 23516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Copyright (C) 2014 The Android Open Source Project 33516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 43516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); you may not 53516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * use this file except in compliance with the License. You may obtain a copy 63516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * of the License at 73516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 83516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 93516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 103516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Unless required by applicable law or agreed to in writing, software 113516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 123516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 133516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * License for the specific language governing permissions and limitations 143516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * under the License. 153516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 163516800b611a79339a3c188332d13a26e9086b09Adam Lesinskipackage com.android.server.usage; 173516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 183516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport com.android.internal.util.FastXmlSerializer; 193516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport com.android.internal.util.XmlUtils; 203516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 213516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport org.xmlpull.v1.XmlPullParser; 223516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport org.xmlpull.v1.XmlPullParserException; 233516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 243516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.TimeSparseArray; 253516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageEvents; 263516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageStats; 273516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.content.ComponentName; 283516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 293516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport java.io.IOException; 303516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport java.net.ProtocolException; 313516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 323516800b611a79339a3c188332d13a26e9086b09Adam Lesinski/** 333516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * UsageStats reader/writer for version 1 of the XML format. 343516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 353516800b611a79339a3c188332d13a26e9086b09Adam Lesinskifinal class UsageStatsXmlV1 { 363516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String BEGIN_TIME_ATTR = "beginTime"; 373516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String END_TIME_ATTR = "endTime"; 383516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String PACKAGE_TAG = "package"; 393516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String NAME_ATTR = "name"; 403516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String TOTAL_TIME_ACTIVE_ATTR = "totalTimeActive"; 413516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive"; 423516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String LAST_EVENT_ATTR = "lastEvent"; 433516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String EVENT_LOG_TAG = "event-log"; 443516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String TYPE_ATTR = "type"; 453516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String TIME_ATTR = "time"; 463516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 473516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static UsageStats readNextUsageStats(XmlPullParser parser) 483516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws XmlPullParserException, IOException { 493516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (parser.getEventType() != XmlPullParser.START_TAG) { 503516800b611a79339a3c188332d13a26e9086b09Adam Lesinski XmlUtils.nextElement(parser); 513516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 523516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 533516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (parser.getEventType() != XmlPullParser.START_TAG || 543516800b611a79339a3c188332d13a26e9086b09Adam Lesinski !parser.getName().equals(PACKAGE_TAG)) { 553516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return null; 563516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 573516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 583516800b611a79339a3c188332d13a26e9086b09Adam Lesinski final String name = parser.getAttributeValue(null, NAME_ATTR); 593516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (name == null) { 603516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throw new ProtocolException("no " + NAME_ATTR + " attribute present"); 613516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 623516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski UsageStats stats = new UsageStats(); 643516800b611a79339a3c188332d13a26e9086b09Adam Lesinski stats.mPackageName = name; 653516800b611a79339a3c188332d13a26e9086b09Adam Lesinski stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR); 663516800b611a79339a3c188332d13a26e9086b09Adam Lesinski stats.mLastTimeUsed = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR); 673516800b611a79339a3c188332d13a26e9086b09Adam Lesinski stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR); 683516800b611a79339a3c188332d13a26e9086b09Adam Lesinski XmlUtils.skipCurrentTag(parser); 693516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return stats; 703516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 713516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 723516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static UsageEvents.Event readNextEvent(XmlPullParser parser, IntervalStats statsOut) 733516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws XmlPullParserException, IOException { 743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (parser.getEventType() != XmlPullParser.START_TAG) { 753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski XmlUtils.nextElement(parser); 763516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 783516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (parser.getEventType() != XmlPullParser.START_TAG || 793516800b611a79339a3c188332d13a26e9086b09Adam Lesinski !parser.getName().equals(EVENT_LOG_TAG)) { 803516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return null; 813516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 823516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 833516800b611a79339a3c188332d13a26e9086b09Adam Lesinski final String componentName = XmlUtils.readStringAttribute(parser, NAME_ATTR); 843516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (componentName == null) { 853516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throw new ProtocolException("no " + NAME_ATTR + " attribute present"); 863516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 873516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 883516800b611a79339a3c188332d13a26e9086b09Adam Lesinski ComponentName component = statsOut.getCachedComponentName(componentName); 893516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (component == null) { 903516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throw new ProtocolException("ComponentName " + componentName + " is invalid"); 913516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 923516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 933516800b611a79339a3c188332d13a26e9086b09Adam Lesinski UsageEvents.Event event = new UsageEvents.Event(); 943516800b611a79339a3c188332d13a26e9086b09Adam Lesinski event.mComponent = component; 953516800b611a79339a3c188332d13a26e9086b09Adam Lesinski event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR); 963516800b611a79339a3c188332d13a26e9086b09Adam Lesinski event.mTimeStamp = XmlUtils.readLongAttribute(parser, TIME_ATTR); 973516800b611a79339a3c188332d13a26e9086b09Adam Lesinski XmlUtils.skipCurrentTag(parser); 983516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return event; 993516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1003516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1013516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static void writeUsageStats(FastXmlSerializer serializer, UsageStats stats) 1023516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws IOException { 1033516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.startTag(null, PACKAGE_TAG); 1043516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, NAME_ATTR, stats.mPackageName); 1053516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, TOTAL_TIME_ACTIVE_ATTR, 1063516800b611a79339a3c188332d13a26e9086b09Adam Lesinski Long.toString(stats.mTotalTimeInForeground)); 1073516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, LAST_TIME_ACTIVE_ATTR, Long.toString(stats.mLastTimeUsed)); 1083516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, LAST_EVENT_ATTR, Integer.toString(stats.mLastEvent)); 1093516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.endTag(null, PACKAGE_TAG); 1103516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1113516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1123516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static void writeEvent(FastXmlSerializer serializer, UsageEvents.Event event) 1133516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws IOException { 1143516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.startTag(null, EVENT_LOG_TAG); 1153516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, NAME_ATTR, event.getComponent().flattenToString()); 1163516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, TYPE_ATTR, Integer.toString(event.getEventType())); 1173516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, TIME_ATTR, Long.toString(event.getTimeStamp())); 1183516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.endTag(null, EVENT_LOG_TAG); 1193516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1203516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1213516800b611a79339a3c188332d13a26e9086b09Adam Lesinski /** 1223516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Reads from the {@link XmlPullParser}, assuming that it is already on the 1233516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * <code><usagestats></code> tag. 1243516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 1253516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param parser The parser from which to read events. 1263516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param statsOut The stats object to populate with the data from the XML file. 1273516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 1283516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public static void read(XmlPullParser parser, IntervalStats statsOut) 1293516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws XmlPullParserException, IOException { 1303516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.stats.clear(); 1313516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1323516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (statsOut.events != null) { 1333516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.events.clear(); 1343516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1353516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1363516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.beginTime = XmlUtils.readLongAttribute(parser, BEGIN_TIME_ATTR); 1373516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.endTime = XmlUtils.readLongAttribute(parser, END_TIME_ATTR); 1383516800b611a79339a3c188332d13a26e9086b09Adam Lesinski XmlUtils.nextElement(parser); 1393516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1403516800b611a79339a3c188332d13a26e9086b09Adam Lesinski UsageStats pkgStats; 1413516800b611a79339a3c188332d13a26e9086b09Adam Lesinski while ((pkgStats = readNextUsageStats(parser)) != null) { 1423516800b611a79339a3c188332d13a26e9086b09Adam Lesinski pkgStats.mBeginTimeStamp = statsOut.beginTime; 1433516800b611a79339a3c188332d13a26e9086b09Adam Lesinski pkgStats.mEndTimeStamp = statsOut.endTime; 1443516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.stats.put(pkgStats.mPackageName, pkgStats); 1453516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1463516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1473516800b611a79339a3c188332d13a26e9086b09Adam Lesinski UsageEvents.Event event; 1483516800b611a79339a3c188332d13a26e9086b09Adam Lesinski while ((event = readNextEvent(parser, statsOut)) != null) { 1493516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (statsOut.events == null) { 1503516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.events = new TimeSparseArray<>(); 1513516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1523516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.events.put(event.getTimeStamp(), event); 1533516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1543516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1553516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1563516800b611a79339a3c188332d13a26e9086b09Adam Lesinski /** 1573516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Writes the stats object to an XML file. The {@link FastXmlSerializer} 1583516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * has already written the <code><usagestats></code> tag, but attributes may still 1593516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * be added. 1603516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 1613516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param serializer The serializer to which to write the stats data. 1623516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param stats The stats object to write to the XML file. 1633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 1643516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public static void write(FastXmlSerializer serializer, IntervalStats stats) throws IOException { 1653516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, BEGIN_TIME_ATTR, Long.toString(stats.beginTime)); 1663516800b611a79339a3c188332d13a26e9086b09Adam Lesinski serializer.attribute(null, END_TIME_ATTR, Long.toString(stats.endTime)); 1673516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1683516800b611a79339a3c188332d13a26e9086b09Adam Lesinski final int statsCount = stats.stats.size(); 1693516800b611a79339a3c188332d13a26e9086b09Adam Lesinski for (int i = 0; i < statsCount; i++) { 1703516800b611a79339a3c188332d13a26e9086b09Adam Lesinski writeUsageStats(serializer, stats.stats.valueAt(i)); 1713516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1723516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1733516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (stats.events != null) { 1743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski final int eventCount = stats.events.size(); 1753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski for (int i = 0; i < eventCount; i++) { 1763516800b611a79339a3c188332d13a26e9086b09Adam Lesinski writeEvent(serializer, stats.events.valueAt(i)); 1773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1783516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1793516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1803516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1813516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private UsageStatsXmlV1() { 1823516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1833516800b611a79339a3c188332d13a26e9086b09Adam Lesinski} 184