UsageStatsService.java revision 760ec4a095567457707abe764cf4dfda0ed84032
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; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 456447ca30b8e41c22c7214f201120327057e356dcDianne Hackbornimport java.util.TimeZone; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This service collects the statistics associated with usage 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of various components, like when a particular package is launched or 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * paused and aggregates events like number of time a component is launched 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * total duration of a component launch. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class UsageStatsService extends IUsageStats.Stub { 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String SERVICE_NAME = "usagestats"; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean localLOGV = false; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "UsageStats"; 576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Current on-disk Parcel version 59760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private static final int VERSION = 1005; 606447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 61760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private static final int CHECKIN_VERSION = 4; 626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final String FILE_PREFIX = "usage-"; 646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms 666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final int MAX_NUM_FILES = 5; 686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 69f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private static final int NUM_LAUNCH_TIME_BINS = 10; 70f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private static final int[] LAUNCH_TIME_BINS = { 71f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000 72f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn }; 736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static IUsageStats sService; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // structure used to maintain statistics since the last checkin. 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final private Map<String, PkgUsageStatsExtended> mStats; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Lock to update package stats. Methods suffixed by SLOCK should invoked with 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this lock held 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mStatsLock; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Lock to write to file. Methods suffixed by FLOCK should invoked with 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this lock held. 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mFileLock; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks 85760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private String mLastResumedPkg; 86760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private String mLastResumedComp; 87760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private boolean mIsResumed; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private File mFile; 896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private String mFileLeaf; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //private File mBackupFile; 916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private long mLastWriteElapsedTime; 926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private File mDir; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Calendar mCal; 946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private int mLastWriteDay; 956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn static class TimeStats { 97760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn int count; 98f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn int[] times = new int[NUM_LAUNCH_TIME_BINS]; 996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 100f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats() { 101f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 1026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 103760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void incCount() { 104760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn count++; 105760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 106760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 1076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn void add(int val) { 108f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] bins = LAUNCH_TIME_BINS; 109f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { 110f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (val < bins[i]) { 111f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times[i]++; 112f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn return; 1136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 115f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times[NUM_LAUNCH_TIME_BINS-1]++; 1166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 118f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats(Parcel in) { 119760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn count = in.readInt(); 120f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] localTimes = times; 121f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 122f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn localTimes[i] = in.readInt(); 1236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 124f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 125f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 126f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn void writeToParcel(Parcel out) { 127760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn out.writeInt(count); 128f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] localTimes = times; 129f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 130f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn out.writeInt(localTimes[i]); 1316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class PkgUsageStatsExtended { 1366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final HashMap<String, TimeStats> mLaunchTimes 1376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn = new HashMap<String, TimeStats>(); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mLaunchCount; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mUsageTime; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mPausedTime; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mResumedTime; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended() { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchCount = 0; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime = 0; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended(Parcel in) { 1496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchCount = in.readInt(); 1506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mUsageTime = in.readLong(); 1516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (localLOGV) Log.v(TAG, "Launch count: " + mLaunchCount 1526447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn + ", Usage time:" + mUsageTime); 1536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int N = in.readInt(); 1556447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (localLOGV) Log.v(TAG, "Reading comps: " + N); 1566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (int i=0; i<N; i++) { 1576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String comp = in.readString(); 158f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (localLOGV) Log.v(TAG, "Component: " + comp); 159f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats times = new TimeStats(in); 160f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn mLaunchTimes.put(comp, times); 1616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 164760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void updateResume(boolean launched) { 165760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (launched) { 166760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLaunchCount ++; 167760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResumedTime = SystemClock.elapsedRealtime(); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void updatePause() { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPausedTime = SystemClock.elapsedRealtime(); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime += (mPausedTime - mResumedTime); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 176760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void addLaunchCount(String comp) { 177760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn TimeStats times = mLaunchTimes.get(comp); 178760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (times == null) { 179760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn times = new TimeStats(); 180760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLaunchTimes.put(comp, times); 181760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 182760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn times.incCount(); 183760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 184760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 1856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn void addLaunchTime(String comp, int millis) { 1866447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = mLaunchTimes.get(comp); 1876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (times == null) { 1886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn times = new TimeStats(); 1896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchTimes.put(comp, times); 1906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn times.add(millis); 1926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 194f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn void writeToParcel(Parcel out) { 1956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(mLaunchCount); 1966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeLong(mUsageTime); 1976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int N = mLaunchTimes.size(); 1986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(N); 1996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (N > 0) { 2006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) { 2016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeString(ent.getKey()); 2026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = ent.getValue(); 203f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times.writeToParcel(out); 2046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void clear() { 2096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchTimes.clear(); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchCount = 0; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime = 0; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn UsageStatsService(String dir) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats = new HashMap<String, PkgUsageStatsExtended>(); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStatsLock = new Object(); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFileLock = new Object(); 2196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mDir = new File(dir); 2206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); 2216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mDir.mkdir(); 2236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Remove any old usage files from previous versions. 2256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File parentDir = mDir.getParentFile(); 2266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String fList[] = parentDir.list(); 2276447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (fList != null) { 2286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String prefix = mDir.getName() + "."; 2296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int i = fList.length; 2306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (i > 0) { 2316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn i--; 2326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (fList[i].startsWith(prefix)) { 2336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn Log.i(TAG, "Deleting old usage file: " + fList[i]); 2346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (new File(parentDir, fList[i])).delete(); 2356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update current stats which are binned by date 2406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFileLeaf = getCurrentDateStr(FILE_PREFIX); 2416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile = new File(mDir, mFileLeaf); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readStatsFromFile(); 2436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteElapsedTime = SystemClock.elapsedRealtime(); 2446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // mCal was set by getCurrentDateStr(), want to use that same time. 2456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteDay = mCal.get(Calendar.DAY_OF_YEAR); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility method to convert date into string. 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getCurrentDateStr(String prefix) { 2526447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal.setTimeInMillis(System.currentTimeMillis()); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prefix != null) { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(mCal.get(Calendar.YEAR)); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mm < 10) { 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("0"); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mm); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dd = mCal.get(Calendar.DAY_OF_MONTH); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dd < 10) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("0"); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(dd); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Parcel getParcelForFile(File file) throws IOException { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileInputStream stream = new FileInputStream(file); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] raw = readFully(stream); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = Parcel.obtain(); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.unmarshall(raw, 0, raw.length); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.setDataPosition(0); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stream.close(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return in; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readStatsFromFile() { 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File newFile = mFile; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newFile.exists()) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readStatsFLOCK(newFile); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for file limit before creating a new file 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkFileLimitFLOCK(); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFile.createNewFile(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG,"Error : " + e + " reading data from file:" + newFile); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readStatsFLOCK(File file) throws IOException { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = getParcelForFile(file); 3006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int vers = in.readInt(); 3016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (vers != VERSION) { 3026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn Log.w(TAG, "Usage stats version changed; dropping"); 3036447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 3046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int N = in.readInt(); 3066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (N > 0) { 3076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn N--; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName = in.readString(); 3096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pkgName == null) { 3106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn break; 3116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (localLOGV) Log.v(TAG, "Reading package #" + N + ": " + pkgName); 3136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.put(pkgName, pus); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<String> getUsageStatsFileListFLOCK() { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check if there are too many files in the system and delete older files 3226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String fList[] = mDir.list(); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fList == null) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> fileList = new ArrayList<String>(); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String file : fList) { 3286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!file.startsWith(FILE_PREFIX)) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (file.endsWith(".bak")) { 3326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (new File(mDir, file)).delete(); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fileList.add(file); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fileList; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkFileLimitFLOCK() { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get all usage stats output files 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> fileList = getUsageStatsFileListFLOCK(); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileList == null) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strange but we dont have to delete any thing 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fileList.size(); 3486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (count <= MAX_NUM_FILES) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sort files 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collections.sort(fileList); 3536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn count -= MAX_NUM_FILES; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete older files 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String fileName = fileList.get(i); 3576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File file = new File(mDir, fileName); 3586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn Log.i(TAG, "Deleting usage file : " + fileName); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project file.delete(); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private void writeStatsToFile(boolean force) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 3656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal.setTimeInMillis(System.currentTimeMillis()); 3666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int curDay = mCal.get(Calendar.DAY_OF_YEAR); 3676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Determine if the day changed... note that this will be wrong 3686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // if the year has changed but we are in the same day of year... 3696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // we can probably live with this. 3706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean dayChanged = curDay != mLastWriteDay; 3716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn long currElapsedTime = SystemClock.elapsedRealtime(); 3726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!force) { 3736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (((currElapsedTime-mLastWriteElapsedTime) < FILE_WRITE_INTERVAL) && 3746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (!dayChanged)) { 3756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // wait till the next update 3766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 3776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the most recent file 3806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFileLeaf = getCurrentDateStr(FILE_PREFIX); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Copy current file to back up 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File backupFile = new File(mFile.getPath() + ".bak"); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFile.renameTo(backupFile); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write mStats to file 386f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn writeStatsFLOCK(); 3876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteElapsedTime = currElapsedTime; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dayChanged) { 3896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteDay = curDay; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clear stats 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStats) { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.clear(); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile = new File(mDir, mFileLeaf); 3956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn checkFileLimitFLOCK(); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete the backup file 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (backupFile != null) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project backupFile.delete(); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Failed writing stats to file:" + mFile); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (backupFile != null) { 4046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile.delete(); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project backupFile.renameTo(mFile); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 411f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private void writeStatsFLOCK() throws IOException { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileOutputStream stream = new FileOutputStream(mFile); 4136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn try { 4146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn Parcel out = Parcel.obtain(); 415f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn writeStatsToParcelFLOCK(out); 4166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.write(out.marshall()); 4176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.recycle(); 4186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.flush(); 4196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } finally { 4206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.close(); 4216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 424f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private void writeStatsToParcelFLOCK(Parcel out) { 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 4266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(VERSION); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> keys = mStats.keySet(); 4286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(keys.size()); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String key : keys) { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(key); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeString(key); 432f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn pus.writeToParcel(out); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void publish(Context context) { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ServiceManager.addService(SERVICE_NAME, asBinder()); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 44255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void shutdown() { 44355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.w(TAG, "Writing usage stats before shutdown..."); 44455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn writeStatsToFile(true); 44555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 44655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static IUsageStats getService() { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sService != null) { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sService; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder b = ServiceManager.getService(SERVICE_NAME); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sService = asInterface(b); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sService; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void noteResumeComponent(ComponentName componentName) { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enforceCallingPermission(); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 460760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if ((componentName == null) || 461760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 462760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 463760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 464760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 465760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn final boolean samePackage = pkgName.equals(mLastResumedPkg); 466760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (mIsResumed) { 467760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (samePackage) { 468760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn Log.w(TAG, "Something wrong here, didn't expect " 469760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + pkgName + " to be resumed"); 470760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 471760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 472760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 473760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (mLastResumedPkg != null) { 474760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // We last resumed some other package... just pause it now 475760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // to recover. 476760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn Log.w(TAG, "Unexpected resume of " + pkgName 477760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + " while already resumed in " + mLastResumedPkg); 478760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg); 479760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (pus != null) { 480760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.updatePause(); 481760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 482760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 483760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 484760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 485760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn final boolean sameComp = samePackage 486760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn && componentName.getClassName().equals(mLastResumedComp); 487760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 488760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mIsResumed = true; 489760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLastResumedPkg = pkgName; 490760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLastResumedComp = componentName.getClassName(); 491760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 492760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (localLOGV) Log.i(TAG, "started component:" + pkgName); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pus = new PkgUsageStatsExtended(); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.put(pkgName, pus); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 498760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.updateResume(!samePackage); 499760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (!sameComp) { 500760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.addLaunchCount(mLastResumedComp); 501760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notePauseComponent(ComponentName componentName) { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enforceCallingPermission(); 5076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 509760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn String pkgName; 510760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if ((componentName == null) || 511760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 512760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 513760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 514760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (!mIsResumed) { 515760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn Log.w(TAG, "Something wrong here, didn't expect " 516760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + pkgName + " to be paused"); 517760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 518760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 519760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mIsResumed = false; 520760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 521760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (localLOGV) Log.i(TAG, "paused component:"+pkgName); 522760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Weird some error here 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "No package stats for pkg:"+pkgName); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pus.updatePause(); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 531760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 532760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // Persist current data to file if needed. 533760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn writeStatsToFile(false); 5346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn public void noteLaunchTime(ComponentName componentName, int millis) { 5376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn enforceCallingPermission(); 5386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String pkgName; 5396447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if ((componentName == null) || 5406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 5416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 5426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Persist current data to file if needed. 5456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn writeStatsToFile(false); 5466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn synchronized (mStatsLock) { 5486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = mStats.get(pkgName); 5496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pus != null) { 5506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pus.addLaunchTime(componentName.getClassName(), millis); 5516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5526447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void enforceCallingPermission() { 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Binder.getCallingPid() == Process.myPid()) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.getCallingPid(), Binder.getCallingUid(), null); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PkgUsageStats getPkgUsageStats(ComponentName componentName) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.PACKAGE_USAGE_STATS, null); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((componentName == null) || 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((pkgName = componentName.getPackageName()) == null)) { 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PkgUsageStats[] getAllPkgUsageStats() { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.PACKAGE_USAGE_STATS, null); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> keys = mStats.keySet(); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = keys.size(); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (size <= 0) { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStats retArr[] = new PkgUsageStats[size]; 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i = 0; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String key: keys) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(key); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i++; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retArr; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static byte[] readFully(FileInputStream stream) throws java.io.IOException { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pos = 0; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int avail = stream.available(); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] data = new byte[avail]; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amt = stream.read(data, pos, data.length-pos); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amt <= 0) { 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return data; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos += amt; 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project avail = stream.available(); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (avail > data.length-pos) { 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] newData = new byte[pos+avail]; 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(data, 0, newData, 0, pos); 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data = newData; 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, 6206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn boolean deleteAfterPrint) { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project List<String> fileList = getUsageStatsFileListFLOCK(); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileList == null) { 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collections.sort(fileList); 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String file : fileList) { 6276447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) { 6286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // In this mode we don't print the current day's stats, since 6296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // they are incomplete. 6306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn continue; 6316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File dFile = new File(mDir, file); 6336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String dateStr = file.substring(FILE_PREFIX.length()); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = getParcelForFile(dFile); 6366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput); 6376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (deleteAfterPrint) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete old file after collecting info only for checkin requests 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dFile.delete(); 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (FileNotFoundException e) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file); 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, 6516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String date, boolean isCompactOutput) { 6526447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn StringBuilder sb = new StringBuilder(512); 6536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (isCompactOutput) { 6546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("D:"); 6556447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(CHECKIN_VERSION); 6566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(','); 6576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } else { 6586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("Date: "); 6596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6606447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(date); 6626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int vers = in.readInt(); 6646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (vers != VERSION) { 6656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" (old data version)"); 6666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.println(sb.toString()); 6676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 6686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.println(sb.toString()); 6716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int N = in.readInt(); 6726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (N > 0) { 6746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn N--; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName = in.readString(); 6766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pkgName == null) { 6776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn break; 6786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.setLength(0); 6806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); 6816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (isCompactOutput) { 6826447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("P:"); 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(pkgName); 684760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 6856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mLaunchCount); 686760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 6876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mUsageTime); 6886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 6896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int NC = pus.mLaunchTimes.size(); 6906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (NC > 0) { 6916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) { 6926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("A:"); 6936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(ent.getKey()); 6946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = ent.getValue(); 695760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 696760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(times.count); 697f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 698f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(","); 699f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(times.times[i]); 700f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 7016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 7026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } else { 7066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" "); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(pkgName); 7086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(": "); 7096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mLaunchCount); 7106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" times, "); 7116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mUsageTime); 7126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" ms"); 7136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 7146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int NC = pus.mLaunchTimes.size(); 7156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (NC > 0) { 7166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) { 7176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" "); 7186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(ent.getKey()); 7196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = ent.getValue(); 720760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(": "); 721760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(times.count); 722760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(" starts"); 723f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn int lastBin = 0; 724f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { 725f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (times.times[i] != 0) { 726760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(", "); 727f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(lastBin); 728f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append('-'); 729f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(LAUNCH_TIME_BINS[i]); 730760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append("ms="); 731f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(times.times[i]); 732f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 733f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn lastBin = LAUNCH_TIME_BINS[i]; 734f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 735f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { 736760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(", "); 737f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(">="); 738f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(lastBin); 739760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append("ms="); 740f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); 741f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 7426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 7436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.write(sb.toString()); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Searches array of arguments for the specified string 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args array of argument strings 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value value to search for 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the value is contained in the array 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean scanArgs(String[] args, String value) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args != null) { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String arg : args) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.equals(arg)) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The data persisted to file is parsed and the stats are computed. 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 7736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean isCheckinRequest = scanArgs(args, "--checkin"); 7746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); 7756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); 7766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Make sure the current stats are written to the file. This 7786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // doesn't need to be done if we are deleting files after printing, 7796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // since it that case we won't print the current stats. 7806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!deleteAfterPrint) { 7816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn writeStatsToFile(true); 7826447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 7856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 790