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; 308a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 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; 429fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackbornimport java.util.HashSet; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 466447ca30b8e41c22c7214f201120327057e356dcDianne Hackbornimport java.util.TimeZone; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This service collects the statistics associated with usage 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of various components, like when a particular package is launched or 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * paused and aggregates events like number of time a component is launched 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * total duration of a component launch. 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class UsageStatsService extends IUsageStats.Stub { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String SERVICE_NAME = "usagestats"; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean localLOGV = false; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "UsageStats"; 586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Current on-disk Parcel version 60760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private static final int VERSION = 1005; 616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 62760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private static final int CHECKIN_VERSION = 4; 636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final String FILE_PREFIX = "usage-"; 656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms 676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final int MAX_NUM_FILES = 5; 696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 70f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private static final int NUM_LAUNCH_TIME_BINS = 10; 71f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private static final int[] LAUNCH_TIME_BINS = { 72f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000 73f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn }; 746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static IUsageStats sService; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // structure used to maintain statistics since the last checkin. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final private Map<String, PkgUsageStatsExtended> mStats; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Lock to update package stats. Methods suffixed by SLOCK should invoked with 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this lock held 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mStatsLock; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Lock to write to file. Methods suffixed by FLOCK should invoked with 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this lock held. 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mFileLock; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks 86760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private String mLastResumedPkg; 87760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private String mLastResumedComp; 88760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn private boolean mIsResumed; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private File mFile; 906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private String mFileLeaf; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //private File mBackupFile; 926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private long mLastWriteElapsedTime; 936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private File mDir; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Calendar mCal; 956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private int mLastWriteDay; 966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn static class TimeStats { 98760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn int count; 99f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn int[] times = new int[NUM_LAUNCH_TIME_BINS]; 1006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 101f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats() { 102f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 1036447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 104760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void incCount() { 105760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn count++; 106760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 107760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 1086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn void add(int val) { 109f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] bins = LAUNCH_TIME_BINS; 110f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { 111f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (val < bins[i]) { 112f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times[i]++; 113f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn return; 1146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 116f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times[NUM_LAUNCH_TIME_BINS-1]++; 1176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 119f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats(Parcel in) { 120760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn count = in.readInt(); 121f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] localTimes = times; 122f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 123f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn localTimes[i] = in.readInt(); 1246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 125f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 126f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 127f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn void writeToParcel(Parcel out) { 128760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn out.writeInt(count); 129f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn final int[] localTimes = times; 130f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 131f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn out.writeInt(localTimes[i]); 1326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class PkgUsageStatsExtended { 1376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final HashMap<String, TimeStats> mLaunchTimes 1386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn = new HashMap<String, TimeStats>(); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mLaunchCount; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mUsageTime; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mPausedTime; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mResumedTime; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended() { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchCount = 0; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime = 0; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended(Parcel in) { 1506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchCount = in.readInt(); 1516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mUsageTime = in.readLong(); 1528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount 1536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn + ", Usage time:" + mUsageTime); 1546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1556447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int N = in.readInt(); 1568a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Reading comps: " + N); 1576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (int i=0; i<N; i++) { 1586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String comp = in.readString(); 1598a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Component: " + comp); 160f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn TimeStats times = new TimeStats(in); 161f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn mLaunchTimes.put(comp, times); 1626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 165760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void updateResume(boolean launched) { 166760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (launched) { 167760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLaunchCount ++; 168760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResumedTime = SystemClock.elapsedRealtime(); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void updatePause() { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPausedTime = SystemClock.elapsedRealtime(); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime += (mPausedTime - mResumedTime); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 177760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn void addLaunchCount(String comp) { 178760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn TimeStats times = mLaunchTimes.get(comp); 179760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (times == null) { 180760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn times = new TimeStats(); 181760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLaunchTimes.put(comp, times); 182760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 183760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn times.incCount(); 184760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 185760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 1866447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn void addLaunchTime(String comp, int millis) { 1876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = mLaunchTimes.get(comp); 1886447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (times == null) { 1896447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn times = new TimeStats(); 1906447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchTimes.put(comp, times); 1916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn times.add(millis); 1936447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 1946447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 195f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn void writeToParcel(Parcel out) { 1966447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(mLaunchCount); 1976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeLong(mUsageTime); 1986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int N = mLaunchTimes.size(); 1996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(N); 2006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (N > 0) { 2016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) { 2026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeString(ent.getKey()); 2036447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = ent.getValue(); 204f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn times.writeToParcel(out); 2056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void clear() { 2106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLaunchTimes.clear(); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchCount = 0; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsageTime = 0; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn UsageStatsService(String dir) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats = new HashMap<String, PkgUsageStatsExtended>(); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStatsLock = new Object(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFileLock = new Object(); 2206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mDir = new File(dir); 2216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); 2226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mDir.mkdir(); 2246447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Remove any old usage files from previous versions. 2266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File parentDir = mDir.getParentFile(); 2276447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String fList[] = parentDir.list(); 2286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (fList != null) { 2296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String prefix = mDir.getName() + "."; 2306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int i = fList.length; 2316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (i > 0) { 2326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn i--; 2336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (fList[i].startsWith(prefix)) { 2348a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "Deleting old usage file: " + fList[i]); 2356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (new File(parentDir, fList[i])).delete(); 2366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 2396447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update current stats which are binned by date 2416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFileLeaf = getCurrentDateStr(FILE_PREFIX); 2426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile = new File(mDir, mFileLeaf); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readStatsFromFile(); 2446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteElapsedTime = SystemClock.elapsedRealtime(); 2456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // mCal was set by getCurrentDateStr(), want to use that same time. 2466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteDay = mCal.get(Calendar.DAY_OF_YEAR); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility method to convert date into string. 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getCurrentDateStr(String prefix) { 2536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal.setTimeInMillis(System.currentTimeMillis()); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prefix != null) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(mCal.get(Calendar.YEAR)); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mm < 10) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("0"); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mm); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dd = mCal.get(Calendar.DAY_OF_MONTH); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dd < 10) { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("0"); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(dd); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Parcel getParcelForFile(File file) throws IOException { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileInputStream stream = new FileInputStream(file); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] raw = readFully(stream); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = Parcel.obtain(); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.unmarshall(raw, 0, raw.length); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.setDataPosition(0); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stream.close(); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return in; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readStatsFromFile() { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File newFile = mFile; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newFile.exists()) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readStatsFLOCK(newFile); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for file limit before creating a new file 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkFileLimitFLOCK(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFile.createNewFile(); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 2948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG,"Error : " + e + " reading data from file:" + newFile); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readStatsFLOCK(File file) throws IOException { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = getParcelForFile(file); 3016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int vers = in.readInt(); 3026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (vers != VERSION) { 3038a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Usage stats version changed; dropping"); 3046447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 3056447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int N = in.readInt(); 3076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (N > 0) { 3086447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn N--; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName = in.readString(); 3106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pkgName == null) { 3116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn break; 3126447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3138a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.v(TAG, "Reading package #" + N + ": " + pkgName); 3146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.put(pkgName, pus); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<String> getUsageStatsFileListFLOCK() { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check if there are too many files in the system and delete older files 3236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String fList[] = mDir.list(); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fList == null) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> fileList = new ArrayList<String>(); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String file : fList) { 3296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!file.startsWith(FILE_PREFIX)) { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (file.endsWith(".bak")) { 3336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (new File(mDir, file)).delete(); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fileList.add(file); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fileList; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkFileLimitFLOCK() { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get all usage stats output files 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> fileList = getUsageStatsFileListFLOCK(); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileList == null) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strange but we dont have to delete any thing 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fileList.size(); 3496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (count <= MAX_NUM_FILES) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sort files 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collections.sort(fileList); 3546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn count -= MAX_NUM_FILES; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete older files 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String fileName = fileList.get(i); 3586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File file = new File(mDir, fileName); 3598a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "Deleting usage file : " + fileName); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project file.delete(); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private void writeStatsToFile(boolean force) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 3666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mCal.setTimeInMillis(System.currentTimeMillis()); 3676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int curDay = mCal.get(Calendar.DAY_OF_YEAR); 3686447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Determine if the day changed... note that this will be wrong 3696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // if the year has changed but we are in the same day of year... 3706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // we can probably live with this. 3716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean dayChanged = curDay != mLastWriteDay; 3726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn long currElapsedTime = SystemClock.elapsedRealtime(); 3736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!force) { 3746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (((currElapsedTime-mLastWriteElapsedTime) < FILE_WRITE_INTERVAL) && 3756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn (!dayChanged)) { 3766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // wait till the next update 3776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 3786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the most recent file 3816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFileLeaf = getCurrentDateStr(FILE_PREFIX); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Copy current file to back up 383be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu File backupFile = null; 384be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu if (mFile != null && mFile.exists()) { 385be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu backupFile = new File(mFile.getPath() + ".bak"); 3861afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn if (!backupFile.exists()) { 3871afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn if (!mFile.renameTo(backupFile)) { 3881afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn Slog.w(TAG, "Failed to persist new stats"); 3891afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn return; 3901afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn } 3911afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn } else { 3921afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn mFile.delete(); 393be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu } 3948550f255232eb4e4852466c5297fdc125887f5afSuchi Amalapurapu } 395be1c422a73cf70e1478a13463de5ab929991c619Suchi Amalapurapu 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write mStats to file 398f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn writeStatsFLOCK(); 3996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteElapsedTime = currElapsedTime; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dayChanged) { 4016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mLastWriteDay = curDay; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clear stats 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStats) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.clear(); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4066447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile = new File(mDir, mFileLeaf); 4076447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn checkFileLimitFLOCK(); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete the backup file 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (backupFile != null) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project backupFile.delete(); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 4148a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Failed writing stats to file:" + mFile); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (backupFile != null) { 4166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn mFile.delete(); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project backupFile.renameTo(mFile); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 423f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private void writeStatsFLOCK() throws IOException { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileOutputStream stream = new FileOutputStream(mFile); 4256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn try { 4266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn Parcel out = Parcel.obtain(); 427f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn writeStatsToParcelFLOCK(out); 4286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.write(out.marshall()); 4296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.recycle(); 4306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.flush(); 4316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } finally { 4326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn stream.close(); 4336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 436f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn private void writeStatsToParcelFLOCK(Parcel out) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 4386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(VERSION); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> keys = mStats.keySet(); 4406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn out.writeInt(keys.size()); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String key : keys) { 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(key); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeString(key); 444f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn pus.writeToParcel(out); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void publish(Context context) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ServiceManager.addService(SERVICE_NAME, asBinder()); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void shutdown() { 4558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Writing usage stats before shutdown..."); 45655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn writeStatsToFile(true); 45755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 45855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static IUsageStats getService() { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sService != null) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sService; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder b = ServiceManager.getService(SERVICE_NAME); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sService = asInterface(b); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sService; 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void noteResumeComponent(ComponentName componentName) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enforceCallingPermission(); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 472760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if ((componentName == null) || 473760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 474760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 475760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 476760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 477760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn final boolean samePackage = pkgName.equals(mLastResumedPkg); 478760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (mIsResumed) { 479760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (mLastResumedPkg != null) { 480760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // We last resumed some other package... just pause it now 481760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // to recover. 4828a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "Unexpected resume of " + pkgName 483760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + " while already resumed in " + mLastResumedPkg); 484760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg); 485760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (pus != null) { 486760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.updatePause(); 487760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 488760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 489760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 490760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 491760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn final boolean sameComp = samePackage 492760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn && componentName.getClassName().equals(mLastResumedComp); 493760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 494760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mIsResumed = true; 495760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLastResumedPkg = pkgName; 496760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mLastResumedComp = componentName.getClassName(); 497760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 4988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.i(TAG, "started component:" + pkgName); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pus = new PkgUsageStatsExtended(); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStats.put(pkgName, pus); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 504760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.updateResume(!samePackage); 505760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (!sameComp) { 506760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn pus.addLaunchCount(mLastResumedComp); 507760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notePauseComponent(ComponentName componentName) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enforceCallingPermission(); 5136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 515760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn String pkgName; 516760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if ((componentName == null) || 517760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 518760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 519760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 520760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn if (!mIsResumed) { 5218a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "Something wrong here, didn't expect " 522760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn + pkgName + " to be paused"); 523760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn return; 524760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn } 525760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn mIsResumed = false; 526760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 5278a9b22056b13477f59df934928c00c58b5871c95Joe Onorato if (localLOGV) Slog.i(TAG, "paused component:"+pkgName); 528760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Weird some error here 5328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "No package stats for pkg:"+pkgName); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pus.updatePause(); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 537760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn 538760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn // Persist current data to file if needed. 539760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn writeStatsToFile(false); 5406447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5416447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5426447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn public void noteLaunchTime(ComponentName componentName, int millis) { 5436447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn enforceCallingPermission(); 5446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String pkgName; 5456447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if ((componentName == null) || 5466447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn ((pkgName = componentName.getPackageName()) == null)) { 5476447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 5486447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5496447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5506447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Persist current data to file if needed. 5516447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn writeStatsToFile(false); 5526447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 5536447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn synchronized (mStatsLock) { 5546447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = mStats.get(pkgName); 5556447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pus != null) { 5566447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pus.addLaunchTime(componentName.getClassName(), millis); 5576447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5586447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void enforceCallingPermission() { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Binder.getCallingPid() == Process.myPid()) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.getCallingPid(), Binder.getCallingUid(), null); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PkgUsageStats getPkgUsageStats(ComponentName componentName) { 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.PACKAGE_USAGE_STATS, null); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((componentName == null) || 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((pkgName = componentName.getPackageName()) == null)) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(pkgName); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pus == null) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PkgUsageStats[] getAllPkgUsageStats() { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.PACKAGE_USAGE_STATS, null); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mStatsLock) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> keys = mStats.keySet(); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = keys.size(); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (size <= 0) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStats retArr[] = new PkgUsageStats[size]; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i = 0; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String key: keys) { 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PkgUsageStatsExtended pus = mStats.get(key); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i++; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retArr; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static byte[] readFully(FileInputStream stream) throws java.io.IOException { 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pos = 0; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int avail = stream.available(); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] data = new byte[avail]; 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amt = stream.read(data, pos, data.length-pos); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amt <= 0) { 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return data; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos += amt; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project avail = stream.available(); 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (avail > data.length-pos) { 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] newData = new byte[pos+avail]; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(data, 0, newData, 0, pos); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data = newData; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, 6269fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn boolean deleteAfterPrint, HashSet<String> packages) { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project List<String> fileList = getUsageStatsFileListFLOCK(); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileList == null) { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Collections.sort(fileList); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String file : fileList) { 6336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) { 6346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // In this mode we don't print the current day's stats, since 6356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // they are incomplete. 6366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn continue; 6376447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6386447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn File dFile = new File(mDir, file); 6396447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn String dateStr = file.substring(FILE_PREFIX.length()); 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcel in = getParcelForFile(dFile); 6429fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput, 6439fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn packages); 6446447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (deleteAfterPrint) { 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Delete old file after collecting info only for checkin requests 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dFile.delete(); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (FileNotFoundException e) { 6498a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 6528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file); 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, 6589fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn String date, boolean isCompactOutput, HashSet<String> packages) { 6596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn StringBuilder sb = new StringBuilder(512); 6606447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (isCompactOutput) { 6616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("D:"); 6626447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(CHECKIN_VERSION); 6636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(','); 6646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } else { 6656447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("Date: "); 6666447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6676447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(date); 6696447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6706447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int vers = in.readInt(); 6716447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (vers != VERSION) { 6726447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" (old data version)"); 6736447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.println(sb.toString()); 6746447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn return; 6756447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6766447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6776447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.println(sb.toString()); 6786447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn int N = in.readInt(); 6796447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 6806447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn while (N > 0) { 6816447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn N--; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkgName = in.readString(); 6836447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (pkgName == null) { 6846447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn break; 6856447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 6866447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.setLength(0); 6876447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); 6889fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (packages != null && !packages.contains(pkgName)) { 6899fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // This package has not been requested -- don't print 6909fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // anything for it. 6919fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } else if (isCompactOutput) { 6926447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("P:"); 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(pkgName); 694760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 6956447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mLaunchCount); 696760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 6976447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mUsageTime); 6986447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 6996447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int NC = pus.mLaunchTimes.size(); 7006447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (NC > 0) { 7016447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) { 7026447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append("A:"); 7036639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag String activity = ent.getKey(); 7046639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag if (activity.startsWith(pkgName)) { 7056639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag sb.append('*'); 7066639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag sb.append(activity.substring( 7076639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag pkgName.length(), activity.length())); 7086639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag } else { 7096639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag sb.append(activity); 7106639bb65c5ebb9493afba6d701a22223ac45ba04Christian Sonntag } 7116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = ent.getValue(); 712760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(','); 713760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(times.count); 714f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { 715f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(","); 716f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(times.times[i]); 717f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 7186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 7196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7216447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7226447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } else { 7236447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" "); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(pkgName); 7256447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(": "); 7266447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mLaunchCount); 7276447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" times, "); 7286447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(pus.mUsageTime); 7296447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" ms"); 7306447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 7316447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final int NC = pus.mLaunchTimes.size(); 7326447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (NC > 0) { 7336447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) { 7346447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(" "); 7356447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append(ent.getKey()); 7366447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn TimeStats times = ent.getValue(); 737760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(": "); 738760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(times.count); 739760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(" starts"); 740f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn int lastBin = 0; 741f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { 742f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (times.times[i] != 0) { 743760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(", "); 744f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(lastBin); 745f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append('-'); 746f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(LAUNCH_TIME_BINS[i]); 747760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append("ms="); 748f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(times.times[i]); 749f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 750f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn lastBin = LAUNCH_TIME_BINS[i]; 751f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 752f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { 753760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append(", "); 754f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(">="); 755f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(lastBin); 756760ec4a095567457707abe764cf4dfda0ed84032Dianne Hackborn sb.append("ms="); 757f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); 758f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 7596447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn sb.append('\n'); 7606447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7616447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7636447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 7646447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn pw.write(sb.toString()); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Searches array of arguments for the specified string 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args array of argument strings 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value value to search for 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the value is contained in the array 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean scanArgs(String[] args, String value) { 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args != null) { 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String arg : args) { 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.equals(arg)) { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7859fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn /** 7869fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * Searches array of arguments for the specified string's data 7879fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * @param args array of argument strings 7889fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * @param value value to search for 7899fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn * @return the string of data after the arg, or null if there is none 7909fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn */ 7919fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn private static String scanArgsData(String[] args, String value) { 7929fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (args != null) { 7939fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn final int N = args.length; 7949fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn for (int i=0; i<N; i++) { 7959fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (value.equals(args[i])) { 7969fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn i++; 7979fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn return i < N ? args[i] : null; 7989fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 7999fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8009fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8019fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn return null; 8029fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8039fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The data persisted to file is parsed and the stats are computed. 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 8096447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean isCheckinRequest = scanArgs(args, "--checkin"); 8106447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); 8116447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); 8129fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn final String rawPackages = scanArgsData(args, "--packages"); 8136447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 8146447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // Make sure the current stats are written to the file. This 8156447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // doesn't need to be done if we are deleting files after printing, 8166447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn // since it that case we won't print the current stats. 8176447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn if (!deleteAfterPrint) { 8186447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn writeStatsToFile(true); 8196447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn } 8206447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn 8219fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn HashSet<String> packages = null; 8229fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (rawPackages != null) { 8239fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (!"*".equals(rawPackages)) { 8249fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // A * is a wildcard to show all packages. 8259fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn String[] names = rawPackages.split(","); 8269fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn for (String n : names) { 8279fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn if (packages == null) { 8289fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn packages = new HashSet<String>(); 8299fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8309fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn packages.add(n); 8319fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8329fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8339fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } else if (isCheckinRequest) { 8349fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // If checkin doesn't specify any packages, then we simply won't 8359fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn // show anything. 8368a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Checkin without packages"); 8379fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn return; 8389fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn } 8399fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mFileLock) { 8419fdbf6ae465f90b50ca5feb320215b98018c9937Dianne Hackborn collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages); 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 846