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
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.app.IUsageStats;
2055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.os.PkgUsageStats;
268bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn
278bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackbornimport android.os.FileUtils;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
328a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
449fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackbornimport java.util.HashSet;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
486447ca30b8e41c22c7214f201120327057e356dcDianne Hackbornimport java.util.TimeZone;
49389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrickimport java.util.concurrent.atomic.AtomicBoolean;
50389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrickimport java.util.concurrent.atomic.AtomicInteger;
51389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrickimport java.util.concurrent.atomic.AtomicLong;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This service collects the statistics associated with usage
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of various components, like when a particular package is launched or
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * paused and aggregates events like number of time a component is launched
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * total duration of a component launch.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class UsageStatsService extends IUsageStats.Stub {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SERVICE_NAME = "usagestats";
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean localLOGV = false;
62cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn    private static final boolean REPORT_UNEXPECTED = false;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "UsageStats";
646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    // Current on-disk Parcel version
66760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn    private static final int VERSION = 1005;
676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
68760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn    private static final int CHECKIN_VERSION = 4;
696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    private static final String FILE_PREFIX = "usage-";
716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    private static final int MAX_NUM_FILES = 5;
756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
76f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn    private static final int NUM_LAUNCH_TIME_BINS = 10;
77f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn    private static final int[] LAUNCH_TIME_BINS = {
78f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
79f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn    };
806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static IUsageStats sService;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // structure used to maintain statistics since the last checkin.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private Map<String, PkgUsageStatsExtended> mStats;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Lock to update package stats. Methods suffixed by SLOCK should invoked with
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // this lock held
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Object mStatsLock;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Lock to write to file. Methods suffixed by FLOCK should invoked with
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // this lock held.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Object mFileLock;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
92760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn    private String mLastResumedPkg;
93760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn    private String mLastResumedComp;
94760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn    private boolean mIsResumed;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private File mFile;
966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    private String mFileLeaf;
976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    private File mDir;
98389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick
99389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    private Calendar mCal; // guarded by itself
100389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick
101389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    private final AtomicInteger mLastWriteDay = new AtomicInteger(-1);
102389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0);
103389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false);
1046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
1056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    static class TimeStats {
106760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        int count;
107f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        int[] times = new int[NUM_LAUNCH_TIME_BINS];
1086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
109f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        TimeStats() {
110f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        }
1116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
112760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        void incCount() {
113760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            count++;
114760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        }
115760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
1166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        void add(int val) {
117f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            final int[] bins = LAUNCH_TIME_BINS;
118f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
119f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                if (val < bins[i]) {
120f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                    times[i]++;
121f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                    return;
1226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                }
1236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
124f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            times[NUM_LAUNCH_TIME_BINS-1]++;
1256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
1266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
127f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        TimeStats(Parcel in) {
128760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            count = in.readInt();
129f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            final int[] localTimes = times;
130f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
131f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                localTimes[i] = in.readInt();
1326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
133f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        }
134f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn
135f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        void writeToParcel(Parcel out) {
136760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            out.writeInt(count);
137f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            final int[] localTimes = times;
138f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
139f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                out.writeInt(localTimes[i]);
1406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
1416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
1426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class PkgUsageStatsExtended {
1456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        final HashMap<String, TimeStats> mLaunchTimes
1466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                = new HashMap<String, TimeStats>();
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mLaunchCount;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long mUsageTime;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long mPausedTime;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long mResumedTime;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PkgUsageStatsExtended() {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLaunchCount = 0;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUsageTime = 0;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
1576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        PkgUsageStatsExtended(Parcel in) {
1586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            mLaunchCount = in.readInt();
1596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            mUsageTime = in.readLong();
1608a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
1616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    + ", Usage time:" + mUsageTime);
1626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
1636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            final int N = in.readInt();
1648a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, "Reading comps: " + N);
1656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            for (int i=0; i<N; i++) {
1666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                String comp = in.readString();
1678a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (localLOGV) Slog.v(TAG, "Component: " + comp);
168f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                TimeStats times = new TimeStats(in);
169f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                mLaunchTimes.put(comp, times);
1706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
1716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
1726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
173760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        void updateResume(boolean launched) {
174760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if (launched) {
175760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                mLaunchCount ++;
176760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mResumedTime = SystemClock.elapsedRealtime();
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void updatePause() {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPausedTime =  SystemClock.elapsedRealtime();
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUsageTime += (mPausedTime - mResumedTime);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
185760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        void addLaunchCount(String comp) {
186760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            TimeStats times = mLaunchTimes.get(comp);
187760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if (times == null) {
188760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                times = new TimeStats();
189760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                mLaunchTimes.put(comp, times);
190760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
191760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            times.incCount();
192760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        }
193760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
1946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        void addLaunchTime(String comp, int millis) {
1956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            TimeStats times = mLaunchTimes.get(comp);
1966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (times == null) {
1976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                times = new TimeStats();
1986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                mLaunchTimes.put(comp, times);
1996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
2006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            times.add(millis);
2016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
2026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
203f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn        void writeToParcel(Parcel out) {
2046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            out.writeInt(mLaunchCount);
2056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            out.writeLong(mUsageTime);
2066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            final int N = mLaunchTimes.size();
2076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            out.writeInt(N);
2086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (N > 0) {
2096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
2106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    out.writeString(ent.getKey());
2116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    TimeStats times = ent.getValue();
212f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                    times.writeToParcel(out);
2136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                }
2146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
2156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
2166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void clear() {
2186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            mLaunchTimes.clear();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLaunchCount = 0;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUsageTime = 0;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    UsageStatsService(String dir) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStats = new HashMap<String, PkgUsageStatsExtended>();
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStatsLock = new Object();
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileLock = new Object();
2286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        mDir = new File(dir);
2296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
2306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
2316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        mDir.mkdir();
2326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
2336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        // Remove any old usage files from previous versions.
2346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        File parentDir = mDir.getParentFile();
2356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        String fList[] = parentDir.list();
2366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if (fList != null) {
2376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            String prefix = mDir.getName() + ".";
2386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            int i = fList.length;
2396447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            while (i > 0) {
2406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                i--;
2416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                if (fList[i].startsWith(prefix)) {
2428a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.i(TAG, "Deleting old usage file: " + fList[i]);
2436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    (new File(parentDir, fList[i])).delete();
2446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                }
2456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
2466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
2476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Update current stats which are binned by date
2496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        mFileLeaf = getCurrentDateStr(FILE_PREFIX);
2506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        mFile = new File(mDir, mFileLeaf);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readStatsFromFile();
252389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        mLastWriteElapsedTime.set(SystemClock.elapsedRealtime());
2536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        // mCal was set by getCurrentDateStr(), want to use that same time.
254389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        mLastWriteDay.set(mCal.get(Calendar.DAY_OF_YEAR));
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Utility method to convert date into string.
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String getCurrentDateStr(String prefix) {
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder sb = new StringBuilder();
262389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        synchronized (mCal) {
263389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            mCal.setTimeInMillis(System.currentTimeMillis());
264389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            if (prefix != null) {
265389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                sb.append(prefix);
266389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            }
267389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            sb.append(mCal.get(Calendar.YEAR));
268389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
269389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            if (mm < 10) {
270389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                sb.append("0");
271389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            }
272389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            sb.append(mm);
273389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            int dd = mCal.get(Calendar.DAY_OF_MONTH);
274389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            if (dd < 10) {
275389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                sb.append("0");
276389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            }
277389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            sb.append(dd);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sb.toString();
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Parcel getParcelForFile(File file) throws IOException {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileInputStream stream = new FileInputStream(file);
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] raw = readFully(stream);
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Parcel in = Parcel.obtain();
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        in.unmarshall(raw, 0, raw.length);
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        in.setDataPosition(0);
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stream.close();
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return in;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void readStatsFromFile() {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        File newFile = mFile;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mFileLock) {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (newFile.exists()) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    readStatsFLOCK(newFile);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Check for file limit before creating a new file
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    checkFileLimitFLOCK();
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newFile.createNewFile();
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
3048a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG,"Error : " + e + " reading data from file:" + newFile);
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void readStatsFLOCK(File file) throws IOException {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Parcel in = getParcelForFile(file);
3116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        int vers = in.readInt();
3126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if (vers != VERSION) {
3138a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Usage stats version changed; dropping");
3146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            return;
3156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
3166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        int N = in.readInt();
3176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        while (N > 0) {
3186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            N--;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String pkgName = in.readString();
3206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (pkgName == null) {
3216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                break;
3226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
3238a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, "Reading package #" + N + ": " + pkgName);
3246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mStatsLock) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStats.put(pkgName, pus);
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<String> getUsageStatsFileListFLOCK() {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if there are too many files in the system and delete older files
3336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        String fList[] = mDir.list();
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fList == null) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<String> fileList = new ArrayList<String>();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String file : fList) {
3396447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (!file.startsWith(FILE_PREFIX)) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (file.endsWith(".bak")) {
3436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                (new File(mDir, file)).delete();
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fileList.add(file);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return fileList;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkFileLimitFLOCK() {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get all usage stats output files
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<String> fileList = getUsageStatsFileListFLOCK();
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fileList == null) {
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Strange but we dont have to delete any thing
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = fileList.size();
3596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if (count <= MAX_NUM_FILES) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Sort files
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Collections.sort(fileList);
3646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        count -= MAX_NUM_FILES;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Delete older files
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < count; i++) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String fileName = fileList.get(i);
3686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            File file = new File(mDir, fileName);
3698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.i(TAG, "Deleting usage file : " + fileName);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            file.delete();
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
373389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick
374389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    /**
375389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     * Conditionally start up a disk write if it's been awhile, or the
376389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     * day has rolled over.
377389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     *
378389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     * This is called indirectly from user-facing actions (when
379389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     * 'force' is false) so it tries to be quick, without writing to
380389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     * disk directly or acquiring heavy locks.
381389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     *
382389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     * @params force  do an unconditional, synchronous stats flush
383389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     *                to disk on the current thread.
384389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick     */
385389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    private void writeStatsToFile(final boolean force) {
386389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        int curDay;
387389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        synchronized (mCal) {
3886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            mCal.setTimeInMillis(System.currentTimeMillis());
389389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            curDay = mCal.get(Calendar.DAY_OF_YEAR);
390389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        }
391389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        final boolean dayChanged = curDay != mLastWriteDay.get();
392389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick
393389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        // Determine if the day changed...  note that this will be wrong
394389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        // if the year has changed but we are in the same day of year...
395389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        // we can probably live with this.
396389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        final long currElapsedTime = SystemClock.elapsedRealtime();
397389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick
398389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        // Fast common path, without taking the often-contentious
399389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        // mFileLock.
400389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        if (!force) {
401389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            if (!dayChanged &&
402389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                (currElapsedTime - mLastWriteElapsedTime.get()) < FILE_WRITE_INTERVAL) {
403389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                // wait till the next update
404389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                return;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
406389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            if (mUnforcedDiskWriteRunning.compareAndSet(false, true)) {
407389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                new Thread("UsageStatsService_DiskWriter") {
408389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                    public void run() {
409389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                        try {
410cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (localLOGV) Slog.d(TAG, "Disk writer thread starting.");
411389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                            writeStatsToFile(true);
412389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                        } finally {
413389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                            mUnforcedDiskWriteRunning.set(false);
414cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (localLOGV) Slog.d(TAG, "Disk writer thread ending.");
415389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                        }
416389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                    }
417389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                }.start();
418389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            }
419389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick            return;
420389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        }
421389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick
422389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        synchronized (mFileLock) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Get the most recent file
4246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            mFileLeaf = getCurrentDateStr(FILE_PREFIX);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Copy current file to back up
426be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu            File backupFile = null;
427be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu            if (mFile != null && mFile.exists()) {
428be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu                backupFile = new File(mFile.getPath() + ".bak");
4291afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                if (!backupFile.exists()) {
4301afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                    if (!mFile.renameTo(backupFile)) {
4311afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                        Slog.w(TAG, "Failed to persist new stats");
4321afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                        return;
4331afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                    }
4341afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                } else {
4351afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                    mFile.delete();
436be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu                }
4378550f255232eb4e4852466c5297fdc125887f5afSuchi Amalapurapu            }
438be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Write mStats to file
441389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                writeStatsFLOCK(mFile);
442389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                mLastWriteElapsedTime.set(currElapsedTime);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (dayChanged) {
444389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick                    mLastWriteDay.set(curDay);
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // clear stats
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mStats) {
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mStats.clear();
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    mFile = new File(mDir, mFileLeaf);
4506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    checkFileLimitFLOCK();
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Delete the backup file
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (backupFile != null) {
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    backupFile.delete();
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
4578a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Failed writing stats to file:" + mFile);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (backupFile != null) {
4596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    mFile.delete();
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    backupFile.renameTo(mFile);
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
464cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        if (localLOGV) Slog.d(TAG, "Dumped usage stats.");
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
467389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick    private void writeStatsFLOCK(File file) throws IOException {
468389a916769aaf4b329839285d2f975fc23aadfb4Brad Fitzpatrick        FileOutputStream stream = new FileOutputStream(file);
4696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        try {
4706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            Parcel out = Parcel.obtain();
471f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn            writeStatsToParcelFLOCK(out);
4726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            stream.write(out.marshall());
4736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            out.recycle();
4746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            stream.flush();
4756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        } finally {
4768bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn            FileUtils.sync(stream);
4776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            stream.close();
4786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
481f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn    private void writeStatsToParcelFLOCK(Parcel out) {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mStatsLock) {
4836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            out.writeInt(VERSION);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Set<String> keys = mStats.keySet();
4856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            out.writeInt(keys.size());
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String key : keys) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PkgUsageStatsExtended pus = mStats.get(key);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.writeString(key);
489f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                pus.writeToParcel(out);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void publish(Context context) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ServiceManager.addService(SERVICE_NAME, asBinder());
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void shutdown() {
500cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        Slog.i(TAG, "Writing usage stats before shutdown...");
50155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        writeStatsToFile(true);
50255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
50355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static IUsageStats getService() {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sService != null) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sService;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IBinder b = ServiceManager.getService(SERVICE_NAME);
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sService = asInterface(b);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sService;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void noteResumeComponent(ComponentName componentName) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceCallingPermission();
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String pkgName;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mStatsLock) {
517760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if ((componentName == null) ||
518760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    ((pkgName = componentName.getPackageName()) == null)) {
519760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                return;
520760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
521760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
522760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            final boolean samePackage = pkgName.equals(mLastResumedPkg);
523760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if (mIsResumed) {
524760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                if (mLastResumedPkg != null) {
525760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    // We last resumed some other package...  just pause it now
526760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    // to recover.
527cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                    if (REPORT_UNEXPECTED) Slog.i(TAG, "Unexpected resume of " + pkgName
528760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                            + " while already resumed in " + mLastResumedPkg);
529760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg);
530760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    if (pus != null) {
531760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        pus.updatePause();
532760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    }
533760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                }
534760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
535760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
536760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            final boolean sameComp = samePackage
537760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    && componentName.getClassName().equals(mLastResumedComp);
538760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
539760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            mIsResumed = true;
540760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            mLastResumedPkg = pkgName;
541760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            mLastResumedComp = componentName.getClassName();
542760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
5438a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.i(TAG, "started component:" + pkgName);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PkgUsageStatsExtended pus = mStats.get(pkgName);
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pus == null) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pus = new PkgUsageStatsExtended();
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStats.put(pkgName, pus);
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
549760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            pus.updateResume(!samePackage);
550760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if (!sameComp) {
551760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                pus.addLaunchCount(mLastResumedComp);
552760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void notePauseComponent(ComponentName componentName) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceCallingPermission();
5586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mStatsLock) {
560760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            String pkgName;
561760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if ((componentName == null) ||
562760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                    ((pkgName = componentName.getPackageName()) == null)) {
563760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                return;
564760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
565760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            if (!mIsResumed) {
566cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                if (REPORT_UNEXPECTED) Slog.i(TAG, "Something wrong here, didn't expect "
567760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        + pkgName + " to be paused");
568760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                return;
569760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            }
570760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn            mIsResumed = false;
571760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
5728a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.i(TAG, "paused component:"+pkgName);
573760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PkgUsageStatsExtended pus = mStats.get(pkgName);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pus == null) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Weird some error here
5778a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.i(TAG, "No package stats for pkg:"+pkgName);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pus.updatePause();
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
582760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn
583760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        // Persist current data to file if needed.
584760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn        writeStatsToFile(false);
5856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    }
5866447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
5876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    public void noteLaunchTime(ComponentName componentName, int millis) {
5886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        enforceCallingPermission();
5896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        String pkgName;
5906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if ((componentName == null) ||
5916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                ((pkgName = componentName.getPackageName()) == null)) {
5926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            return;
5936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
5946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
5956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        // Persist current data to file if needed.
5966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        writeStatsToFile(false);
5976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
5986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        synchronized (mStatsLock) {
5996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            PkgUsageStatsExtended pus = mStats.get(pkgName);
6006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (pus != null) {
6016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                pus.addLaunchTime(componentName.getClassName(), millis);
6026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
6036447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enforceCallingPermission() {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Binder.getCallingPid() == Process.myPid()) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.getCallingPid(), Binder.getCallingUid(), null);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String pkgName;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((componentName == null) ||
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((pkgName = componentName.getPackageName()) == null)) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mStatsLock) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PkgUsageStatsExtended pus = mStats.get(pkgName);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pus == null) {
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               return null;
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PkgUsageStats[] getAllPkgUsageStats() {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mStatsLock) {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Set<String> keys = mStats.keySet();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = keys.size();
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (size <= 0) {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PkgUsageStats retArr[] = new PkgUsageStats[size];
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i = 0;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String key: keys) {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PkgUsageStatsExtended pus = mStats.get(key);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime);
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                i++;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return retArr;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int pos = 0;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int avail = stream.available();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] data = new byte[avail];
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (true) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int amt = stream.read(data, pos, data.length-pos);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (amt <= 0) {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return data;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos += amt;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            avail = stream.available();
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (avail > data.length-pos) {
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] newData = new byte[pos+avail];
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                System.arraycopy(data, 0, newData, 0, pos);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                data = newData;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn    private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
6719fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            boolean deleteAfterPrint, HashSet<String> packages) {
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<String> fileList = getUsageStatsFileListFLOCK();
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fileList == null) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Collections.sort(fileList);
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String file : fileList) {
6786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) {
6796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                // In this mode we don't print the current day's stats, since
6806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                // they are incomplete.
6816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                continue;
6826447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
6836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            File dFile = new File(mDir, file);
6846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            String dateStr = file.substring(FILE_PREFIX.length());
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Parcel in = getParcelForFile(dFile);
6879fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput,
6889fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                        packages);
6896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                if (deleteAfterPrint) {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Delete old file after collecting info only for checkin requests
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    dFile.delete();
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (FileNotFoundException e) {
6948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
6978a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
7039fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            String date, boolean isCompactOutput, HashSet<String> packages) {
7046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        StringBuilder sb = new StringBuilder(512);
7056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if (isCompactOutput) {
7066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            sb.append("D:");
7076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            sb.append(CHECKIN_VERSION);
7086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            sb.append(',');
7096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        } else {
7106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            sb.append("Date: ");
7116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
7126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.append(date);
7146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
7156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        int vers = in.readInt();
7166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if (vers != VERSION) {
7176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            sb.append(" (old data version)");
7186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            pw.println(sb.toString());
7196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            return;
7206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
7216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
7226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        pw.println(sb.toString());
7236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        int N = in.readInt();
7246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
7256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        while (N > 0) {
7266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            N--;
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String pkgName = in.readString();
7286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            if (pkgName == null) {
7296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                break;
7306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            }
7316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            sb.setLength(0);
7326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
7339fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            if (packages != null && !packages.contains(pkgName)) {
7349fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                // This package has not been requested -- don't print
7359fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                // anything for it.
7369fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            } else if (isCompactOutput) {
7376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append("P:");
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(pkgName);
739760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                sb.append(',');
7406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(pus.mLaunchCount);
741760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                sb.append(',');
7426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(pus.mUsageTime);
7436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append('\n');
7446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                final int NC = pus.mLaunchTimes.size();
7456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                if (NC > 0) {
7466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
7476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        sb.append("A:");
7486639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                        String activity = ent.getKey();
7496639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                        if (activity.startsWith(pkgName)) {
7506639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                            sb.append('*');
7516639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                            sb.append(activity.substring(
7526639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                                    pkgName.length(), activity.length()));
7536639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                        } else {
7546639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                            sb.append(activity);
7556639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag                        }
7566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        TimeStats times = ent.getValue();
757760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        sb.append(',');
758760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        sb.append(times.count);
759f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
760f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            sb.append(",");
761f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            sb.append(times.times[i]);
762f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        }
7636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        sb.append('\n');
7646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
7676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            } else {
7686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append("  ");
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(pkgName);
7706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(": ");
7716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(pus.mLaunchCount);
7726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(" times, ");
7736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(pus.mUsageTime);
7746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append(" ms");
7756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                sb.append('\n');
7766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                final int NC = pus.mLaunchTimes.size();
7776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                if (NC > 0) {
7786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
7796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        sb.append("    ");
7806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        sb.append(ent.getKey());
7816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        TimeStats times = ent.getValue();
782760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        sb.append(": ");
783760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        sb.append(times.count);
784760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                        sb.append(" starts");
785f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        int lastBin = 0;
786f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
787f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            if (times.times[i] != 0) {
788760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                                sb.append(", ");
789f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                                sb.append(lastBin);
790f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                                sb.append('-');
791f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                                sb.append(LAUNCH_TIME_BINS[i]);
792760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                                sb.append("ms=");
793f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                                sb.append(times.times[i]);
794f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            }
795f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            lastBin = LAUNCH_TIME_BINS[i];
796f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        }
797f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
798760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                            sb.append(", ");
799f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            sb.append(">=");
800f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            sb.append(lastBin);
801760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn                            sb.append("ms=");
802f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                            sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
803f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn                        }
8046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                        sb.append('\n');
8056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                    }
8066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn                }
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
8096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            pw.write(sb.toString());
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Searches array of arguments for the specified string
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param args array of argument strings
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param value value to search for
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the value is contained in the array
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean scanArgs(String[] args, String value) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (args != null) {
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String arg : args) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value.equals(arg)) {
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8309fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn    /**
8319fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn     * Searches array of arguments for the specified string's data
8329fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn     * @param args array of argument strings
8339fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn     * @param value value to search for
8349fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn     * @return the string of data after the arg, or null if there is none
8359fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn     */
8369fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn    private static String scanArgsData(String[] args, String value) {
8379fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        if (args != null) {
8389fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            final int N = args.length;
8399fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            for (int i=0; i<N; i++) {
8409fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                if (value.equals(args[i])) {
8419fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                    i++;
8429fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                    return i < N ? args[i] : null;
8439fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                }
8449fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            }
8459fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        }
8469fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        return null;
8479fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn    }
8489fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The data persisted to file is parsed and the stats are computed.
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
8546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        final boolean isCheckinRequest = scanArgs(args, "--checkin");
8556447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
8566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
8579fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        final String rawPackages = scanArgsData(args, "--packages");
8586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
8596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        // Make sure the current stats are written to the file.  This
8606447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        // doesn't need to be done if we are deleting files after printing,
8616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        // since it that case we won't print the current stats.
8626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        if (!deleteAfterPrint) {
8636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn            writeStatsToFile(true);
8646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn        }
8656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn
8669fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        HashSet<String> packages = null;
8679fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        if (rawPackages != null) {
8689fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            if (!"*".equals(rawPackages)) {
8699fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                // A * is a wildcard to show all packages.
8709fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                String[] names = rawPackages.split(",");
8719fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                for (String n : names) {
8729fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                    if (packages == null) {
8739fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                        packages = new HashSet<String>();
8749fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                    }
8759fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                    packages.add(n);
8769fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn                }
8779fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            }
8789fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        } else if (isCheckinRequest) {
8799fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            // If checkin doesn't specify any packages, then we simply won't
8809fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            // show anything.
8818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Checkin without packages");
8829fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            return;
8839fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn        }
8849fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mFileLock) {
8869fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn            collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages);
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
891