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