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.XmlUtils; 193516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 203516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport org.xmlpull.v1.XmlPullParser; 213516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport org.xmlpull.v1.XmlPullParserException; 227f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport org.xmlpull.v1.XmlSerializer; 233516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 247f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.app.usage.ConfigurationStats; 2560aa35b756707a16d310c222a36edbcef9d56ed4Suprabh Shuklaimport android.app.usage.EventList; 263516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageEvents; 273516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageStats; 287f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.content.res.Configuration; 2953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Liimport android.util.ArrayMap; 303516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 313516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport java.io.IOException; 323516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport java.net.ProtocolException; 333516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 343516800b611a79339a3c188332d13a26e9086b09Adam Lesinski/** 353516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * UsageStats reader/writer for version 1 of the XML format. 363516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 373516800b611a79339a3c188332d13a26e9086b09Adam Lesinskifinal class UsageStatsXmlV1 { 38ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki private static final String TAG = "UsageStatsXmlV1"; 39ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki 40ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn private static final String INTERACTIVE_TAG = "interactive"; 41ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn private static final String NON_INTERACTIVE_TAG = "non-interactive"; 423378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn private static final String KEYGUARD_SHOWN_TAG = "keyguard-shown"; 433378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn private static final String KEYGUARD_HIDDEN_TAG = "keyguard-hidden"; 44ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn 4537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String PACKAGES_TAG = "packages"; 467f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static final String PACKAGE_TAG = "package"; 4737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 4853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static final String CHOOSER_COUNT_TAG = "chosen_action"; 4953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static final String CATEGORY_TAG = "category"; 5053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static final String NAME = "name"; 5153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static final String COUNT = "count"; 5253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li 5337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String CONFIGURATIONS_TAG = "configurations"; 5437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String CONFIG_TAG = "config"; 5537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 567f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static final String EVENT_LOG_TAG = "event-log"; 5737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String EVENT_TAG = "event"; 587f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 5937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Attributes 609d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski private static final String PACKAGE_ATTR = "package"; 61ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki private static final String FLAGS_ATTR = "flags"; 629d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski private static final String CLASS_ATTR = "class"; 6337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive"; 647f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static final String COUNT_ATTR = "count"; 657f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static final String ACTIVE_ATTR = "active"; 663516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String LAST_EVENT_ATTR = "lastEvent"; 673516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String TYPE_ATTR = "type"; 68ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki private static final String SHORTCUT_ID_ATTR = "shortcutId"; 69bfc4bf5febe3d97d3f51206c9ead2f7d2b05e700Amith Yamasani private static final String STANDBY_BUCKET_ATTR = "standbyBucket"; 70bc813eb26e3027856114a26312e36e4bad86bd86Amith Yamasani private static final String APP_LAUNCH_COUNT_ATTR = "appLaunchCount"; 7137a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 7237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Time attributes stored as an offset of the beginTime. 7337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive"; 7437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static final String END_TIME_ATTR = "endTime"; 753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private static final String TIME_ATTR = "time"; 763516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 777f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut) 7853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li throws XmlPullParserException, IOException { 7937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final String pkg = parser.getAttributeValue(null, PACKAGE_ATTR); 8037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski if (pkg == null) { 8137a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present"); 823516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 8337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final UsageStats stats = statsOut.getOrCreateUsageStats(pkg); 8437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 8537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Apply the offset to the beginTime to find the absolute time. 8637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute( 8737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski parser, LAST_TIME_ACTIVE_ATTR); 883516800b611a79339a3c188332d13a26e9086b09Adam Lesinski stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR); 893516800b611a79339a3c188332d13a26e9086b09Adam Lesinski stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR); 90bc813eb26e3027856114a26312e36e4bad86bd86Amith Yamasani stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR, 0); 9153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li int eventCode; 9253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) { 9353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li final String tag = parser.getName(); 9453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (eventCode == XmlPullParser.END_TAG && tag.equals(PACKAGE_TAG)) { 9553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li break; 9653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 9753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (eventCode != XmlPullParser.START_TAG) { 9853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li continue; 9953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 10053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (tag.equals(CHOOSER_COUNT_TAG)) { 10153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li String action = XmlUtils.readStringAttribute(parser, NAME); 10253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li loadChooserCounts(parser, stats, action); 10353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 10453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 10553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 10653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li 1073378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn private static void loadCountAndTime(XmlPullParser parser, 1083378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn IntervalStats.EventTracker tracker) 109ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn throws IOException, XmlPullParserException { 1103378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn tracker.count = XmlUtils.readIntAttribute(parser, COUNT_ATTR, 0); 1113378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn tracker.duration = XmlUtils.readLongAttribute(parser, TIME_ATTR, 0); 112ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn XmlUtils.skipCurrentTag(parser); 113ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn } 114ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn 11553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static void loadChooserCounts( 11653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li XmlPullParser parser, UsageStats usageStats, String action) 11753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li throws XmlPullParserException, IOException { 11853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (action == null) { 11953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li return; 12053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 12153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (usageStats.mChooserCounts == null) { 12253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li usageStats.mChooserCounts = new ArrayMap<>(); 12353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 12453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (!usageStats.mChooserCounts.containsKey(action)) { 12553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li ArrayMap<String, Integer> counts = new ArrayMap<>(); 12653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li usageStats.mChooserCounts.put(action, counts); 12753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 12853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li 12953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li int eventCode; 13053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) { 13153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li final String tag = parser.getName(); 13253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (eventCode == XmlPullParser.END_TAG && tag.equals(CHOOSER_COUNT_TAG)) { 13353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li break; 13453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 13553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (eventCode != XmlPullParser.START_TAG) { 13653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li continue; 13753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 13853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (tag.equals(CATEGORY_TAG)) { 13953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li String category = XmlUtils.readStringAttribute(parser, NAME); 14053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li int count = XmlUtils.readIntAttribute(parser, COUNT); 14153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li usageStats.mChooserCounts.get(action).put(category, count); 14253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 14353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 1443516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1453516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1467f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static void loadConfigStats(XmlPullParser parser, IntervalStats statsOut) 1473516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws XmlPullParserException, IOException { 1487f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final Configuration config = new Configuration(); 1497f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski Configuration.readXmlAttrs(parser, config); 1507f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 15137a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config); 15237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 15337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Apply the offset to the beginTime to find the absolute time. 15437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski configStats.mLastTimeActive = statsOut.beginTime + XmlUtils.readLongAttribute( 15537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski parser, LAST_TIME_ACTIVE_ATTR); 15637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 1577f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski configStats.mTotalTimeActive = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR); 1587f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski configStats.mActivationCount = XmlUtils.readIntAttribute(parser, COUNT_ATTR); 1597f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (XmlUtils.readBooleanAttribute(parser, ACTIVE_ATTR)) { 1607f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski statsOut.activeConfiguration = configStats.mConfiguration; 1613516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1627f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 1647f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski private static void loadEvent(XmlPullParser parser, IntervalStats statsOut) 1657f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski throws XmlPullParserException, IOException { 16637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR); 1679d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski if (packageName == null) { 16837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present"); 1693516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 17037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR); 1717f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 17237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final UsageEvents.Event event = statsOut.buildEvent(packageName, className); 17337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 174ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki event.mFlags = XmlUtils.readIntAttribute(parser, FLAGS_ATTR, 0); 175ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki 17637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Apply the offset to the beginTime to find the absolute time of this event. 17737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR); 17837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 17937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR); 180ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki switch (event.mEventType) { 181ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki case UsageEvents.Event.CONFIGURATION_CHANGE: 182ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki event.mConfiguration = new Configuration(); 183ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki Configuration.readXmlAttrs(parser, event.mConfiguration); 184ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki break; 185ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki case UsageEvents.Event.SHORTCUT_INVOCATION: 186ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki final String id = XmlUtils.readStringAttribute(parser, SHORTCUT_ID_ATTR); 187ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki event.mShortcutId = (id != null) ? id.intern() : null; 188ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki break; 189bfc4bf5febe3d97d3f51206c9ead2f7d2b05e700Amith Yamasani case UsageEvents.Event.STANDBY_BUCKET_CHANGED: 190119be9a5fc4033eba570ec94b94862401ee84570Amith Yamasani event.mBucketAndReason = XmlUtils.readIntAttribute(parser, STANDBY_BUCKET_ATTR, 0); 191bfc4bf5febe3d97d3f51206c9ead2f7d2b05e700Amith Yamasani break; 1927f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 1937f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 1947f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (statsOut.events == null) { 19560aa35b756707a16d310c222a36edbcef9d56ed4Suprabh Shukla statsOut.events = new EventList(); 1967f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 19760aa35b756707a16d310c222a36edbcef9d56ed4Suprabh Shukla statsOut.events.insert(event); 1983516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 1993516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 20037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static void writeUsageStats(XmlSerializer xml, final IntervalStats stats, 20137a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final UsageStats usageStats) throws IOException { 2027f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski xml.startTag(null, PACKAGE_TAG); 20337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 20437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Write the time offset. 20537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, 20637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski usageStats.mLastTimeUsed - stats.beginTime); 20737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 20837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName); 20937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground); 21037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent); 211bc813eb26e3027856114a26312e36e4bad86bd86Amith Yamasani if (usageStats.mAppLaunchCount > 0) { 212bc813eb26e3027856114a26312e36e4bad86bd86Amith Yamasani XmlUtils.writeIntAttribute(xml, APP_LAUNCH_COUNT_ATTR, usageStats.mAppLaunchCount); 213bc813eb26e3027856114a26312e36e4bad86bd86Amith Yamasani } 21453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li writeChooserCounts(xml, usageStats); 2157f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski xml.endTag(null, PACKAGE_TAG); 2167f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 2177f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 218ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn private static void writeCountAndTime(XmlSerializer xml, String tag, int count, long time) 219ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn throws IOException { 220ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn xml.startTag(null, tag); 221ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn XmlUtils.writeIntAttribute(xml, COUNT_ATTR, count); 222ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn XmlUtils.writeLongAttribute(xml, TIME_ATTR, time); 223ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn xml.endTag(null, tag); 224ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn } 225ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn 22653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static void writeChooserCounts(XmlSerializer xml, final UsageStats usageStats) 22753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li throws IOException { 22853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (usageStats == null || usageStats.mChooserCounts == null || 22953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li usageStats.mChooserCounts.keySet().isEmpty()) { 23053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li return; 23153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 23253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li final int chooserCountSize = usageStats.mChooserCounts.size(); 23353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li for (int i = 0; i < chooserCountSize; i++) { 23453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li final String action = usageStats.mChooserCounts.keyAt(i); 23553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li final ArrayMap<String, Integer> counts = usageStats.mChooserCounts.valueAt(i); 23653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (action == null || counts == null || counts.isEmpty()) { 23753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li continue; 23853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 23953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li xml.startTag(null, CHOOSER_COUNT_TAG); 24053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li XmlUtils.writeStringAttribute(xml, NAME, action); 24153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li writeCountsForAction(xml, counts); 24253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li xml.endTag(null, CHOOSER_COUNT_TAG); 24353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 24453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 24553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li 24653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li private static void writeCountsForAction(XmlSerializer xml, ArrayMap<String, Integer> counts) 24753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li throws IOException { 24853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li final int countsSize = counts.size(); 24953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li for (int i = 0; i < countsSize; i++) { 25053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li String key = counts.keyAt(i); 25153b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li int count = counts.valueAt(i); 25253b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li if (count > 0) { 25353b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li xml.startTag(null, CATEGORY_TAG); 25453b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li XmlUtils.writeStringAttribute(xml, NAME, key); 25553b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li XmlUtils.writeIntAttribute(xml, COUNT, count); 25653b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li xml.endTag(null, CATEGORY_TAG); 25753b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 25853b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 25953b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li } 26053b4314ad9b43b1890cbd765b896ccb0f005fdebKang Li 26137a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static void writeConfigStats(XmlSerializer xml, final IntervalStats stats, 26237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final ConfigurationStats configStats, boolean isActive) throws IOException { 26337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.startTag(null, CONFIG_TAG); 26437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 26537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Write the time offset. 26637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, 26737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski configStats.mLastTimeActive - stats.beginTime); 26837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 26937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, configStats.mTotalTimeActive); 27037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeIntAttribute(xml, COUNT_ATTR, configStats.mActivationCount); 2717f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (isActive) { 2727f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski XmlUtils.writeBooleanAttribute(xml, ACTIVE_ATTR, true); 2737f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 2747f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 2757f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski // Now write the attributes representing the configuration object. 27637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski Configuration.writeXmlAttrs(xml, configStats.mConfiguration); 2777f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 27837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.endTag(null, CONFIG_TAG); 2793516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 2803516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 28137a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski private static void writeEvent(XmlSerializer xml, final IntervalStats stats, 28237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final UsageEvents.Event event) throws IOException { 28337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.startTag(null, EVENT_TAG); 28437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 28537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski // Store the time offset. 28637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp - stats.beginTime); 28737a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 2887f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, event.mPackage); 2899d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski if (event.mClass != null) { 2907f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass); 2917f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 292ad623015a119efe9b63f594af9c4703f40a0c27bMakoto Onuki XmlUtils.writeIntAttribute(xml, FLAGS_ATTR, event.mFlags); 2937f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType); 2947f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 295ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki switch (event.mEventType) { 296ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki case UsageEvents.Event.CONFIGURATION_CHANGE: 297ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki if (event.mConfiguration != null) { 298ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki Configuration.writeXmlAttrs(xml, event.mConfiguration); 299ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } 300ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki break; 301ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki case UsageEvents.Event.SHORTCUT_INVOCATION: 302ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki if (event.mShortcutId != null) { 303ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki XmlUtils.writeStringAttribute(xml, SHORTCUT_ID_ATTR, event.mShortcutId); 304ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } 305ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki break; 306bfc4bf5febe3d97d3f51206c9ead2f7d2b05e700Amith Yamasani case UsageEvents.Event.STANDBY_BUCKET_CHANGED: 307119be9a5fc4033eba570ec94b94862401ee84570Amith Yamasani if (event.mBucketAndReason != 0) { 308119be9a5fc4033eba570ec94b94862401ee84570Amith Yamasani XmlUtils.writeIntAttribute(xml, STANDBY_BUCKET_ATTR, event.mBucketAndReason); 309bfc4bf5febe3d97d3f51206c9ead2f7d2b05e700Amith Yamasani } 3109d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski } 3117f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 31237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.endTag(null, EVENT_TAG); 3133516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 3143516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 3153516800b611a79339a3c188332d13a26e9086b09Adam Lesinski /** 3163516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Reads from the {@link XmlPullParser}, assuming that it is already on the 3173516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * <code><usagestats></code> tag. 3183516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 3193516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param parser The parser from which to read events. 3203516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param statsOut The stats object to populate with the data from the XML file. 3213516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 3223516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public static void read(XmlPullParser parser, IntervalStats statsOut) 3233516800b611a79339a3c188332d13a26e9086b09Adam Lesinski throws XmlPullParserException, IOException { 32437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski statsOut.packageStats.clear(); 3257f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski statsOut.configurations.clear(); 3267f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski statsOut.activeConfiguration = null; 3273516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 3283516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (statsOut.events != null) { 3293516800b611a79339a3c188332d13a26e9086b09Adam Lesinski statsOut.events.clear(); 3303516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 3313516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 332690f78adf1737b2356d341b46f21a4e2d5df58ebEdward Cunningham statsOut.endTime = statsOut.beginTime + XmlUtils.readLongAttribute(parser, END_TIME_ATTR); 3333516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 3347f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski int eventCode; 3357f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski int outerDepth = parser.getDepth(); 3367f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT 3377f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski && (eventCode != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 3387f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (eventCode != XmlPullParser.START_TAG) { 3397f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski continue; 3407f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 3417f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 3427f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final String tag = parser.getName(); 3437f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski switch (tag) { 3443378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn case INTERACTIVE_TAG: 3453378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn loadCountAndTime(parser, statsOut.interactiveTracker); 3463378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn break; 3473378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn 3483378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn case NON_INTERACTIVE_TAG: 3493378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn loadCountAndTime(parser, statsOut.nonInteractiveTracker); 3503378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn break; 3513378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn 3523378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn case KEYGUARD_SHOWN_TAG: 3533378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn loadCountAndTime(parser, statsOut.keyguardShownTracker); 3543378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn break; 3553378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn 3563378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn case KEYGUARD_HIDDEN_TAG: 3573378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn loadCountAndTime(parser, statsOut.keyguardHiddenTracker); 3583378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn break; 359ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn 3607f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski case PACKAGE_TAG: 3617f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski loadUsageStats(parser, statsOut); 3627f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski break; 3633516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 36437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski case CONFIG_TAG: 3657f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski loadConfigStats(parser, statsOut); 3667f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski break; 3677f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 36837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski case EVENT_TAG: 3697f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski loadEvent(parser, statsOut); 3707f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski break; 3713516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 3723516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 3733516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 3743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 3753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski /** 37637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski * Writes the stats object to an XML file. The {@link XmlSerializer} 3773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * has already written the <code><usagestats></code> tag, but attributes may still 3783516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * be added. 3793516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * 38037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski * @param xml The serializer to which to write the packageStats data. 3813516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * @param stats The stats object to write to the XML file. 3823516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 38337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski public static void write(XmlSerializer xml, IntervalStats stats) throws IOException { 38437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime); 3853516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 3863378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveTracker.count, 3873378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn stats.interactiveTracker.duration); 3883378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn writeCountAndTime(xml, NON_INTERACTIVE_TAG, stats.nonInteractiveTracker.count, 3893378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn stats.nonInteractiveTracker.duration); 3903378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn writeCountAndTime(xml, KEYGUARD_SHOWN_TAG, stats.keyguardShownTracker.count, 3913378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn stats.keyguardShownTracker.duration); 3923378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn writeCountAndTime(xml, KEYGUARD_HIDDEN_TAG, stats.keyguardHiddenTracker.count, 3933378aa9f88101d77bc52c1a00b257c752bd8c193Dianne Hackborn stats.keyguardHiddenTracker.duration); 394ced54398cc0dfd2f782153560c2ffd0eb8743045Dianne Hackborn 39537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.startTag(null, PACKAGES_TAG); 39637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski final int statsCount = stats.packageStats.size(); 3973516800b611a79339a3c188332d13a26e9086b09Adam Lesinski for (int i = 0; i < statsCount; i++) { 39837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski writeUsageStats(xml, stats, stats.packageStats.valueAt(i)); 3993516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 40037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.endTag(null, PACKAGES_TAG); 4013516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 40237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.startTag(null, CONFIGURATIONS_TAG); 4037f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final int configCount = stats.configurations.size(); 4047f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski for (int i = 0; i < configCount; i++) { 4057f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i)); 40637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski writeConfigStats(xml, stats, stats.configurations.valueAt(i), active); 4077f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 40837a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.endTag(null, CONFIGURATIONS_TAG); 4097f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 41037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.startTag(null, EVENT_LOG_TAG); 4117f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final int eventCount = stats.events != null ? stats.events.size() : 0; 4127f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski for (int i = 0; i < eventCount; i++) { 41360aa35b756707a16d310c222a36edbcef9d56ed4Suprabh Shukla writeEvent(xml, stats, stats.events.get(i)); 4143516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 41537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski xml.endTag(null, EVENT_LOG_TAG); 4163516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 4173516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 4183516800b611a79339a3c188332d13a26e9086b09Adam Lesinski private UsageStatsXmlV1() { 4193516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 4203516800b611a79339a3c188332d13a26e9086b09Adam Lesinski} 421