19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006-2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server.am; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackbornimport android.app.AppGlobals; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 22904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackbornimport android.content.pm.IPackageManager; 23c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport android.content.pm.PackageInfo; 243abd75ba3a981850cac43a401d0014a836559cb0Kenny Rootimport android.content.pm.PackageManager; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 278bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackbornimport android.os.FileUtils; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 30904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackbornimport android.os.RemoteException; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 33904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackbornimport android.util.ArrayMap; 3439606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile; 358a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 36c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport android.util.Xml; 37c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 38c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport com.android.internal.app.IUsageStats; 39c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport com.android.internal.content.PackageMonitor; 40c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport com.android.internal.os.PkgUsageStats; 41c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport com.android.internal.util.FastXmlSerializer; 42c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 43c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport org.xmlpull.v1.XmlPullParser; 44c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport org.xmlpull.v1.XmlPullParserException; 45c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophyimport org.xmlpull.v1.XmlSerializer; 46c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 589fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackbornimport java.util.HashSet; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 626447ca30b8e41c22c7214f201120327057e356dcDianne Hackbornimport java.util.TimeZone; 63389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrickimport java.util.concurrent.atomic.AtomicBoolean; 64389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrickimport java.util.concurrent.atomic.AtomicInteger; 65389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrickimport java.util.concurrent.atomic.AtomicLong; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This service collects the statistics associated with usage 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of various components, like when a particular package is launched or 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * paused and aggregates events like number of time a component is launched 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * total duration of a component launch. 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class UsageStatsService extends IUsageStats.Stub { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String SERVICE_NAME = "usagestats"; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean localLOGV = false; 76cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn private static final boolean REPORT_UNEXPECTED = false; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "UsageStats"; 786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Current on-disk Parcel version 802286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn private static final int VERSION = 1008; 816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 82760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private static final int CHECKIN_VERSION = 4; 836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final String FILE_PREFIX = "usage-"; 85c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 86c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private static final String FILE_HISTORY = FILE_PREFIX + "history.xml"; 87c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms 896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final int MAX_NUM_FILES = 5; 916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 92f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private static final int NUM_LAUNCH_TIME_BINS = 10; 93f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private static final int[] LAUNCH_TIME_BINS = { 94f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000 95f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn }; 966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static IUsageStats sService; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // structure used to maintain statistics since the last checkin. 100904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn final private ArrayMap<String, PkgUsageStatsExtended> mStats; 101c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 102c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy // Maintains the last time any component was resumed, for all time. 103904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes; 104c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 105c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy // To remove last-resume time stats when a pacakge is removed. 106c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private PackageMonitor mPackageMonitor; 107c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Lock to update package stats. Methods suffixed by SLOCK should invoked with 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this lock held 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mStatsLock; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Lock to write to file. Methods suffixed by FLOCK should invoked with 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this lock held. 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mFileLock; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks 115760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private String mLastResumedPkg; 116760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private String mLastResumedComp; 117760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private boolean mIsResumed; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private File mFile; 119c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private AtomicFile mHistoryFile; 1206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private String mFileLeaf; 1216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private File mDir; 122389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick 123389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick private Calendar mCal; // guarded by itself 124389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick 125389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick private final AtomicInteger mLastWriteDay = new AtomicInteger(-1); 126389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0); 127389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false); 1286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn static class TimeStats { 130760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn int count; 131f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn int[] times = new int[NUM_LAUNCH_TIME_BINS]; 1326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 133f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats() { 134f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 1356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 136760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void incCount() { 137760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn count++; 138760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 139760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 1406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn void add(int val) { 141f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] bins = LAUNCH_TIME_BINS; 142f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { 143f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (val < bins[i]) { 144f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times[i]++; 145f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn return; 1466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 148f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times[NUM_LAUNCH_TIME_BINS-1]++; 1496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 151f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats(Parcel in) { 152760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn count = in.readInt(); 153f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] localTimes = times; 154f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 155f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn localTimes[i] = in.readInt(); 1566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 157f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 158f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 159f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn void writeToParcel(Parcel out) { 160760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn out.writeInt(count); 161f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] localTimes = times; 162f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 163f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn out.writeInt(localTimes[i]); 1646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class PkgUsageStatsExtended { 1692286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final ArrayMap<String, TimeStats> mLaunchTimes 1702286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn = new ArrayMap<String, TimeStats>(); 1712286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final ArrayMap<String, TimeStats> mFullyDrawnTimes 1722286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn = new ArrayMap<String, TimeStats>(); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mLaunchCount; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mUsageTime; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mPausedTime; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mResumedTime; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended() { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchCount = 0; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime = 0; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1826447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended(Parcel in) { 1846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchCount = in.readInt(); 1856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mUsageTime = in.readLong(); 1868a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount 1876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn + ", Usage time:" + mUsageTime); 1886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1892286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int numLaunchTimeStats = in.readInt(); 1902286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (localLOGV) Slog.v(TAG, "Reading launch times: " + numLaunchTimeStats); 1912286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mLaunchTimes.ensureCapacity(numLaunchTimeStats); 1922286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<numLaunchTimeStats; i++) { 1936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String comp = in.readString(); 1948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Component: " + comp); 195f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats times = new TimeStats(in); 196f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn mLaunchTimes.put(comp, times); 1976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1982286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 1992286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int numFullyDrawnTimeStats = in.readInt(); 2002286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (localLOGV) Slog.v(TAG, "Reading fully drawn times: " + numFullyDrawnTimeStats); 2012286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mFullyDrawnTimes.ensureCapacity(numFullyDrawnTimeStats); 2022286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<numFullyDrawnTimeStats; i++) { 2032286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn String comp = in.readString(); 2042286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (localLOGV) Slog.v(TAG, "Component: " + comp); 2052286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn TimeStats times = new TimeStats(in); 2062286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mFullyDrawnTimes.put(comp, times); 2072286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 2086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2099fc033083267d0c7f01e083400721b6cddb3a398Mark Brophy 2109fc033083267d0c7f01e083400721b6cddb3a398Mark Brophy void updateResume(String comp, boolean launched) { 211760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (launched) { 212760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLaunchCount ++; 213760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResumedTime = SystemClock.elapsedRealtime(); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void updatePause() { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPausedTime = SystemClock.elapsedRealtime(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime += (mPausedTime - mResumedTime); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 222760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void addLaunchCount(String comp) { 223760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn TimeStats times = mLaunchTimes.get(comp); 224760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (times == null) { 225760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn times = new TimeStats(); 226760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLaunchTimes.put(comp, times); 227760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 228760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn times.incCount(); 229760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 230760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 2316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn void addLaunchTime(String comp, int millis) { 2326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = mLaunchTimes.get(comp); 2336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (times == null) { 2346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn times = new TimeStats(); 2356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchTimes.put(comp, times); 2366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn times.add(millis); 2386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2392286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 2402286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn void addFullyDrawnTime(String comp, int millis) { 2412286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn TimeStats times = mFullyDrawnTimes.get(comp); 2422286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (times == null) { 2432286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn times = new TimeStats(); 2442286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mFullyDrawnTimes.put(comp, times); 2452286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 2462286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn times.add(millis); 2472286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 2482286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 249f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn void writeToParcel(Parcel out) { 2506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(mLaunchCount); 2516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeLong(mUsageTime); 2522286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int numLaunchTimeStats = mLaunchTimes.size(); 2532286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn out.writeInt(numLaunchTimeStats); 2542286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<numLaunchTimeStats; i++) { 2552286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn out.writeString(mLaunchTimes.keyAt(i)); 2562286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mLaunchTimes.valueAt(i).writeToParcel(out); 2572286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 2582286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int numFullyDrawnTimeStats = mFullyDrawnTimes.size(); 2592286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn out.writeInt(numFullyDrawnTimeStats); 2602286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<numFullyDrawnTimeStats; i++) { 2612286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn out.writeString(mFullyDrawnTimes.keyAt(i)); 2622286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mFullyDrawnTimes.valueAt(i).writeToParcel(out); 2636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void clear() { 2676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchTimes.clear(); 2682286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn mFullyDrawnTimes.clear(); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchCount = 0; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime = 0; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn UsageStatsService(String dir) { 275904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn mStats = new ArrayMap<String, PkgUsageStatsExtended>(); 276904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn mLastResumeTimes = new ArrayMap<String, ArrayMap<String, Long>>(); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStatsLock = new Object(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFileLock = new Object(); 2796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mDir = new File(dir); 2806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); 2816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2826447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mDir.mkdir(); 2836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Remove any old usage files from previous versions. 2856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File parentDir = mDir.getParentFile(); 2866447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String fList[] = parentDir.list(); 2876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (fList != null) { 2886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String prefix = mDir.getName() + "."; 2896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int i = fList.length; 2906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (i > 0) { 2916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn i--; 2926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (fList[i].startsWith(prefix)) { 2938a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "Deleting old usage file: " + fList[i]); 2946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (new File(parentDir, fList[i])).delete(); 2956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update current stats which are binned by date 3006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFileLeaf = getCurrentDateStr(FILE_PREFIX); 3016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile = new File(mDir, mFileLeaf); 302c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy mHistoryFile = new AtomicFile(new File(mDir, FILE_HISTORY)); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readStatsFromFile(); 304c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy readHistoryStatsFromFile(); 305389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick mLastWriteElapsedTime.set(SystemClock.elapsedRealtime()); 3066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // mCal was set by getCurrentDateStr(), want to use that same time. 307389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick mLastWriteDay.set(mCal.get(Calendar.DAY_OF_YEAR)); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility method to convert date into string. 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getCurrentDateStr(String prefix) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 315389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick synchronized (mCal) { 316389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick mCal.setTimeInMillis(System.currentTimeMillis()); 317389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick if (prefix != null) { 318389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick sb.append(prefix); 319389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 320389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick sb.append(mCal.get(Calendar.YEAR)); 321389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1; 322389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick if (mm < 10) { 323389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick sb.append("0"); 324389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 325389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick sb.append(mm); 326389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick int dd = mCal.get(Calendar.DAY_OF_MONTH); 327389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick if (dd < 10) { 328389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick sb.append("0"); 329389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 330389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick sb.append(dd); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Parcel getParcelForFile(File file) throws IOException { 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileInputStream stream = new FileInputStream(file); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] raw = readFully(stream); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = Parcel.obtain(); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.unmarshall(raw, 0, raw.length); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.setDataPosition(0); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stream.close(); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return in; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readStatsFromFile() { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File newFile = mFile; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newFile.exists()) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readStatsFLOCK(newFile); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for file limit before creating a new file 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkFileLimitFLOCK(); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFile.createNewFile(); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 3578a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG,"Error : " + e + " reading data from file:" + newFile); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readStatsFLOCK(File file) throws IOException { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = getParcelForFile(file); 3646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int vers = in.readInt(); 3656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (vers != VERSION) { 3668a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Usage stats version changed; dropping"); 3676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 3686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int N = in.readInt(); 3706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (N > 0) { 3716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn N--; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName = in.readString(); 3736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pkgName == null) { 3746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn break; 3756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Reading package #" + N + ": " + pkgName); 3776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.put(pkgName, pus); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 384c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private void readHistoryStatsFromFile() { 385c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy synchronized (mFileLock) { 386c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (mHistoryFile.getBaseFile().exists()) { 387c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy readHistoryStatsFLOCK(mHistoryFile); 388c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 389c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 390c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 391c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 392c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private void readHistoryStatsFLOCK(AtomicFile file) { 393c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy FileInputStream fis = null; 394c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy try { 395c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy fis = mHistoryFile.openRead(); 396c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy XmlPullParser parser = Xml.newPullParser(); 397c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy parser.setInput(fis, null); 398c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy int eventType = parser.getEventType(); 399c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy while (eventType != XmlPullParser.START_TAG) { 400c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy eventType = parser.next(); 401c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 402c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy String tagName = parser.getName(); 403c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if ("usage-history".equals(tagName)) { 404c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy String pkg = null; 405c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy do { 406c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy eventType = parser.next(); 407c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (eventType == XmlPullParser.START_TAG) { 408c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy tagName = parser.getName(); 409c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy int depth = parser.getDepth(); 410c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if ("pkg".equals(tagName) && depth == 2) { 411c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy pkg = parser.getAttributeValue(null, "name"); 412c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } else if ("comp".equals(tagName) && depth == 3 && pkg != null) { 413c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy String comp = parser.getAttributeValue(null, "name"); 414c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy String lastResumeTimeStr = parser.getAttributeValue(null, "lrt"); 415c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (comp != null && lastResumeTimeStr != null) { 416c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy try { 417c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy long lastResumeTime = Long.parseLong(lastResumeTimeStr); 418c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy synchronized (mStatsLock) { 419904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn ArrayMap<String, Long> lrt = mLastResumeTimes.get(pkg); 420c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (lrt == null) { 421904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn lrt = new ArrayMap<String, Long>(); 422c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy mLastResumeTimes.put(pkg, lrt); 423c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 424c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy lrt.put(comp, lastResumeTime); 425c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 426c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } catch (NumberFormatException e) { 427c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 428c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 429c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 430c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } else if (eventType == XmlPullParser.END_TAG) { 431c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if ("pkg".equals(parser.getName())) { 432c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy pkg = null; 433c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 434c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 435c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } while (eventType != XmlPullParser.END_DOCUMENT); 436c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 437c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } catch (XmlPullParserException e) { 438c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy Slog.w(TAG,"Error reading history stats: " + e); 439c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } catch (IOException e) { 440c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy Slog.w(TAG,"Error reading history stats: " + e); 441c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } finally { 442c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (fis != null) { 443c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy try { 444c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy fis.close(); 445c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } catch (IOException e) { 446c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 447c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 448c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 449c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 450c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<String> getUsageStatsFileListFLOCK() { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check if there are too many files in the system and delete older files 4536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String fList[] = mDir.list(); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fList == null) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> fileList = new ArrayList<String>(); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String file : fList) { 4596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!file.startsWith(FILE_PREFIX)) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (file.endsWith(".bak")) { 4636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (new File(mDir, file)).delete(); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fileList.add(file); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fileList; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkFileLimitFLOCK() { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get all usage stats output files 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> fileList = getUsageStatsFileListFLOCK(); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileList == null) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strange but we dont have to delete any thing 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fileList.size(); 4796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (count <= MAX_NUM_FILES) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sort files 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collections.sort(fileList); 4846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn count -= MAX_NUM_FILES; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete older files 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String fileName = fileList.get(i); 4886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File file = new File(mDir, fileName); 4898a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "Deleting usage file : " + fileName); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project file.delete(); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 493389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick 494389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick /** 495389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * Conditionally start up a disk write if it's been awhile, or the 496389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * day has rolled over. 497389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * 498389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * This is called indirectly from user-facing actions (when 499389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * 'force' is false) so it tries to be quick, without writing to 500389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * disk directly or acquiring heavy locks. 501389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * 502389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * @params force do an unconditional, synchronous stats flush 503389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick * to disk on the current thread. 504c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy * @params forceWriteHistoryStats Force writing of historical stats. 505389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick */ 506c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private void writeStatsToFile(final boolean force, final boolean forceWriteHistoryStats) { 507389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick int curDay; 508389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick synchronized (mCal) { 5096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal.setTimeInMillis(System.currentTimeMillis()); 510389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick curDay = mCal.get(Calendar.DAY_OF_YEAR); 511389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 512389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick final boolean dayChanged = curDay != mLastWriteDay.get(); 513389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick 514389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick // Determine if the day changed... note that this will be wrong 515389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick // if the year has changed but we are in the same day of year... 516389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick // we can probably live with this. 517389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick final long currElapsedTime = SystemClock.elapsedRealtime(); 518389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick 519389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick // Fast common path, without taking the often-contentious 520389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick // mFileLock. 521389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick if (!force) { 522389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick if (!dayChanged && 523389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick (currElapsedTime - mLastWriteElapsedTime.get()) < FILE_WRITE_INTERVAL) { 524389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick // wait till the next update 525389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick return; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 527389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick if (mUnforcedDiskWriteRunning.compareAndSet(false, true)) { 528389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick new Thread("UsageStatsService_DiskWriter") { 529389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick public void run() { 530389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick try { 531cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn if (localLOGV) Slog.d(TAG, "Disk writer thread starting."); 532c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy writeStatsToFile(true, false); 533389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } finally { 534389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick mUnforcedDiskWriteRunning.set(false); 535cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn if (localLOGV) Slog.d(TAG, "Disk writer thread ending."); 536389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 537389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 538389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick }.start(); 539389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 540389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick return; 541389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick } 542389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick 543389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick synchronized (mFileLock) { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the most recent file 5456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFileLeaf = getCurrentDateStr(FILE_PREFIX); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Copy current file to back up 547be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu File backupFile = null; 548be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu if (mFile != null && mFile.exists()) { 549be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu backupFile = new File(mFile.getPath() + ".bak"); 5501afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn if (!backupFile.exists()) { 5511afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn if (!mFile.renameTo(backupFile)) { 5521afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn Slog.w(TAG, "Failed to persist new stats"); 5531afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn return; 5541afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn } 5551afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn } else { 5561afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn mFile.delete(); 557be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu } 5588550f255232eb4e4852466c5297fdc125887f5afSuchi Amalapurapu } 559be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write mStats to file 562389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick writeStatsFLOCK(mFile); 563389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick mLastWriteElapsedTime.set(currElapsedTime); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dayChanged) { 565389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick mLastWriteDay.set(curDay); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clear stats 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStats) { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.clear(); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile = new File(mDir, mFileLeaf); 5716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn checkFileLimitFLOCK(); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 573c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 574c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (dayChanged || forceWriteHistoryStats) { 575c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy // Write history stats daily, or when forced (due to shutdown). 576c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy writeHistoryStatsFLOCK(mHistoryFile); 577c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 578c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete the backup file 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (backupFile != null) { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project backupFile.delete(); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 5848a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Failed writing stats to file:" + mFile); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (backupFile != null) { 5866447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile.delete(); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project backupFile.renameTo(mFile); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 591cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn if (localLOGV) Slog.d(TAG, "Dumped usage stats."); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 594389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick private void writeStatsFLOCK(File file) throws IOException { 595389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick FileOutputStream stream = new FileOutputStream(file); 5966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn try { 5976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn Parcel out = Parcel.obtain(); 598f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn writeStatsToParcelFLOCK(out); 5996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.write(out.marshall()); 6006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.recycle(); 6016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.flush(); 6026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } finally { 6038bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn FileUtils.sync(stream); 6046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.close(); 6056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 608f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private void writeStatsToParcelFLOCK(Parcel out) { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 6106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(VERSION); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> keys = mStats.keySet(); 6126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(keys.size()); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String key : keys) { 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(key); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeString(key); 616f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn pus.writeToParcel(out); 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 621c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy /** Filter out stats for any packages which aren't present anymore. */ 622c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private void filterHistoryStats() { 623c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy synchronized (mStatsLock) { 624904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn IPackageManager pm = AppGlobals.getPackageManager(); 625904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn for (int i=0; i<mLastResumeTimes.size(); i++) { 626904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn String pkg = mLastResumeTimes.keyAt(i); 627904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn try { 628904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn if (pm.getPackageUid(pkg, 0) < 0) { 629904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn mLastResumeTimes.removeAt(i); 630904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn i--; 631904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn } 632904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn } catch (RemoteException e) { 633c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 634c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 635c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 636c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 637c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 638c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy private void writeHistoryStatsFLOCK(AtomicFile historyFile) { 639c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy FileOutputStream fos = null; 640c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy try { 641c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy fos = historyFile.startWrite(); 642c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy XmlSerializer out = new FastXmlSerializer(); 643c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.setOutput(fos, "utf-8"); 644c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.startDocument(null, true); 645c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 646c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.startTag(null, "usage-history"); 647c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy synchronized (mStatsLock) { 648904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn for (int i=0; i<mLastResumeTimes.size(); i++) { 649c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.startTag(null, "pkg"); 650904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn out.attribute(null, "name", mLastResumeTimes.keyAt(i)); 651904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn ArrayMap<String, Long> comp = mLastResumeTimes.valueAt(i); 652904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn for (int j=0; j<comp.size(); j++) { 653c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.startTag(null, "comp"); 654904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn out.attribute(null, "name", comp.keyAt(j)); 655904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn out.attribute(null, "lrt", comp.valueAt(j).toString()); 656c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.endTag(null, "comp"); 657c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 658c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.endTag(null, "pkg"); 659c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 660c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 661c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.endTag(null, "usage-history"); 662c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy out.endDocument(); 663c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 664c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy historyFile.finishWrite(fos); 665c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } catch (IOException e) { 666c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy Slog.w(TAG,"Error writing history stats" + e); 667c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (fos != null) { 668c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy historyFile.failWrite(fos); 669c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 670c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 671c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 672c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void publish(Context context) { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ServiceManager.addService(SERVICE_NAME, asBinder()); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 677c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 678c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy /** 679c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy * Start watching packages to remove stats when a package is uninstalled. 680c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy * May only be called when the package manager is ready. 681c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy */ 682c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy public void monitorPackages() { 683c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy mPackageMonitor = new PackageMonitor() { 684c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy @Override 685c72fc674a33b8d17585764d09d3bb6c77d7d947eDianne Hackborn public void onPackageRemovedAllUsers(String packageName, int uid) { 686c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy synchronized (mStatsLock) { 687c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy mLastResumeTimes.remove(packageName); 688c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 689c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 690c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy }; 691d0d7503fd3e941113094532f28986f49b11b5fdbDianne Hackborn mPackageMonitor.register(mContext, null, true); 692c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy filterHistoryStats(); 693c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 694c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 69555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void shutdown() { 696c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (mPackageMonitor != null) { 697c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy mPackageMonitor.unregister(); 698c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 699cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn Slog.i(TAG, "Writing usage stats before shutdown..."); 700c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy writeStatsToFile(true, true); 70155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 702c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static IUsageStats getService() { 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sService != null) { 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sService; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder b = ServiceManager.getService(SERVICE_NAME); 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sService = asInterface(b); 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sService; 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void noteResumeComponent(ComponentName componentName) { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enforceCallingPermission(); 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 716760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if ((componentName == null) || 717760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 718760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 719760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 720760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 721760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn final boolean samePackage = pkgName.equals(mLastResumedPkg); 722760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (mIsResumed) { 723760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (mLastResumedPkg != null) { 724760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // We last resumed some other package... just pause it now 725760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // to recover. 726cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn if (REPORT_UNEXPECTED) Slog.i(TAG, "Unexpected resume of " + pkgName 727760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + " while already resumed in " + mLastResumedPkg); 728760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg); 729760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (pus != null) { 730760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.updatePause(); 731760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 732760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 733760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 734760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 735760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn final boolean sameComp = samePackage 736760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn && componentName.getClassName().equals(mLastResumedComp); 737760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 738760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mIsResumed = true; 739760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLastResumedPkg = pkgName; 740760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLastResumedComp = componentName.getClassName(); 741760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 7428a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.i(TAG, "started component:" + pkgName); 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pus = new PkgUsageStatsExtended(); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.put(pkgName, pus); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489fc033083267d0c7f01e083400721b6cddb3a398Mark Brophy pus.updateResume(mLastResumedComp, !samePackage); 749760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (!sameComp) { 750760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.addLaunchCount(mLastResumedComp); 751760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 752c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 753904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn ArrayMap<String, Long> componentResumeTimes = mLastResumeTimes.get(pkgName); 754c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (componentResumeTimes == null) { 755904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn componentResumeTimes = new ArrayMap<String, Long>(); 756c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy mLastResumeTimes.put(pkgName, componentResumeTimes); 757c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 758c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy componentResumeTimes.put(mLastResumedComp, System.currentTimeMillis()); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notePauseComponent(ComponentName componentName) { 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enforceCallingPermission(); 7646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 766760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn String pkgName; 767760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if ((componentName == null) || 768760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 769760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 770760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 771760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (!mIsResumed) { 772cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn if (REPORT_UNEXPECTED) Slog.i(TAG, "Something wrong here, didn't expect " 773760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + pkgName + " to be paused"); 774760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 775760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 776760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mIsResumed = false; 777760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 7788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.i(TAG, "paused component:"+pkgName); 779760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Weird some error here 7838a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "No package stats for pkg:"+pkgName); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pus.updatePause(); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 788760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 789760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // Persist current data to file if needed. 790c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy writeStatsToFile(false, false); 7916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn public void noteLaunchTime(ComponentName componentName, int millis) { 7946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn enforceCallingPermission(); 7956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String pkgName; 7966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if ((componentName == null) || 7976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 7986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 7996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 8006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 8016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Persist current data to file if needed. 802c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy writeStatsToFile(false, false); 8036447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 8046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn synchronized (mStatsLock) { 8056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = mStats.get(pkgName); 8066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pus != null) { 8076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pus.addLaunchTime(componentName.getClassName(), millis); 8086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 8096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8122286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn public void noteFullyDrawnTime(ComponentName componentName, int millis) { 8132286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn enforceCallingPermission(); 8142286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn String pkgName; 8152286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if ((componentName == null) || 8162286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 8172286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn return; 8182286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 8192286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 8202286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn // Persist current data to file if needed. 8212286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn writeStatsToFile(false, false); 8222286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 8232286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn synchronized (mStatsLock) { 8242286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn PkgUsageStatsExtended pus = mStats.get(pkgName); 8252286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (pus != null) { 8262286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn pus.addFullyDrawnTime(componentName.getClassName(), millis); 8272286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 8282286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 8292286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 8302286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void enforceCallingPermission() { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Binder.getCallingPid() == Process.myPid()) { 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.getCallingPid(), Binder.getCallingUid(), null); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PkgUsageStats getPkgUsageStats(ComponentName componentName) { 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.PACKAGE_USAGE_STATS, null); 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((componentName == null) || 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((pkgName = componentName.getPackageName()) == null)) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 849c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy Map<String, Long> lastResumeTimes = mLastResumeTimes.get(pkgName); 850c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (pus == null && lastResumeTimes == null) { 851c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy return null; 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 853c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy int launchCount = pus != null ? pus.mLaunchCount : 0; 854c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy long usageTime = pus != null ? pus.mUsageTime : 0; 855c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy return new PkgUsageStats(pkgName, launchCount, usageTime, lastResumeTimes); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PkgUsageStats[] getAllPkgUsageStats() { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.PACKAGE_USAGE_STATS, null); 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 863c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy int size = mLastResumeTimes.size(); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (size <= 0) { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStats retArr[] = new PkgUsageStats[size]; 868904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn for (int i=0; i<size; i++) { 869904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn String pkg = mLastResumeTimes.keyAt(i); 870c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy long usageTime = 0; 871c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy int launchCount = 0; 872c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy 873c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy PkgUsageStatsExtended pus = mStats.get(pkg); 874c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy if (pus != null) { 875c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy usageTime = pus.mUsageTime; 876c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy launchCount = pus.mLaunchCount; 877c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy } 878904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn retArr[i] = new PkgUsageStats(pkg, launchCount, usageTime, 879904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn mLastResumeTimes.valueAt(i)); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retArr; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static byte[] readFully(FileInputStream stream) throws java.io.IOException { 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pos = 0; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int avail = stream.available(); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] data = new byte[avail]; 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amt = stream.read(data, pos, data.length-pos); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amt <= 0) { 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return data; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos += amt; 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project avail = stream.available(); 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (avail > data.length-pos) { 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] newData = new byte[pos+avail]; 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(data, 0, newData, 0, pos); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data = newData; 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, 9059fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn boolean deleteAfterPrint, HashSet<String> packages) { 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project List<String> fileList = getUsageStatsFileListFLOCK(); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileList == null) { 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collections.sort(fileList); 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String file : fileList) { 9126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) { 9136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // In this mode we don't print the current day's stats, since 9146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // they are incomplete. 9156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn continue; 9166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 9176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File dFile = new File(mDir, file); 9186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String dateStr = file.substring(FILE_PREFIX.length()); 919904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn if (dateStr.length() > 0 && (dateStr.charAt(0) <= '0' || dateStr.charAt(0) >= '9')) { 920904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn // If the remainder does not start with a number, it is not a date, 921904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn // so we should ignore it for purposes here. 922904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn continue; 923904a857d5a319e32d1df065b38e3191324b35b0fDianne Hackborn } 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = getParcelForFile(dFile); 9269fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput, 9279fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn packages); 9286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (deleteAfterPrint) { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete old file after collecting info only for checkin requests 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dFile.delete(); 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (FileNotFoundException e) { 9338a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file); 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 9368a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file); 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, 9429fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn String date, boolean isCompactOutput, HashSet<String> packages) { 9436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn StringBuilder sb = new StringBuilder(512); 9446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (isCompactOutput) { 9456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("D:"); 9466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(CHECKIN_VERSION); 9476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(','); 9486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } else { 9496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("Date: "); 9506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 9516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(date); 9536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 9546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int vers = in.readInt(); 9556447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (vers != VERSION) { 9566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" (old data version)"); 9576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.println(sb.toString()); 9586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 9596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 9606447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 9616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.println(sb.toString()); 9626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int N = in.readInt(); 9636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 9646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (N > 0) { 9656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn N--; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName = in.readString(); 9676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pkgName == null) { 9686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn break; 9696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 9706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.setLength(0); 9716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); 9729fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (packages != null && !packages.contains(pkgName)) { 9739fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // This package has not been requested -- don't print 9749fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // anything for it. 9759fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } else if (isCompactOutput) { 9766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("P:"); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(pkgName); 978760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 9796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mLaunchCount); 980760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 9816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mUsageTime); 9826447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 9832286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int NLT = pus.mLaunchTimes.size(); 9842286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<NLT; i++) { 9852286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append("A:"); 9862286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn String activity = pus.mLaunchTimes.keyAt(i); 9872286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(activity); 9882286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn TimeStats times = pus.mLaunchTimes.valueAt(i); 9892286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(','); 9902286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.count); 9912286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { 9922286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(","); 9932286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.times[j]); 9946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 9952286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append('\n'); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9972286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int NFDT = pus.mFullyDrawnTimes.size(); 9982286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<NFDT; i++) { 9992286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append("A:"); 10002286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn String activity = pus.mFullyDrawnTimes.keyAt(i); 10012286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(activity); 10022286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn TimeStats times = pus.mFullyDrawnTimes.valueAt(i); 10032286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { 10042286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(","); 10052286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.times[j]); 10062286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10072286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append('\n'); 10082286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10092286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 10106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } else { 10116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" "); 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(pkgName); 10136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(": "); 10146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mLaunchCount); 10156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" times, "); 10166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mUsageTime); 10176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" ms"); 10186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 10192286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int NLT = pus.mLaunchTimes.size(); 10202286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<NLT; i++) { 10212286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(" "); 10222286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(pus.mLaunchTimes.keyAt(i)); 10232286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn TimeStats times = pus.mLaunchTimes.valueAt(i); 10242286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(": "); 10252286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.count); 10262286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(" starts"); 10272286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn int lastBin = 0; 10282286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { 10292286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (times.times[j] != 0) { 10302286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(", "); 10312286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(lastBin); 10322286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append('-'); 10332286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(LAUNCH_TIME_BINS[j]); 10342286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append("ms="); 10352286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.times[j]); 10362286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10372286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn lastBin = LAUNCH_TIME_BINS[j]; 10382286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10392286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { 10402286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(", "); 10412286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(">="); 10422286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(lastBin); 10432286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append("ms="); 10442286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); 10452286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10462286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append('\n'); 10472286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10482286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn final int NFDT = pus.mFullyDrawnTimes.size(); 10492286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int i=0; i<NFDT; i++) { 10502286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(" "); 10512286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(pus.mFullyDrawnTimes.keyAt(i)); 10522286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn TimeStats times = pus.mFullyDrawnTimes.valueAt(i); 10532286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(": fully drawn "); 10542286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn boolean needComma = false; 10552286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn int lastBin = 0; 10562286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { 10572286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (times.times[j] != 0) { 10582286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (needComma) { 1059760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(", "); 10602286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } else { 10612286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn needComma = true; 1062f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 1063f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(lastBin); 10642286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append('-'); 10652286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(LAUNCH_TIME_BINS[j]); 1066760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append("ms="); 10672286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.times[j]); 10682286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10692286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn lastBin = LAUNCH_TIME_BINS[j]; 10702286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn } 10712286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { 10722286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn if (needComma) { 10732286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(", "); 1074f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 10752286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(">="); 10762286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(lastBin); 10772286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append("ms="); 10782286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); 10796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 10802286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn sb.append('\n'); 10816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 10846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.write(sb.toString()); 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Searches array of arguments for the specified string 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args array of argument strings 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value value to search for 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the value is contained in the array 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean scanArgs(String[] args, String value) { 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args != null) { 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String arg : args) { 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.equals(arg)) { 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11059fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn /** 11069fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * Searches array of arguments for the specified string's data 11079fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * @param args array of argument strings 11089fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * @param value value to search for 11099fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * @return the string of data after the arg, or null if there is none 11109fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn */ 11119fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn private static String scanArgsData(String[] args, String value) { 11129fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (args != null) { 11139fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn final int N = args.length; 11149fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn for (int i=0; i<N; i++) { 11159fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (value.equals(args[i])) { 11169fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn i++; 11179fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn return i < N ? args[i] : null; 11189fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11199fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11209fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11219fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn return null; 11229fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11239fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The data persisted to file is parsed and the stats are computed. 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 11293abd75ba3a981850cac43a401d0014a836559cb0Kenny Root if (mContext.checkCallingPermission(android.Manifest.permission.DUMP) 11303abd75ba3a981850cac43a401d0014a836559cb0Kenny Root != PackageManager.PERMISSION_GRANTED) { 11313abd75ba3a981850cac43a401d0014a836559cb0Kenny Root pw.println("Permission Denial: can't dump UsageStats from from pid=" 11323abd75ba3a981850cac43a401d0014a836559cb0Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 11333abd75ba3a981850cac43a401d0014a836559cb0Kenny Root + " without permission " + android.Manifest.permission.DUMP); 11343abd75ba3a981850cac43a401d0014a836559cb0Kenny Root return; 11353abd75ba3a981850cac43a401d0014a836559cb0Kenny Root } 11363abd75ba3a981850cac43a401d0014a836559cb0Kenny Root 11376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean isCheckinRequest = scanArgs(args, "--checkin"); 11386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); 11396447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); 11409fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn final String rawPackages = scanArgsData(args, "--packages"); 11416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 11426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Make sure the current stats are written to the file. This 11436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // doesn't need to be done if we are deleting files after printing, 11446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // since it that case we won't print the current stats. 11456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!deleteAfterPrint) { 1146c63502720e7b7c72e823589cf9afeb16f08c7c7dMark Brophy writeStatsToFile(true, false); 11476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 11486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 11499fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn HashSet<String> packages = null; 11509fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (rawPackages != null) { 11519fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (!"*".equals(rawPackages)) { 11529fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // A * is a wildcard to show all packages. 11539fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn String[] names = rawPackages.split(","); 11549fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn for (String n : names) { 11559fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (packages == null) { 11569fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn packages = new HashSet<String>(); 11579fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11589fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn packages.add(n); 11599fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11609fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11619fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } else if (isCheckinRequest) { 11629fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // If checkin doesn't specify any packages, then we simply won't 11639fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // show anything. 11648a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Checkin without packages"); 11659fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn return; 11669fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 11679fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 11699fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages); 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1174