blob: ef032ba5133025b1764b5a6783d336f8cf30704c [file] [log] [blame]
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn904a8572013-06-28 18:12:31 -070019import android.app.AppGlobals;
20import android.content.pm.IPackageManager;
21import android.os.Parcel;
22import android.os.RemoteException;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070023import android.os.SystemClock;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070024import android.os.UserHandle;
Dianne Hackborn169c8032013-07-03 14:42:22 -070025import android.text.format.DateFormat;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070026import android.util.ArrayMap;
Dianne Hackborna17c0f52013-06-20 18:59:11 -070027import android.util.ArraySet;
Dianne Hackborn904a8572013-06-28 18:12:31 -070028import android.util.AtomicFile;
29import android.util.Slog;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070030import android.util.SparseArray;
31import android.util.TimeUtils;
Dianne Hackborn904a8572013-06-28 18:12:31 -070032import com.android.internal.os.BackgroundThread;
Dianne Hackborn13ac0412013-06-25 19:34:49 -070033import com.android.internal.util.ArrayUtils;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070034import com.android.server.ProcessMap;
35
Dianne Hackborn904a8572013-06-28 18:12:31 -070036import java.io.File;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070037import java.io.FileDescriptor;
Dianne Hackborn904a8572013-06-28 18:12:31 -070038import java.io.FileInputStream;
39import java.io.FileOutputStream;
40import java.io.IOException;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070041import java.io.PrintWriter;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070042import java.util.ArrayList;
Dianne Hackborna17c0f52013-06-20 18:59:11 -070043import java.util.Arrays;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070044import java.util.Collections;
45import java.util.Comparator;
Dianne Hackborn904a8572013-06-28 18:12:31 -070046import java.util.concurrent.locks.ReentrantLock;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070047
48public final class ProcessTracker {
Dianne Hackborn904a8572013-06-28 18:12:31 -070049 static final String TAG = "ProcessTracker";
Dianne Hackborn2286cdc2013-07-01 19:10:06 -070050 static final boolean DEBUG = false;
Dianne Hackborn904a8572013-06-28 18:12:31 -070051
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070052 public static final int STATE_NOTHING = -1;
Dianne Hackborna17c0f52013-06-20 18:59:11 -070053 public static final int STATE_PERSISTENT = 0;
54 public static final int STATE_TOP = 1;
Dianne Hackbornc8230512013-07-13 21:32:12 -070055 public static final int STATE_IMPORTANT_FOREGROUND = 2;
56 public static final int STATE_IMPORTANT_BACKGROUND = 3;
57 public static final int STATE_BACKUP = 4;
58 public static final int STATE_HEAVY_WEIGHT = 5;
Dianne Hackborna17c0f52013-06-20 18:59:11 -070059 public static final int STATE_SERVICE = 6;
Dianne Hackbornc8230512013-07-13 21:32:12 -070060 public static final int STATE_RECEIVER = 7;
61 public static final int STATE_HOME = 8;
62 public static final int STATE_LAST_ACTIVITY = 9;
63 public static final int STATE_CACHED_ACTIVITY = 10;
64 public static final int STATE_CACHED_ACTIVITY_CLIENT = 11;
65 public static final int STATE_CACHED_EMPTY = 12;
66 public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070067
Dianne Hackbornc8230512013-07-13 21:32:12 -070068 static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
69 STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND,
70 STATE_BACKUP, STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_RECEIVER,
71 STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
72 STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
Dianne Hackborncfc837f2013-06-27 18:32:07 -070073 };
74
Dianne Hackborn13ac0412013-06-25 19:34:49 -070075 public static final int PSS_SAMPLE_COUNT = 0;
76 public static final int PSS_MINIMUM = 1;
77 public static final int PSS_AVERAGE = 2;
78 public static final int PSS_MAXIMUM = 3;
Dianne Hackbornc8230512013-07-13 21:32:12 -070079 public static final int PSS_USS_MINIMUM = 4;
80 public static final int PSS_USS_AVERAGE = 5;
81 public static final int PSS_USS_MAXIMUM = 6;
82 public static final int PSS_COUNT = PSS_USS_MAXIMUM+1;
Dianne Hackborn13ac0412013-06-25 19:34:49 -070083
Dianne Hackborn91268cf2013-06-13 19:06:50 -070084 public static final int ADJ_NOTHING = -1;
85 public static final int ADJ_MEM_FACTOR_NORMAL = 0;
86 public static final int ADJ_MEM_FACTOR_MODERATE = 1;
87 public static final int ADJ_MEM_FACTOR_LOW = 2;
88 public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
89 public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
90 public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
91 public static final int ADJ_SCREEN_OFF = 0;
92 public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
93 public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070094
Dianne Hackborncfc837f2013-06-27 18:32:07 -070095 static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
96 static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL, ADJ_MEM_FACTOR_MODERATE,
97 ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
98
Dianne Hackborn13ac0412013-06-25 19:34:49 -070099 // Most data is kept in a sparse data structure: an integer array which integer
100 // holds the type of the entry, and the identifier for a long array that data
101 // exists in and the offset into the array to find it. The constants below
102 // define the encoding of that data in an integer.
103
104 // Where the "type"/"state" part of the data appears in an offset integer.
105 static int OFFSET_TYPE_SHIFT = 0;
106 static int OFFSET_TYPE_MASK = 0xff;
107
108 // Where the "which array" part of the data appears in an offset integer.
109 static int OFFSET_ARRAY_SHIFT = 8;
110 static int OFFSET_ARRAY_MASK = 0xff;
111
112 // Where the "index into array" part of the data appears in an offset integer.
113 static int OFFSET_INDEX_SHIFT = 16;
114 static int OFFSET_INDEX_MASK = 0xffff;
115
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700116 static final String[] STATE_NAMES = new String[] {
Dianne Hackbornc8230512013-07-13 21:32:12 -0700117 "Persistent", "Top ", "Imp Fg ", "Imp Bg ",
118 "Backup ", "Heavy Wght", "Service ", "Receiver ", "Home ",
119 "Last Act ", "Cch Actvty", "Cch Client", "Cch Empty "
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -0700120 };
121
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700122 static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
123 "off", "on"
124 };
125
126 static final String[] ADJ_MEM_NAMES_CSV = new String[] {
127 "norm", "mod", "low", "crit"
128 };
129
130 static final String[] STATE_NAMES_CSV = new String[] {
Dianne Hackbornc8230512013-07-13 21:32:12 -0700131 "pers", "top", "impfg", "impbg", "backup", "heavy",
132 "service", "receiver", "home", "lastact",
133 "cch-activity", "cch-aclient", "cch-empty"
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700134 };
135
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700136 static final String[] ADJ_SCREEN_TAGS = new String[] {
137 "0", "1"
138 };
139
140 static final String[] ADJ_MEM_TAGS = new String[] {
141 "n", "m", "l", "c"
142 };
143
144 static final String[] STATE_TAGS = new String[] {
Dianne Hackbornc8230512013-07-13 21:32:12 -0700145 "p", "t", "f", "b", "u", "w",
146 "s", "r", "h", "l", "a", "c", "e"
147 };
148
149 // Map from process states to the states we track.
150 static final int[] PROCESS_STATE_TO_STATE = new int[] {
151 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
152 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
153 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
154 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
155 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
156 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP
157 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
158 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE
159 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER
160 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME
161 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
162 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
163 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
164 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700165 };
166
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700167 static final String CSV_SEP = "\t";
168
Dianne Hackborn169c8032013-07-03 14:42:22 -0700169 static final int MAX_HISTORIC_STATES = 4; // Maximum number of historic states we will keep.
170 static final String STATE_FILE_PREFIX = "state-"; // Prefix to use for state filenames.
Dianne Hackborna4cc2052013-07-08 17:31:25 -0700171 static final String STATE_FILE_SUFFIX = ".bin"; // Suffix to use for state filenames.
172 static final String STATE_FILE_CHECKIN_SUFFIX = ".ci"; // State files that have checked in.
Dianne Hackborn904a8572013-06-28 18:12:31 -0700173 static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so.
Dianne Hackborn169c8032013-07-03 14:42:22 -0700174 static long COMMIT_PERIOD = 24*60*60*1000; // Commit current stats every day.
Dianne Hackborn904a8572013-06-28 18:12:31 -0700175
Dianne Hackborna4cc2052013-07-08 17:31:25 -0700176 final Object mLock;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700177 final File mBaseDir;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700178 State mState;
179 boolean mCommitPending;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700180 boolean mShuttingDown;
181
Dianne Hackborn904a8572013-06-28 18:12:31 -0700182 final ReentrantLock mWriteLock = new ReentrantLock();
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700183
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -0700184 public static final class ProcessState {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700185 static final int[] BAD_TABLE = new int[0];
186
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700187 final State mState;
188 final ProcessState mCommonProcess;
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700189 final String mPackage;
190 final int mUid;
191 final String mName;
192
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700193 int[] mDurationsTable;
194 int mDurationsTableSize;
195
196 //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -0700197 int mCurState = STATE_NOTHING;
198 long mStartTime;
199
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700200 int mLastPssState = STATE_NOTHING;
201 long mLastPssTime;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700202 int[] mPssTable;
203 int mPssTableSize;
204
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700205 int mNumExcessiveWake;
206 int mNumExcessiveCpu;
207
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700208 boolean mMultiPackage;
209
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700210 long mTmpTotalTime;
211
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700212 /**
213 * Create a new top-level process state, for the initial case where there is only
214 * a single package running in a process. The initial state is not running.
215 */
216 public ProcessState(State state, String pkg, int uid, String name) {
217 mState = state;
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700218 mCommonProcess = this;
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700219 mPackage = pkg;
220 mUid = uid;
221 mName = name;
222 }
223
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700224 /**
225 * Create a new per-package process state for an existing top-level process
226 * state. The current running state of the top-level process is also copied,
227 * marked as started running at 'now'.
228 */
229 public ProcessState(ProcessState commonProcess, String pkg, int uid, String name,
230 long now) {
231 mState = commonProcess.mState;
232 mCommonProcess = commonProcess;
233 mPackage = pkg;
234 mUid = uid;
235 mName = name;
236 mCurState = commonProcess.mCurState;
237 mStartTime = now;
238 }
239
240 ProcessState clone(String pkg, long now) {
241 ProcessState pnew = new ProcessState(this, pkg, mUid, mName, now);
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700242 if (mDurationsTable != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700243 mState.mAddLongTable = new int[mDurationsTable.length];
244 mState.mAddLongTableSize = 0;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700245 for (int i=0; i<mDurationsTableSize; i++) {
246 int origEnt = mDurationsTable[i];
247 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
248 int newOff = mState.addLongData(i, type, 1);
Dianne Hackborn904a8572013-06-28 18:12:31 -0700249 mState.mAddLongTable[i] = newOff | type;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700250 mState.setLong(newOff, 0, mState.getLong(origEnt, 0));
251 }
Dianne Hackborn904a8572013-06-28 18:12:31 -0700252 pnew.mDurationsTable = mState.mAddLongTable;
253 pnew.mDurationsTableSize = mState.mAddLongTableSize;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700254 }
255 /*
256 if (mPssTable != null) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700257 mState.mAddLongTable = new int[mPssTable.length];
258 mState.mAddLongTableSize = 0;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700259 for (int i=0; i<mPssTableSize; i++) {
260 int origEnt = mPssTable[i];
261 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
262 int newOff = mState.addLongData(i, type, PSS_COUNT);
Dianne Hackborn904a8572013-06-28 18:12:31 -0700263 mState.mAddLongTable[i] = newOff | type;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700264 for (int j=0; j<PSS_COUNT; j++) {
265 mState.setLong(newOff, j, mState.getLong(origEnt, j));
266 }
267 }
Dianne Hackborn904a8572013-06-28 18:12:31 -0700268 pnew.mPssTable = mState.mAddLongTable;
269 pnew.mPssTableSize = mState.mAddLongTableSize;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700270 }
271 */
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700272 pnew.mNumExcessiveWake = mNumExcessiveWake;
273 pnew.mNumExcessiveCpu = mNumExcessiveCpu;
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700274 return pnew;
275 }
276
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700277 void resetSafely(long now) {
278 mDurationsTable = null;
279 mDurationsTableSize = 0;
280 mStartTime = now;
281 mLastPssState = STATE_NOTHING;
282 mLastPssTime = 0;
283 mPssTable = null;
284 mPssTableSize = 0;
285 mNumExcessiveWake = 0;
286 mNumExcessiveCpu = 0;
287 }
288
Dianne Hackborn904a8572013-06-28 18:12:31 -0700289 void writeToParcel(Parcel out, long now) {
290 commitStateTime(now);
291 out.writeInt(mMultiPackage ? 1 : 0);
292 out.writeInt(mDurationsTableSize);
293 for (int i=0; i<mDurationsTableSize; i++) {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700294 if (DEBUG) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
295 + State.printLongOffset(mDurationsTable[i]));
Dianne Hackborn904a8572013-06-28 18:12:31 -0700296 out.writeInt(mDurationsTable[i]);
297 }
298 out.writeInt(mPssTableSize);
299 for (int i=0; i<mPssTableSize; i++) {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700300 if (DEBUG) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
301 + State.printLongOffset(mPssTable[i]));
Dianne Hackborn904a8572013-06-28 18:12:31 -0700302 out.writeInt(mPssTable[i]);
303 }
304 out.writeInt(mNumExcessiveWake);
305 out.writeInt(mNumExcessiveCpu);
306 }
307
308 private int[] readTable(Parcel in, String what) {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700309 final int size = in.readInt();
Dianne Hackborn904a8572013-06-28 18:12:31 -0700310 if (size < 0) {
311 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size);
Dianne Hackborn169c8032013-07-03 14:42:22 -0700312 return BAD_TABLE;
313 }
314 if (size == 0) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700315 return null;
316 }
Dianne Hackborn169c8032013-07-03 14:42:22 -0700317 final int[] table = new int[size];
Dianne Hackborn904a8572013-06-28 18:12:31 -0700318 for (int i=0; i<size; i++) {
319 table[i] = in.readInt();
Dianne Hackborn169c8032013-07-03 14:42:22 -0700320 if (DEBUG) Slog.i(TAG, "Reading in " + mName + " table #" + i + ": "
321 + State.printLongOffset(table[i]));
Dianne Hackborn904a8572013-06-28 18:12:31 -0700322 if (!mState.validateLongOffset(table[i])) {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700323 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
324 + State.printLongOffset(table[i]));
Dianne Hackborn904a8572013-06-28 18:12:31 -0700325 return null;
326 }
327 }
328 return table;
329 }
330
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700331 boolean readFromParcel(Parcel in, boolean fully) {
332 boolean multiPackage = in.readInt() != 0;
333 if (fully) {
334 mMultiPackage = multiPackage;
335 }
Dianne Hackborn169c8032013-07-03 14:42:22 -0700336 if (DEBUG) Slog.d(TAG, "Reading durations table...");
Dianne Hackborn904a8572013-06-28 18:12:31 -0700337 mDurationsTable = readTable(in, "durations");
Dianne Hackborn169c8032013-07-03 14:42:22 -0700338 if (mDurationsTable == BAD_TABLE) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700339 return false;
340 }
Dianne Hackborn169c8032013-07-03 14:42:22 -0700341 mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
342 if (DEBUG) Slog.d(TAG, "Reading pss table...");
Dianne Hackborn904a8572013-06-28 18:12:31 -0700343 mPssTable = readTable(in, "pss");
Dianne Hackborn169c8032013-07-03 14:42:22 -0700344 if (mPssTable == BAD_TABLE) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700345 return false;
346 }
Dianne Hackborn169c8032013-07-03 14:42:22 -0700347 mPssTableSize = mPssTable != null ? mPssTable.length : 0;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700348 mNumExcessiveWake = in.readInt();
349 mNumExcessiveCpu = in.readInt();
350 return true;
351 }
352
Dianne Hackbornc8230512013-07-13 21:32:12 -0700353 /**
354 * Update the current state of the given list of processes.
355 *
356 * @param state Current ActivityManager.PROCESS_STATE_*
357 * @param memFactor Current mem factor constant.
358 * @param now Current time.
359 * @param pkgList Processes to update.
360 */
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700361 public void setState(int state, int memFactor, long now,
362 ArrayMap<String, ProcessTracker.ProcessState> pkgList) {
Dianne Hackbornc8230512013-07-13 21:32:12 -0700363 if (state < 0) {
364 state = STATE_NOTHING;
365 } else {
366 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -0700367 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700368
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700369 // First update the common process.
370 mCommonProcess.setState(state, now);
371
372 // If the common process is not multi-package, there is nothing else to do.
373 if (!mCommonProcess.mMultiPackage) {
374 return;
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700375 }
376
377 for (int ip=pkgList.size()-1; ip>=0; ip--) {
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700378 pullFixedProc(pkgList, ip).setState(state, now);
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700379 }
380 }
381
382 void setState(int state, long now) {
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700383 if (mCurState != state) {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700384 commitStateTime(now);
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700385 mCurState = state;
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700386 }
387 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700388
Dianne Hackborn904a8572013-06-28 18:12:31 -0700389 void commitStateTime(long now) {
390 if (mCurState != STATE_NOTHING) {
391 long dur = now - mStartTime;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700392 if (dur > 0) {
393 int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, mCurState);
394 int off;
395 if (idx >= 0) {
396 off = mDurationsTable[idx];
397 } else {
398 mState.mAddLongTable = mDurationsTable;
399 mState.mAddLongTableSize = mDurationsTableSize;
400 off = mState.addLongData(~idx, mCurState, 1);
401 mDurationsTable = mState.mAddLongTable;
402 mDurationsTableSize = mState.mAddLongTableSize;
403 }
404 long[] longs = mState.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
405 longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700406 }
Dianne Hackborn904a8572013-06-28 18:12:31 -0700407 }
408 mStartTime = now;
409 }
410
Dianne Hackbornc8230512013-07-13 21:32:12 -0700411 public void addPss(long pss, long uss, boolean always) {
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700412 if (!always) {
413 if (mLastPssState == mCurState && SystemClock.uptimeMillis()
414 < (mLastPssTime+(30*1000))) {
415 return;
416 }
417 }
418 mLastPssState = mCurState;
419 mLastPssTime = SystemClock.uptimeMillis();
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700420 if (mCurState != STATE_NOTHING) {
421 int idx = State.binarySearch(mPssTable, mPssTableSize, mCurState);
422 int off;
423 if (idx >= 0) {
424 off = mPssTable[idx];
425 } else {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700426 mState.mAddLongTable = mPssTable;
427 mState.mAddLongTableSize = mPssTableSize;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700428 off = mState.addLongData(~idx, mCurState, PSS_COUNT);
Dianne Hackborn904a8572013-06-28 18:12:31 -0700429 mPssTable = mState.mAddLongTable;
430 mPssTableSize = mState.mAddLongTableSize;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700431 }
432 long[] longs = mState.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
433 idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
434 long count = longs[idx+PSS_SAMPLE_COUNT];
435 if (count == 0) {
436 longs[idx+PSS_SAMPLE_COUNT] = 1;
437 longs[idx+PSS_MINIMUM] = pss;
438 longs[idx+PSS_AVERAGE] = pss;
439 longs[idx+PSS_MAXIMUM] = pss;
Dianne Hackbornc8230512013-07-13 21:32:12 -0700440 longs[idx+PSS_USS_MINIMUM] = uss;
441 longs[idx+PSS_USS_AVERAGE] = uss;
442 longs[idx+PSS_USS_MAXIMUM] = uss;
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700443 } else {
444 longs[idx+PSS_SAMPLE_COUNT] = count+1;
445 if (longs[idx+PSS_MINIMUM] > pss) {
446 longs[idx+PSS_MINIMUM] = pss;
447 }
Dianne Hackbornc8230512013-07-13 21:32:12 -0700448 longs[idx+PSS_AVERAGE] = (long)(
449 ((longs[idx+PSS_AVERAGE]*(double)count)+pss) / (count+1) );
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700450 if (longs[idx+PSS_MAXIMUM] < pss) {
451 longs[idx+PSS_MAXIMUM] = pss;
452 }
Dianne Hackbornc8230512013-07-13 21:32:12 -0700453 if (longs[idx+PSS_USS_MINIMUM] > uss) {
454 longs[idx+PSS_USS_MINIMUM] = uss;
455 }
456 longs[idx+PSS_USS_AVERAGE] = (long)(
457 ((longs[idx+PSS_USS_AVERAGE]*(double)count)+uss) / (count+1) );
458 if (longs[idx+PSS_USS_MAXIMUM] < uss) {
459 longs[idx+PSS_USS_MAXIMUM] = uss;
460 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700461 }
462 }
463 }
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700464
Dianne Hackborncfc837f2013-06-27 18:32:07 -0700465 public void reportExcessiveWake(ArrayMap<String, ProcessTracker.ProcessState> pkgList) {
466 mCommonProcess.mNumExcessiveWake++;
467 if (!mCommonProcess.mMultiPackage) {
468 return;
469 }
470
471 for (int ip=pkgList.size()-1; ip>=0; ip--) {
472 pullFixedProc(pkgList, ip).mNumExcessiveWake++;
473 }
474 }
475
476 public void reportExcessiveCpu(ArrayMap<String, ProcessTracker.ProcessState> pkgList) {
477 mCommonProcess.mNumExcessiveCpu++;
478 if (!mCommonProcess.mMultiPackage) {
479 return;
480 }
481
482 for (int ip=pkgList.size()-1; ip>=0; ip--) {
483 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
484 }
485 }
486
487 private ProcessState pullFixedProc(ArrayMap<String, ProcessTracker.ProcessState> pkgList,
488 int index) {
489 ProcessState proc = pkgList.valueAt(index);
490 if (proc.mMultiPackage) {
491 // The array map is still pointing to a common process state
492 // that is now shared across packages. Update it to point to
493 // the new per-package state.
494 proc = mState.mPackages.get(pkgList.keyAt(index),
495 proc.mUid).mProcesses.get(proc.mName);
496 if (proc == null) {
497 throw new IllegalStateException("Didn't create per-package process");
498 }
499 pkgList.setValueAt(index, proc);
500 }
501 return proc;
502 }
503
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700504 long getDuration(int state, long now) {
505 int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, state);
506 long time = idx >= 0 ? mState.getLong(mDurationsTable[idx], 0) : 0;
507 if (mCurState == state) {
508 time += now - mStartTime;
509 }
510 return time;
511 }
512
513 long getPssSampleCount(int state) {
514 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
515 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
516 }
517
518 long getPssMinimum(int state) {
519 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
520 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
521 }
522
523 long getPssAverage(int state) {
524 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
525 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
526 }
527
528 long getPssMaximum(int state) {
529 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
530 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
531 }
Dianne Hackbornc8230512013-07-13 21:32:12 -0700532
533 long getPssUssMinimum(int state) {
534 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
535 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
536 }
537
538 long getPssUssAverage(int state) {
539 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
540 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
541 }
542
543 long getPssUssMaximum(int state) {
544 int idx = State.binarySearch(mPssTable, mPssTableSize, state);
545 return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
546 }
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700547 }
548
549 public static final class ServiceState {
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700550 final long[] mStartedDurations = new long[ADJ_COUNT];
551 int mStartedCount;
552 int mStartedState = STATE_NOTHING;
553 long mStartedStartTime;
554
555 final long[] mBoundDurations = new long[ADJ_COUNT];
556 int mBoundCount;
557 int mBoundState = STATE_NOTHING;
558 long mBoundStartTime;
559
560 final long[] mExecDurations = new long[ADJ_COUNT];
561 int mExecCount;
562 int mExecState = STATE_NOTHING;
563 long mExecStartTime;
564
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700565 void resetSafely(long now) {
566 for (int i=0; i<ADJ_COUNT; i++) {
567 mStartedDurations[i] = mBoundDurations[i] = mExecDurations[i] = 0;
568 }
569 mStartedCount = mBoundCount = mExecCount = 0;
570 mStartedStartTime = mBoundStartTime = mExecStartTime = now;
571 }
572
Dianne Hackborn904a8572013-06-28 18:12:31 -0700573 void writeToParcel(Parcel out, long now) {
574 if (mStartedState != STATE_NOTHING) {
575 mStartedDurations[mStartedState] += now - mStartedStartTime;
576 mStartedStartTime = now;
577 }
578 if (mBoundState != STATE_NOTHING) {
579 mBoundDurations[mBoundState] += now - mBoundStartTime;
580 mBoundStartTime = now;
581 }
582 if (mExecState != STATE_NOTHING) {
583 mExecDurations[mExecState] += now - mExecStartTime;
584 mExecStartTime = now;
585 }
586 out.writeLongArray(mStartedDurations);
587 out.writeInt(mStartedCount);
588 out.writeLongArray(mBoundDurations);
589 out.writeInt(mBoundCount);
590 out.writeLongArray(mExecDurations);
591 out.writeInt(mExecCount);
592 }
593
594 boolean readFromParcel(Parcel in) {
595 in.readLongArray(mStartedDurations);
596 mStartedCount = in.readInt();
597 in.readLongArray(mBoundDurations);
598 mBoundCount = in.readInt();
599 in.readLongArray(mExecDurations);
600 mExecCount = in.readInt();
601 return true;
602 }
603
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700604 public void setStarted(boolean started, int memFactor, long now) {
605 int state = started ? memFactor : STATE_NOTHING;
606 if (mStartedState != state) {
607 if (mStartedState != STATE_NOTHING) {
608 mStartedDurations[mStartedState] += now - mStartedStartTime;
609 } else if (started) {
610 mStartedCount++;
611 }
612 mStartedState = state;
613 mStartedStartTime = now;
614 }
615 }
616
617 public void setBound(boolean bound, int memFactor, long now) {
618 int state = bound ? memFactor : STATE_NOTHING;
619 if (mBoundState != state) {
620 if (mBoundState != STATE_NOTHING) {
621 mBoundDurations[mBoundState] += now - mBoundStartTime;
622 } else if (bound) {
623 mBoundCount++;
624 }
625 mBoundState = state;
626 mBoundStartTime = now;
627 }
628 }
629
630 public void setExecuting(boolean executing, int memFactor, long now) {
631 int state = executing ? memFactor : STATE_NOTHING;
632 if (mExecState != state) {
633 if (mExecState != STATE_NOTHING) {
634 mExecDurations[mExecState] += now - mExecStartTime;
635 } else if (executing) {
636 mExecCount++;
637 }
638 mExecState = state;
639 mExecStartTime = now;
640 }
641 }
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700642 }
643
644 public static final class PackageState {
645 final ArrayMap<String, ProcessState> mProcesses = new ArrayMap<String, ProcessState>();
646 final ArrayMap<String, ServiceState> mServices = new ArrayMap<String, ServiceState>();
647 final int mUid;
648
649 public PackageState(int uid) {
650 mUid = uid;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -0700651 }
652 }
653
654 static final class State {
Dianne Hackborn904a8572013-06-28 18:12:31 -0700655 // Current version of the parcel format.
Dianne Hackbornc8230512013-07-13 21:32:12 -0700656 private static final int PARCEL_VERSION = 6;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700657 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
658 private static final int MAGIC = 0x50535453;
659
Dianne Hackbornc8230512013-07-13 21:32:12 -0700660 static final int FLAG_COMPLETE = 1<<0;
661 static final int FLAG_SHUTDOWN = 1<<1;
662
Dianne Hackborn169c8032013-07-03 14:42:22 -0700663 final File mBaseDir;
664 final ProcessTracker mProcessTracker;
665 AtomicFile mFile;
666 String mReadError;
667
668 long mTimePeriodStartClock;
669 String mTimePeriodStartClockStr;
670 long mTimePeriodStartRealtime;
671 long mTimePeriodEndRealtime;
672 boolean mRunning;
Dianne Hackbornc8230512013-07-13 21:32:12 -0700673 int mFlags;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700674
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700675 final ProcessMap<PackageState> mPackages = new ProcessMap<PackageState>();
Dianne Hackborna17c0f52013-06-20 18:59:11 -0700676 final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700677 final long[] mMemFactorDurations = new long[ADJ_COUNT];
Dianne Hackborn78a369c2013-06-11 17:10:32 -0700678 int mMemFactor = STATE_NOTHING;
679 long mStartTime;
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -0700680
Dianne Hackborn13ac0412013-06-25 19:34:49 -0700681 static final int LONGS_SIZE = 4096;
682 final ArrayList<long[]> mLongs = new ArrayList<long[]>();
683 int mNextLong;
684
Dianne Hackborn904a8572013-06-28 18:12:31 -0700685 int[] mAddLongTable;
686 int mAddLongTableSize;
687
Dianne Hackborn169c8032013-07-03 14:42:22 -0700688 final Object mPendingWriteLock = new Object();
689 Parcel mPendingWrite;
690 long mLastWriteTime;
691
692 State(File baseDir, ProcessTracker tracker) {
693 mBaseDir = baseDir;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700694 reset();
Dianne Hackborn169c8032013-07-03 14:42:22 -0700695 mProcessTracker = tracker;
696 }
697
698 State(String file) {
699 mBaseDir = null;
700 reset();
701 mFile = new AtomicFile(new File(file));
702 mProcessTracker = null;
703 readLocked();
Dianne Hackborn904a8572013-06-28 18:12:31 -0700704 }
705
706 void reset() {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700707 if (DEBUG && mFile != null) Slog.d(TAG, "Resetting state of " + mFile.getBaseFile());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700708 resetCommon();
Dianne Hackborn904a8572013-06-28 18:12:31 -0700709 mPackages.getMap().clear();
710 mProcesses.getMap().clear();
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700711 mMemFactor = STATE_NOTHING;
712 mStartTime = 0;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700713 if (DEBUG && mFile != null) Slog.d(TAG, "State reset; now " + mFile.getBaseFile());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700714 }
715
716 void resetSafely() {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700717 if (DEBUG && mFile != null) Slog.d(TAG, "Safely resetting state of " + mFile.getBaseFile());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700718 resetCommon();
719 long now = SystemClock.uptimeMillis();
720 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
721 final int NPROC = procMap.size();
722 for (int ip=0; ip<NPROC; ip++) {
723 SparseArray<ProcessState> uids = procMap.valueAt(ip);
724 final int NUID = uids.size();
725 for (int iu=0; iu<NUID; iu++) {
726 uids.valueAt(iu).resetSafely(now);
727 }
728 }
729 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
730 final int NPKG = pkgMap.size();
731 for (int ip=0; ip<NPKG; ip++) {
732 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
733 final int NUID = uids.size();
734 for (int iu=0; iu<NUID; iu++) {
735 PackageState pkgState = uids.valueAt(iu);
736 final int NPROCS = pkgState.mProcesses.size();
737 for (int iproc=0; iproc<NPROCS; iproc++) {
738 pkgState.mProcesses.valueAt(iproc).resetSafely(now);
739 }
740 final int NSRVS = pkgState.mServices.size();
741 for (int isvc=0; isvc<NSRVS; isvc++) {
742 pkgState.mServices.valueAt(isvc).resetSafely(now);
743 }
744 }
745 }
746 mStartTime = SystemClock.uptimeMillis();
Dianne Hackborn169c8032013-07-03 14:42:22 -0700747 if (DEBUG && mFile != null) Slog.d(TAG, "State reset; now " + mFile.getBaseFile());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -0700748 }
749
750 private void resetCommon() {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700751 mLastWriteTime = SystemClock.uptimeMillis();
752 mTimePeriodStartClock = System.currentTimeMillis();
753 buildTimePeriodStartClockStr();
754 mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn904a8572013-06-28 18:12:31 -0700755 mLongs.clear();
756 mLongs.add(new long[LONGS_SIZE]);
757 mNextLong = 0;
758 Arrays.fill(mMemFactorDurations, 0);
759 mMemFactor = STATE_NOTHING;
760 mStartTime = 0;
Dianne Hackbornc8230512013-07-13 21:32:12 -0700761 mReadError = null;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700762 }
763
Dianne Hackborn169c8032013-07-03 14:42:22 -0700764 private void buildTimePeriodStartClockStr() {
765 mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
766 mTimePeriodStartClock).toString();
767 if (mBaseDir != null) {
768 mFile = new AtomicFile(new File(mBaseDir,
Dianne Hackborna4cc2052013-07-08 17:31:25 -0700769 STATE_FILE_PREFIX + mTimePeriodStartClockStr + STATE_FILE_SUFFIX));
Dianne Hackborn169c8032013-07-03 14:42:22 -0700770 }
771 }
772
773 static byte[] readFully(FileInputStream stream) throws java.io.IOException {
774 int pos = 0;
775 int avail = stream.available();
776 byte[] data = new byte[avail];
777 while (true) {
778 int amt = stream.read(data, pos, data.length-pos);
779 //Log.i("foo", "Read " + amt + " bytes at " + pos
780 // + " of avail " + data.length);
781 if (amt <= 0) {
782 //Log.i("foo", "**** FINISHED READING: pos=" + pos
783 // + " len=" + data.length);
784 return data;
785 }
786 pos += amt;
787 avail = stream.available();
788 if (avail > data.length-pos) {
789 byte[] newData = new byte[pos+avail];
790 System.arraycopy(data, 0, newData, 0, pos);
791 data = newData;
792 }
793 }
794 }
795
Dianne Hackbornc8230512013-07-13 21:32:12 -0700796 boolean readLocked() {
Dianne Hackborn169c8032013-07-03 14:42:22 -0700797 try {
798 FileInputStream stream = mFile.openRead();
799
800 byte[] raw = readFully(stream);
801 Parcel in = Parcel.obtain();
802 in.unmarshall(raw, 0, raw.length);
803 in.setDataPosition(0);
804 stream.close();
805
806 readFromParcel(in);
807 if (mReadError != null) {
808 Slog.w(TAG, "Ignoring existing stats; " + mReadError);
809 if (DEBUG) {
810 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
811 final int NPROC = procMap.size();
812 for (int ip=0; ip<NPROC; ip++) {
813 Slog.w(TAG, "Process: " + procMap.keyAt(ip));
814 SparseArray<ProcessState> uids = procMap.valueAt(ip);
815 final int NUID = uids.size();
816 for (int iu=0; iu<NUID; iu++) {
817 Slog.w(TAG, " Uid " + uids.keyAt(iu) + ": " + uids.valueAt(iu));
818 }
819 }
820 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
821 final int NPKG = pkgMap.size();
822 for (int ip=0; ip<NPKG; ip++) {
823 Slog.w(TAG, "Package: " + pkgMap.keyAt(ip));
824 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
825 final int NUID = uids.size();
826 for (int iu=0; iu<NUID; iu++) {
827 Slog.w(TAG, " Uid: " + uids.keyAt(iu));
828 PackageState pkgState = uids.valueAt(iu);
829 final int NPROCS = pkgState.mProcesses.size();
830 for (int iproc=0; iproc<NPROCS; iproc++) {
831 Slog.w(TAG, " Process " + pkgState.mProcesses.keyAt(iproc)
832 + ": " + pkgState.mProcesses.valueAt(iproc));
833 }
834 final int NSRVS = pkgState.mServices.size();
835 for (int isvc=0; isvc<NSRVS; isvc++) {
836 Slog.w(TAG, " Service " + pkgState.mServices.keyAt(isvc)
837 + ": " + pkgState.mServices.valueAt(isvc));
838 }
839 }
840 }
841 }
Dianne Hackbornc8230512013-07-13 21:32:12 -0700842 return false;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700843 }
844 } catch (Throwable e) {
Dianne Hackbornc8230512013-07-13 21:32:12 -0700845 mReadError = "caught exception: " + e;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700846 Slog.e(TAG, "Error reading process statistics", e);
Dianne Hackbornc8230512013-07-13 21:32:12 -0700847 return false;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700848 }
Dianne Hackbornc8230512013-07-13 21:32:12 -0700849 return true;
Dianne Hackborn169c8032013-07-03 14:42:22 -0700850 }
851
852 private void writeStateLocked(boolean sync, final boolean commit) {
853 synchronized (mPendingWriteLock) {
854 long now = SystemClock.uptimeMillis();
855 mPendingWrite = Parcel.obtain();
856 mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
857 writeToParcel(mPendingWrite);
858 mLastWriteTime = SystemClock.uptimeMillis();
859 Slog.i(TAG, "Prepared write state in " + (SystemClock.uptimeMillis()-now) + "ms");
860 if (!sync) {
861 BackgroundThread.getHandler().post(new Runnable() {
862 @Override public void run() {
863 performWriteState(commit);
864 }
865 });
866 return;
867 }
868 }
869
870 performWriteState(commit);
871 }
872
873 void performWriteState(boolean commit) {
874 if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile()
875 + " commit=" + commit);
876 Parcel data;
877 synchronized (mPendingWriteLock) {
878 data = mPendingWrite;
879 if (data == null) {
880 return;
881 }
882 mPendingWrite = null;
883 if (mProcessTracker != null) {
884 mProcessTracker.mWriteLock.lock();
885 }
886 }
887
888 FileOutputStream stream = null;
889 try {
890 stream = mFile.startWrite();
891 stream.write(data.marshall());
892 stream.flush();
893 mFile.finishWrite(stream);
894 if (DEBUG) Slog.d(TAG, "Write completed successfully!");
895 } catch (IOException e) {
896 Slog.w(TAG, "Error writing process statistics", e);
897 mFile.failWrite(stream);
898 } finally {
899 data.recycle();
900 if (mProcessTracker != null) {
901 mProcessTracker.trimHistoricStatesWriteLocked();
902 mProcessTracker.mWriteLock.unlock();
903 }
904 }
905
906 if (commit) {
907 resetSafely();
908 }
909 }
910
Dianne Hackborn904a8572013-06-28 18:12:31 -0700911 void writeToParcel(Parcel out) {
912 long now = SystemClock.uptimeMillis();
913 out.writeInt(MAGIC);
914 out.writeInt(PARCEL_VERSION);
915 out.writeInt(STATE_COUNT);
916 out.writeInt(ADJ_COUNT);
917 out.writeInt(PSS_COUNT);
918 out.writeInt(LONGS_SIZE);
919
Dianne Hackborn169c8032013-07-03 14:42:22 -0700920 out.writeLong(mTimePeriodStartClock);
921 out.writeLong(mTimePeriodStartRealtime);
922 out.writeLong(mTimePeriodEndRealtime);
Dianne Hackbornc8230512013-07-13 21:32:12 -0700923 out.writeInt(mFlags);
Dianne Hackborn904a8572013-06-28 18:12:31 -0700924
925 out.writeInt(mLongs.size());
926 out.writeInt(mNextLong);
927 for (int i=0; i<(mLongs.size()-1); i++) {
928 out.writeLongArray(mLongs.get(i));
929 }
930 long[] lastLongs = mLongs.get(mLongs.size()-1);
931 for (int i=0; i<mNextLong; i++) {
932 out.writeLong(lastLongs[i]);
Dianne Hackborn169c8032013-07-03 14:42:22 -0700933 if (DEBUG) Slog.d(TAG, "Writing last long #" + i + ": " + lastLongs[i]);
Dianne Hackborn904a8572013-06-28 18:12:31 -0700934 }
935
936 if (mMemFactor != STATE_NOTHING) {
937 mMemFactorDurations[mMemFactor] += now - mStartTime;
938 mStartTime = now;
939 }
940 out.writeLongArray(mMemFactorDurations);
941
942 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
943 final int NPROC = procMap.size();
944 out.writeInt(NPROC);
945 for (int ip=0; ip<NPROC; ip++) {
946 out.writeString(procMap.keyAt(ip));
947 SparseArray<ProcessState> uids = procMap.valueAt(ip);
948 final int NUID = uids.size();
949 out.writeInt(NUID);
950 for (int iu=0; iu<NUID; iu++) {
951 out.writeInt(uids.keyAt(iu));
952 ProcessState proc = uids.valueAt(iu);
953 out.writeString(proc.mPackage);
954 proc.writeToParcel(out, now);
955 }
956 }
957 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
958 final int NPKG = pkgMap.size();
959 out.writeInt(NPKG);
960 for (int ip=0; ip<NPKG; ip++) {
961 out.writeString(pkgMap.keyAt(ip));
962 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
963 final int NUID = uids.size();
964 out.writeInt(NUID);
965 for (int iu=0; iu<NUID; iu++) {
966 out.writeInt(uids.keyAt(iu));
967 PackageState pkgState = uids.valueAt(iu);
968 final int NPROCS = pkgState.mProcesses.size();
969 out.writeInt(NPROCS);
970 for (int iproc=0; iproc<NPROCS; iproc++) {
971 out.writeString(pkgState.mProcesses.keyAt(iproc));
972 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
973 if (proc.mCommonProcess == proc) {
974 // This is the same as the common process we wrote above.
975 out.writeInt(0);
976 } else {
977 // There is separate data for this package's process.
978 out.writeInt(1);
979 proc.writeToParcel(out, now);
980 }
981 }
982 final int NSRVS = pkgState.mServices.size();
983 out.writeInt(NSRVS);
984 for (int isvc=0; isvc<NSRVS; isvc++) {
985 out.writeString(pkgState.mServices.keyAt(isvc));
986 ServiceState svc = pkgState.mServices.valueAt(isvc);
987 svc.writeToParcel(out, now);
988 }
989 }
990 }
991 }
992
993 private boolean readCheckedInt(Parcel in, int val, String what) {
994 int got;
995 if ((got=in.readInt()) != val) {
Dianne Hackbornc8230512013-07-13 21:32:12 -0700996 mReadError = "bad " + what + ": " + got;
Dianne Hackborn904a8572013-06-28 18:12:31 -0700997 return false;
998 }
999 return true;
1000 }
1001
Dianne Hackborn169c8032013-07-03 14:42:22 -07001002 private void readFromParcel(Parcel in) {
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001003 final boolean hadData = mPackages.getMap().size() > 0
1004 || mProcesses.getMap().size() > 0;
1005 if (hadData) {
1006 resetSafely();
1007 }
1008
Dianne Hackborn904a8572013-06-28 18:12:31 -07001009 if (!readCheckedInt(in, MAGIC, "magic number")) {
1010 return;
1011 }
1012 if (!readCheckedInt(in, PARCEL_VERSION, "version")) {
1013 return;
1014 }
1015 if (!readCheckedInt(in, STATE_COUNT, "state count")) {
1016 return;
1017 }
1018 if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
1019 return;
1020 }
1021 if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
1022 return;
1023 }
1024 if (!readCheckedInt(in, LONGS_SIZE, "longs size")) {
1025 return;
1026 }
1027
Dianne Hackborn169c8032013-07-03 14:42:22 -07001028 mTimePeriodStartClock = in.readLong();
1029 buildTimePeriodStartClockStr();
1030 mTimePeriodStartRealtime = in.readLong();
1031 mTimePeriodEndRealtime = in.readLong();
Dianne Hackbornc8230512013-07-13 21:32:12 -07001032 mFlags = in.readInt();
Dianne Hackborn904a8572013-06-28 18:12:31 -07001033
Dianne Hackborn169c8032013-07-03 14:42:22 -07001034 final int NLONGS = in.readInt();
1035 final int NEXTLONG = in.readInt();
1036 mLongs.clear();
Dianne Hackborn904a8572013-06-28 18:12:31 -07001037 for (int i=0; i<(NLONGS-1); i++) {
1038 while (i >= mLongs.size()) {
1039 mLongs.add(new long[LONGS_SIZE]);
1040 }
1041 in.readLongArray(mLongs.get(i));
1042 }
1043 long[] longs = new long[LONGS_SIZE];
1044 mNextLong = NEXTLONG;
1045 for (int i=0; i<NEXTLONG; i++) {
1046 longs[i] = in.readLong();
Dianne Hackborn169c8032013-07-03 14:42:22 -07001047 if (DEBUG) Slog.d(TAG, "Reading last long #" + i + ": " + longs[i]);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001048 }
1049 mLongs.add(longs);
1050
1051 in.readLongArray(mMemFactorDurations);
1052
1053 int NPROC = in.readInt();
1054 if (NPROC < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001055 mReadError = "bad process count: " + NPROC;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001056 return;
1057 }
1058 while (NPROC > 0) {
1059 NPROC--;
1060 String procName = in.readString();
1061 if (procName == null) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001062 mReadError = "bad process name";
Dianne Hackborn904a8572013-06-28 18:12:31 -07001063 return;
1064 }
1065 int NUID = in.readInt();
1066 if (NUID < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001067 mReadError = "bad uid count: " + NUID;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001068 return;
1069 }
1070 while (NUID > 0) {
1071 NUID--;
1072 int uid = in.readInt();
1073 if (uid < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001074 mReadError = "bad uid: " + uid;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001075 return;
1076 }
1077 String pkgName = in.readString();
1078 if (pkgName == null) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001079 mReadError = "bad process package name";
Dianne Hackborn904a8572013-06-28 18:12:31 -07001080 return;
1081 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001082 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
1083 if (proc != null) {
1084 if (!proc.readFromParcel(in, false)) {
1085 return;
1086 }
1087 } else {
1088 proc = new ProcessState(this, pkgName, uid, procName);
1089 if (!proc.readFromParcel(in, true)) {
1090 return;
1091 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001092 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001093 if (DEBUG) Slog.d(TAG, "Adding process: " + procName + " " + uid + " " + proc);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001094 mProcesses.put(procName, uid, proc);
1095 }
1096 }
1097
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001098 if (DEBUG) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
1099
Dianne Hackborn904a8572013-06-28 18:12:31 -07001100 int NPKG = in.readInt();
1101 if (NPKG < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001102 mReadError = "bad package count: " + NPKG;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001103 return;
1104 }
1105 while (NPKG > 0) {
1106 NPKG--;
1107 String pkgName = in.readString();
1108 if (pkgName == null) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001109 mReadError = "bad package name";
Dianne Hackborn904a8572013-06-28 18:12:31 -07001110 return;
1111 }
1112 int NUID = in.readInt();
1113 if (NUID < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001114 mReadError = "bad uid count: " + NUID;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001115 return;
1116 }
1117 while (NUID > 0) {
1118 NUID--;
1119 int uid = in.readInt();
1120 if (uid < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001121 mReadError = "bad uid: " + uid;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001122 return;
1123 }
1124 PackageState pkgState = new PackageState(uid);
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001125 mPackages.put(pkgName, uid, pkgState);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001126 int NPROCS = in.readInt();
1127 if (NPROCS < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001128 mReadError = "bad package process count: " + NPROCS;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001129 return;
1130 }
1131 while (NPROCS > 0) {
1132 NPROCS--;
1133 String procName = in.readString();
1134 if (procName == null) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001135 mReadError = "bad package process name";
Dianne Hackborn904a8572013-06-28 18:12:31 -07001136 return;
1137 }
1138 int hasProc = in.readInt();
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001139 if (DEBUG) Slog.d(TAG, "Reading package " + pkgName + " " + uid
1140 + " process " + procName + " hasProc=" + hasProc);
Dianne Hackborn169c8032013-07-03 14:42:22 -07001141 ProcessState commonProc = mProcesses.get(procName, uid);
1142 if (DEBUG) Slog.d(TAG, "Got common proc " + procName + " " + uid
1143 + ": " + commonProc);
1144 if (commonProc == null) {
1145 mReadError = "no common proc: " + procName;
1146 return;
1147 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001148 if (hasProc != 0) {
1149 // The process for this package is unique to the package; we
1150 // need to load it. We don't need to do anything about it if
1151 // it is not unique because if someone later looks for it
1152 // they will find and use it from the global procs.
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001153 ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
1154 if (proc != null) {
1155 if (!proc.readFromParcel(in, false)) {
1156 return;
1157 }
1158 } else {
1159 proc = new ProcessState(commonProc, pkgName, uid, procName, 0);
1160 if (!proc.readFromParcel(in, true)) {
1161 return;
1162 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001163 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001164 if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " process: "
1165 + procName + " " + uid + " " + proc);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001166 pkgState.mProcesses.put(procName, proc);
Dianne Hackborn169c8032013-07-03 14:42:22 -07001167 } else {
1168 if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " process: "
1169 + procName + " " + uid + " " + commonProc);
1170 pkgState.mProcesses.put(procName, commonProc);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001171 }
1172 }
1173 int NSRVS = in.readInt();
1174 if (NSRVS < 0) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001175 mReadError = "bad package service count: " + NSRVS;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001176 return;
1177 }
1178 while (NSRVS > 0) {
1179 NSRVS--;
1180 String serviceName = in.readString();
1181 if (serviceName == null) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001182 mReadError = "bad package service name";
Dianne Hackborn904a8572013-06-28 18:12:31 -07001183 return;
1184 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001185 ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
1186 if (serv == null) {
1187 serv = new ServiceState();
1188 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001189 if (!serv.readFromParcel(in)) {
1190 return;
1191 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001192 if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " service: "
1193 + serviceName + " " + uid + " " + serv);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001194 pkgState.mServices.put(serviceName, serv);
1195 }
1196 }
1197 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001198
1199 if (DEBUG) Slog.d(TAG, "Successfully read procstats!");
Dianne Hackborn904a8572013-06-28 18:12:31 -07001200 }
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001201
1202 int addLongData(int index, int type, int num) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07001203 int tableLen = mAddLongTable != null ? mAddLongTable.length : 0;
1204 if (mAddLongTableSize >= tableLen) {
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001205 int newSize = ArrayUtils.idealIntArraySize(tableLen + 1);
1206 int[] newTable = new int[newSize];
1207 if (tableLen > 0) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07001208 System.arraycopy(mAddLongTable, 0, newTable, 0, tableLen);
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001209 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001210 mAddLongTable = newTable;
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001211 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001212 if (mAddLongTableSize > 0 && mAddLongTableSize - index != 0) {
1213 System.arraycopy(mAddLongTable, index, mAddLongTable, index + 1,
1214 mAddLongTableSize - index);
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001215 }
1216 int off = allocLongData(num);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001217 mAddLongTable[index] = type | off;
1218 mAddLongTableSize++;
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001219 return off;
1220 }
1221
1222 int allocLongData(int num) {
1223 int whichLongs = mLongs.size()-1;
1224 long[] longs = mLongs.get(whichLongs);
1225 if (mNextLong + num > longs.length) {
1226 longs = new long[LONGS_SIZE];
1227 mLongs.add(longs);
1228 whichLongs++;
1229 mNextLong = 0;
1230 }
1231 int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
1232 mNextLong += num;
1233 return off;
1234 }
1235
Dianne Hackborn904a8572013-06-28 18:12:31 -07001236 boolean validateLongOffset(int off) {
1237 int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK;
1238 if (arr >= mLongs.size()) {
1239 return false;
1240 }
1241 int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
1242 if (idx >= LONGS_SIZE) {
1243 return false;
1244 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07001245 if (DEBUG) Slog.d(TAG, "Validated long " + printLongOffset(off)
1246 + ": " + getLong(off, 0));
Dianne Hackborn904a8572013-06-28 18:12:31 -07001247 return true;
1248 }
1249
Dianne Hackborn169c8032013-07-03 14:42:22 -07001250 static String printLongOffset(int off) {
1251 StringBuilder sb = new StringBuilder(16);
1252 sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1253 sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK);
1254 sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK);
1255 return sb.toString();
1256 }
1257
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001258 void setLong(int off, int index, long value) {
1259 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1260 longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
1261 }
1262
1263 long getLong(int off, int index) {
1264 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1265 return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
1266 }
1267
1268 static int binarySearch(int[] array, int size, int value) {
1269 int lo = 0;
1270 int hi = size - 1;
1271
1272 while (lo <= hi) {
1273 int mid = (lo + hi) >>> 1;
1274 int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
1275
1276 if (midVal < value) {
1277 lo = mid + 1;
1278 } else if (midVal > value) {
1279 hi = mid - 1;
1280 } else {
1281 return mid; // value found
1282 }
1283 }
1284 return ~lo; // value not present
1285 }
1286
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001287 PackageState getPackageStateLocked(String packageName, int uid) {
1288 PackageState as = mPackages.get(packageName, uid);
1289 if (as != null) {
1290 return as;
1291 }
1292 as = new PackageState(uid);
1293 mPackages.put(packageName, uid, as);
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001294 return as;
1295 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001296
1297 ProcessState getProcessStateLocked(String packageName, int uid, String processName) {
1298 final PackageState pkgState = getPackageStateLocked(packageName, uid);
1299 ProcessState ps = pkgState.mProcesses.get(processName);
1300 if (ps != null) {
1301 return ps;
1302 }
1303 ProcessState commonProc = mProcesses.get(processName, uid);
1304 if (commonProc == null) {
1305 commonProc = new ProcessState(this, packageName, uid, processName);
1306 mProcesses.put(processName, uid, commonProc);
1307 }
1308 if (!commonProc.mMultiPackage) {
1309 if (packageName.equals(commonProc.mPackage)) {
1310 // This common process is not in use by multiple packages, and
1311 // is for the calling package, so we can just use it directly.
1312 ps = commonProc;
1313 } else {
1314 // This common process has not been in use by multiple packages,
1315 // but it was created for a different package than the caller.
1316 // We need to convert it to a multi-package process.
1317 commonProc.mMultiPackage = true;
1318 // The original package it was created for now needs to point
1319 // to its own copy.
1320 long now = SystemClock.uptimeMillis();
Dianne Hackborn169c8032013-07-03 14:42:22 -07001321 pkgState.mProcesses.put(commonProc.mName, commonProc.clone(
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001322 commonProc.mPackage, now));
1323 ps = new ProcessState(commonProc, packageName, uid, processName, now);
1324 }
1325 } else {
1326 // The common process is for multiple packages, we need to create a
1327 // separate object for the per-package data.
1328 ps = new ProcessState(commonProc, packageName, uid, processName,
1329 SystemClock.uptimeMillis());
1330 }
1331 pkgState.mProcesses.put(processName, ps);
1332 return ps;
1333 }
1334
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001335 void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpAll) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07001336 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
1337 boolean printedHeader = false;
1338 for (int ip=0; ip<pkgMap.size(); ip++) {
1339 String pkgName = pkgMap.keyAt(ip);
1340 if (reqPackage != null && !reqPackage.equals(pkgName)) {
1341 continue;
1342 }
1343 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
1344 for (int iu=0; iu<uids.size(); iu++) {
1345 int uid = uids.keyAt(iu);
1346 PackageState pkgState = uids.valueAt(iu);
1347 final int NPROCS = pkgState.mProcesses.size();
1348 final int NSRVS = pkgState.mServices.size();
1349 if (NPROCS > 0 || NSRVS > 0) {
1350 if (!printedHeader) {
1351 pw.println("Per-Package Process Stats:");
1352 printedHeader = true;
1353 }
1354 pw.print(" * "); pw.print(pkgName); pw.print(" / ");
1355 UserHandle.formatUid(pw, uid); pw.println(":");
1356 }
1357 for (int iproc=0; iproc<NPROCS; iproc++) {
1358 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1359 pw.print(" Process ");
1360 pw.print(pkgState.mProcesses.keyAt(iproc));
1361 pw.print(" (");
1362 pw.print(proc.mDurationsTableSize);
1363 pw.print(" entries)");
1364 pw.println(":");
1365 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1366 ALL_PROC_STATES, now);
1367 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1368 ALL_PROC_STATES);
1369 }
1370 for (int isvc=0; isvc<NSRVS; isvc++) {
1371 pw.print(" Service ");
1372 pw.print(pkgState.mServices.keyAt(isvc));
1373 pw.println(":");
1374 ServiceState svc = pkgState.mServices.valueAt(isvc);
1375 if (svc.mStartedCount != 0) {
1376 pw.print(" Started op count "); pw.print(svc.mStartedCount);
1377 pw.println(":");
1378 dumpSingleTime(pw, " ", svc.mStartedDurations, svc.mStartedState,
1379 svc.mStartedStartTime, now);
1380 }
1381 if (svc.mBoundCount != 0) {
1382 pw.print(" Bound op count "); pw.print(svc.mBoundCount);
1383 pw.println(":");
1384 dumpSingleTime(pw, " ", svc.mBoundDurations, svc.mBoundState,
1385 svc.mBoundStartTime, now);
1386 }
1387 if (svc.mExecCount != 0) {
1388 pw.print(" Executing op count "); pw.print(svc.mExecCount);
1389 pw.println(":");
1390 dumpSingleTime(pw, " ", svc.mExecDurations, svc.mExecState,
1391 svc.mExecStartTime, now);
1392 }
1393 }
1394 }
1395 }
1396
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001397 if (reqPackage == null) {
1398 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1399 printedHeader = false;
1400 for (int ip=0; ip<procMap.size(); ip++) {
1401 String procName = procMap.keyAt(ip);
1402 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1403 for (int iu=0; iu<uids.size(); iu++) {
1404 int uid = uids.keyAt(iu);
1405 ProcessState proc = uids.valueAt(iu);
1406 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
1407 && proc.mPssTableSize == 0) {
1408 continue;
1409 }
1410 if (!printedHeader) {
1411 pw.println("Process Stats:");
1412 printedHeader = true;
1413 }
1414 pw.print(" * "); pw.print(procName); pw.print(" / ");
1415 UserHandle.formatUid(pw, uid);
1416 pw.print(" ("); pw.print(proc.mDurationsTableSize);
1417 pw.print(" entries)"); pw.println(":");
1418 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1419 ALL_PROC_STATES, now);
1420 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1421 ALL_PROC_STATES);
1422 }
1423 }
1424
1425 pw.println();
1426 pw.println("Summary:");
1427 dumpSummaryLocked(pw, reqPackage, now);
1428 }
1429
1430 if (dumpAll) {
1431 pw.println();
1432 pw.println("Internal state:");
1433 pw.print(" mFile="); pw.println(mFile.getBaseFile());
1434 pw.print(" Num long arrays: "); pw.println(mLongs.size());
1435 pw.print(" Next long entry: "); pw.println(mNextLong);
1436 pw.print(" mRunning="); pw.println(mRunning);
1437 }
1438 }
1439
1440 void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now) {
1441 dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
Dianne Hackbornc8230512013-07-13 21:32:12 -07001442 new int[] { STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
1443 STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT,
1444 STATE_SERVICE, STATE_RECEIVER, STATE_HOME, STATE_LAST_ACTIVITY },
Dianne Hackborn904a8572013-06-28 18:12:31 -07001445 now, reqPackage);
1446 pw.println();
1447 pw.println("Run time Stats:");
1448 dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now);
Dianne Hackborn169c8032013-07-03 14:42:22 -07001449 pw.println();
1450 pw.print(" Start time: ");
1451 pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
1452 pw.println();
1453 pw.print(" Total elapsed time: ");
1454 TimeUtils.formatDuration(
1455 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001456 - mTimePeriodStartRealtime, pw);
Dianne Hackbornc8230512013-07-13 21:32:12 -07001457 if ((mFlags&FLAG_COMPLETE) != 0) pw.print(" (complete)");
1458 else if ((mFlags&FLAG_SHUTDOWN) != 0) pw.print(" (shutdown)");
1459 else pw.print(" (partial)");
Dianne Hackborn169c8032013-07-03 14:42:22 -07001460 pw.println();
Dianne Hackborn13ac0412013-06-25 19:34:49 -07001461 }
1462
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001463 void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
Dianne Hackborn904a8572013-06-28 18:12:31 -07001464 int[] screenStates, int[] memStates, int[] procStates, long now, String reqPackage) {
1465 ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
1466 procStates, now, reqPackage);
1467 if (procs.size() > 0) {
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001468 if (header != null) {
1469 pw.println();
1470 pw.println(header);
1471 }
1472 dumpProcessSummary(pw, prefix, procs, screenStates, memStates, procStates, now);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001473 }
1474 }
1475
1476 ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
1477 int[] procStates, long now, String reqPackage) {
1478 ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
1479 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
1480 for (int ip=0; ip<pkgMap.size(); ip++) {
1481 if (reqPackage != null && !reqPackage.equals(pkgMap.keyAt(ip))) {
1482 continue;
1483 }
1484 SparseArray<PackageState> procs = pkgMap.valueAt(ip);
1485 for (int iu=0; iu<procs.size(); iu++) {
1486 PackageState state = procs.valueAt(iu);
1487 for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
1488 ProcessState proc = state.mProcesses.valueAt(iproc);
1489 foundProcs.add(proc.mCommonProcess);
1490 }
1491 }
1492 }
1493 ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
1494 for (int i=0; i<foundProcs.size(); i++) {
1495 ProcessState proc = foundProcs.valueAt(i);
1496 if (computeProcessTimeLocked(proc, screenStates, memStates,
1497 procStates, now) > 0) {
1498 outProcs.add(proc);
1499 }
1500 }
1501 Collections.sort(outProcs, new Comparator<ProcessState>() {
1502 @Override
1503 public int compare(ProcessState lhs, ProcessState rhs) {
1504 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
1505 return -1;
1506 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
1507 return 1;
1508 }
1509 return 0;
1510 }
1511 });
1512 return outProcs;
1513 }
1514
Dianne Hackborn169c8032013-07-03 14:42:22 -07001515 String collapseString(String pkgName, String itemName) {
1516 if (itemName.startsWith(pkgName)) {
1517 final int ITEMLEN = itemName.length();
1518 final int PKGLEN = pkgName.length();
1519 if (ITEMLEN == PKGLEN) {
1520 return "";
1521 } else if (ITEMLEN >= PKGLEN) {
1522 if (itemName.charAt(PKGLEN) == '.') {
1523 return itemName.substring(PKGLEN);
1524 }
1525 }
1526 }
1527 return itemName;
1528 }
1529
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07001530 void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07001531 final long now = SystemClock.uptimeMillis();
1532 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
Dianne Hackbornc8230512013-07-13 21:32:12 -07001533 pw.println("vers,2");
Dianne Hackborn169c8032013-07-03 14:42:22 -07001534 pw.print("period,"); pw.print(mTimePeriodStartClockStr);
1535 pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
1536 pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
Dianne Hackbornc8230512013-07-13 21:32:12 -07001537 if ((mFlags&FLAG_COMPLETE) != 0) pw.print(",complete");
1538 else if ((mFlags&FLAG_SHUTDOWN) != 0) pw.print(",shutdown");
1539 else pw.print(",partial");
Dianne Hackborn169c8032013-07-03 14:42:22 -07001540 pw.println();
Dianne Hackborn904a8572013-06-28 18:12:31 -07001541 for (int ip=0; ip<pkgMap.size(); ip++) {
1542 String pkgName = pkgMap.keyAt(ip);
1543 if (reqPackage != null && !reqPackage.equals(pkgName)) {
1544 continue;
1545 }
1546 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
1547 for (int iu=0; iu<uids.size(); iu++) {
1548 int uid = uids.keyAt(iu);
1549 PackageState pkgState = uids.valueAt(iu);
1550 final int NPROCS = pkgState.mProcesses.size();
1551 final int NSRVS = pkgState.mServices.size();
1552 for (int iproc=0; iproc<NPROCS; iproc++) {
1553 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1554 pw.print("pkgproc,");
1555 pw.print(pkgName);
1556 pw.print(",");
1557 pw.print(uid);
1558 pw.print(",");
Dianne Hackborn169c8032013-07-03 14:42:22 -07001559 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
Dianne Hackborn904a8572013-06-28 18:12:31 -07001560 dumpAllProcessStateCheckin(pw, proc, now);
1561 pw.println();
1562 if (proc.mPssTableSize > 0) {
1563 pw.print("pkgpss,");
1564 pw.print(pkgName);
1565 pw.print(",");
1566 pw.print(uid);
1567 pw.print(",");
Dianne Hackborn169c8032013-07-03 14:42:22 -07001568 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
Dianne Hackborn904a8572013-06-28 18:12:31 -07001569 dumpAllProcessPssCheckin(pw, proc);
1570 pw.println();
1571 }
1572 if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0) {
1573 pw.print("pkgkills,");
1574 pw.print(pkgName);
1575 pw.print(",");
1576 pw.print(uid);
1577 pw.print(",");
Dianne Hackborn169c8032013-07-03 14:42:22 -07001578 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
Dianne Hackborn904a8572013-06-28 18:12:31 -07001579 pw.print(",");
1580 pw.print(proc.mNumExcessiveWake);
1581 pw.print(",");
1582 pw.print(proc.mNumExcessiveCpu);
1583 pw.println();
1584 }
1585 }
1586 for (int isvc=0; isvc<NSRVS; isvc++) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001587 String serviceName = collapseString(pkgName,
1588 pkgState.mServices.keyAt(isvc));
Dianne Hackborn904a8572013-06-28 18:12:31 -07001589 ServiceState svc = pkgState.mServices.valueAt(isvc);
1590 dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, serviceName,
1591 svc, svc.mStartedCount, svc.mStartedDurations, svc.mStartedState,
1592 svc.mStartedStartTime, now);
1593 dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, serviceName,
1594 svc, svc.mBoundCount, svc.mBoundDurations, svc.mBoundState,
1595 svc.mBoundStartTime, now);
1596 dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, serviceName,
1597 svc, svc.mExecCount, svc.mExecDurations, svc.mExecState,
1598 svc.mExecStartTime, now);
1599 }
1600 }
1601 }
1602
1603 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1604 for (int ip=0; ip<procMap.size(); ip++) {
1605 String procName = procMap.keyAt(ip);
1606 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1607 for (int iu=0; iu<uids.size(); iu++) {
1608 int uid = uids.keyAt(iu);
1609 ProcessState procState = uids.valueAt(iu);
1610 if (procState.mDurationsTableSize > 0) {
1611 pw.print("proc,");
1612 pw.print(procName);
1613 pw.print(",");
1614 pw.print(uid);
1615 dumpAllProcessStateCheckin(pw, procState, now);
1616 pw.println();
1617 }
1618 if (procState.mPssTableSize > 0) {
1619 pw.print("pss,");
1620 pw.print(procName);
1621 pw.print(",");
1622 pw.print(uid);
1623 dumpAllProcessPssCheckin(pw, procState);
1624 pw.println();
1625 }
1626 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0) {
1627 pw.print("kills,");
1628 pw.print(procName);
1629 pw.print(",");
1630 pw.print(uid);
1631 pw.print(",");
1632 pw.print(procState.mNumExcessiveWake);
1633 pw.print(",");
1634 pw.print(procState.mNumExcessiveCpu);
1635 pw.println();
1636 }
1637 }
1638 }
1639 pw.print("total");
1640 dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor,
1641 mStartTime, now);
1642 pw.println();
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001643 }
1644 }
1645
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001646 public ProcessTracker(Object lock, File file) {
1647 mLock = lock;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001648 mBaseDir = file;
1649 mBaseDir.mkdirs();
Dianne Hackborn169c8032013-07-03 14:42:22 -07001650 mState = new State(mBaseDir, this);
1651 mState.mRunning = true;
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001652 }
1653
1654 public ProcessState getProcessStateLocked(String packageName, int uid, String processName) {
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001655 return mState.getProcessStateLocked(packageName, uid, processName);
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -07001656 }
1657
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001658 public ServiceState getServiceStateLocked(String packageName, int uid, String className) {
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001659 final PackageState as = mState.getPackageStateLocked(packageName, uid);
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001660 ServiceState ss = as.mServices.get(className);
1661 if (ss != null) {
1662 return ss;
1663 }
1664 ss = new ServiceState();
1665 as.mServices.put(className, ss);
1666 return ss;
1667 }
1668
Dianne Hackborn904a8572013-06-28 18:12:31 -07001669 public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001670 if (screenOn) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001671 memFactor += ADJ_SCREEN_ON;
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001672 }
1673 if (memFactor != mState.mMemFactor) {
1674 if (mState.mMemFactor != STATE_NOTHING) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001675 mState.mMemFactorDurations[mState.mMemFactor] += now - mState.mStartTime;
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001676 }
1677 mState.mMemFactor = memFactor;
1678 mState.mStartTime = now;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001679 ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
1680 for (int i=0; i<pmap.size(); i++) {
1681 SparseArray<PackageState> uids = pmap.valueAt(i);
1682 for (int j=0; j<uids.size(); j++) {
1683 PackageState pkg = uids.valueAt(j);
1684 ArrayMap<String, ServiceState> services = pkg.mServices;
1685 for (int k=0; k<services.size(); k++) {
1686 ServiceState service = services.valueAt(k);
1687 if (service.mStartedState != STATE_NOTHING) {
1688 service.setStarted(true, memFactor, now);
1689 }
1690 if (service.mBoundState != STATE_NOTHING) {
1691 service.setBound(true, memFactor, now);
1692 }
1693 }
1694 }
1695 }
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001696 return true;
1697 }
1698 return false;
1699 }
1700
Dianne Hackborn904a8572013-06-28 18:12:31 -07001701 public int getMemFactorLocked() {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001702 return mState.mMemFactor != STATE_NOTHING ? mState.mMemFactor : 0;
1703 }
1704
Dianne Hackborn904a8572013-06-28 18:12:31 -07001705 public void readLocked() {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001706 mState.readLocked();
Dianne Hackborn904a8572013-06-28 18:12:31 -07001707 }
1708
1709 public boolean shouldWriteNowLocked(long now) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001710 if (now > (mState.mLastWriteTime+WRITE_PERIOD)) {
1711 if (SystemClock.elapsedRealtime() > (mState.mTimePeriodStartRealtime+COMMIT_PERIOD)) {
1712 mCommitPending = true;
Dianne Hackbornc8230512013-07-13 21:32:12 -07001713 mState.mFlags |= State.FLAG_COMPLETE;
Dianne Hackborn169c8032013-07-03 14:42:22 -07001714 }
1715 return true;
1716 }
1717 return false;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001718 }
1719
1720 public void shutdownLocked() {
1721 Slog.w(TAG, "Writing process stats before shutdown...");
Dianne Hackbornc8230512013-07-13 21:32:12 -07001722 mState.mFlags |= State.FLAG_SHUTDOWN;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001723 writeStateSyncLocked();
1724 mShuttingDown = true;
1725 }
1726
1727 public void writeStateAsyncLocked() {
1728 writeStateLocked(false);
1729 }
1730
1731 public void writeStateSyncLocked() {
1732 writeStateLocked(true);
1733 }
1734
1735 private void writeStateLocked(boolean sync) {
1736 if (mShuttingDown) {
1737 return;
1738 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07001739 boolean commitPending = mCommitPending;
1740 mCommitPending = false;
1741 mState.writeStateLocked(sync, commitPending);
Dianne Hackborn904a8572013-06-28 18:12:31 -07001742 }
1743
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001744 private ArrayList<String> getCommittedFiles(int minNum, boolean inclAll) {
Dianne Hackborn169c8032013-07-03 14:42:22 -07001745 File[] files = mBaseDir.listFiles();
1746 if (files == null || files.length <= minNum) {
1747 return null;
Dianne Hackborn904a8572013-06-28 18:12:31 -07001748 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07001749 ArrayList<String> filesArray = new ArrayList<String>(files.length);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001750 String currentFile = mState.mFile.getBaseFile().getPath();
Dianne Hackborn169c8032013-07-03 14:42:22 -07001751 if (DEBUG) Slog.d(TAG, "Collecting " + files.length + " files except: " + currentFile);
1752 for (int i=0; i<files.length; i++) {
1753 File file = files[i];
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001754 String fileStr = file.getPath();
1755 if (DEBUG) Slog.d(TAG, "Collecting: " + fileStr);
1756 if (!inclAll && fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX)) {
1757 if (DEBUG) Slog.d(TAG, "Skipping: already checked in");
1758 continue;
Dianne Hackborn169c8032013-07-03 14:42:22 -07001759 }
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001760 if (fileStr.equals(currentFile)) {
1761 if (DEBUG) Slog.d(TAG, "Skipping: current stats");
1762 continue;
1763 }
1764 filesArray.add(fileStr);
Dianne Hackborn169c8032013-07-03 14:42:22 -07001765 }
1766 Collections.sort(filesArray);
1767 return filesArray;
1768 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07001769
Dianne Hackborn169c8032013-07-03 14:42:22 -07001770 public void trimHistoricStatesWriteLocked() {
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001771 ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, true);
Dianne Hackborn169c8032013-07-03 14:42:22 -07001772 if (filesArray == null) {
1773 return;
1774 }
1775 while (filesArray.size() > MAX_HISTORIC_STATES) {
1776 String file = filesArray.remove(0);
1777 Slog.i(TAG, "Pruning old procstats: " + file);
1778 (new File(file)).delete();
Dianne Hackborn904a8572013-06-28 18:12:31 -07001779 }
1780 }
1781
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001782 static private void printScreenLabel(PrintWriter pw, int offset) {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001783 switch (offset) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001784 case ADJ_NOTHING:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001785 pw.print(" ");
1786 break;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001787 case ADJ_SCREEN_OFF:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001788 pw.print("Screen Off / ");
1789 break;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001790 case ADJ_SCREEN_ON:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001791 pw.print("Screen On / ");
1792 break;
1793 default:
1794 pw.print("?????????? / ");
1795 break;
1796 }
1797 }
1798
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001799 static private void printScreenLabelCsv(PrintWriter pw, int offset) {
1800 switch (offset) {
1801 case ADJ_NOTHING:
1802 break;
1803 case ADJ_SCREEN_OFF:
1804 pw.print(ADJ_SCREEN_NAMES_CSV[0]);
1805 break;
1806 case ADJ_SCREEN_ON:
1807 pw.print(ADJ_SCREEN_NAMES_CSV[1]);
1808 break;
1809 default:
1810 pw.print("???");
1811 break;
1812 }
1813 }
1814
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001815 static private void printMemLabel(PrintWriter pw, int offset) {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001816 switch (offset) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001817 case ADJ_NOTHING:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001818 pw.print(" ");
1819 break;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001820 case ADJ_MEM_FACTOR_NORMAL:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001821 pw.print("Norm / ");
1822 break;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001823 case ADJ_MEM_FACTOR_MODERATE:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001824 pw.print("Mod / ");
1825 break;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001826 case ADJ_MEM_FACTOR_LOW:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001827 pw.print("Low / ");
1828 break;
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001829 case ADJ_MEM_FACTOR_CRITICAL:
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001830 pw.print("Crit / ");
1831 break;
1832 default:
1833 pw.print("???? / ");
1834 break;
1835 }
1836 }
1837
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001838 static private void printMemLabelCsv(PrintWriter pw, int offset) {
1839 if (offset >= ADJ_MEM_FACTOR_NORMAL) {
1840 if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
1841 pw.print(ADJ_MEM_NAMES_CSV[offset]);
1842 } else {
1843 pw.print("???");
1844 }
1845 }
1846 }
1847
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001848 static void dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
1849 int curState, long curStartTime, long now) {
1850 long totalTime = 0;
1851 int printedScreen = -1;
1852 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
1853 int printedMem = -1;
1854 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
1855 int state = imem+iscreen;
1856 long time = durations[state];
1857 String running = "";
1858 if (curState == state) {
1859 time += now - curStartTime;
1860 running = " (running)";
1861 }
1862 if (time != 0) {
1863 pw.print(prefix);
1864 printScreenLabel(pw, printedScreen != iscreen
1865 ? iscreen : STATE_NOTHING);
1866 printedScreen = iscreen;
1867 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
1868 printedMem = imem;
1869 TimeUtils.formatDuration(time, pw); pw.println(running);
1870 totalTime += time;
1871 }
1872 }
1873 }
1874 if (totalTime != 0) {
1875 pw.print(prefix);
1876 printScreenLabel(pw, STATE_NOTHING);
1877 pw.print("TOTAL: ");
1878 TimeUtils.formatDuration(totalTime, pw);
1879 pw.println();
1880 }
1881 }
1882
Dianne Hackborncfc837f2013-06-27 18:32:07 -07001883 static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001884 int curState, long curStartTime, long now) {
1885 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
1886 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
1887 int state = imem+iscreen;
1888 long time = durations[state];
1889 if (curState == state) {
1890 time += now - curStartTime;
1891 }
Dianne Hackborncfc837f2013-06-27 18:32:07 -07001892 if (time != 0) {
1893 printAdjTagAndValue(pw, state, time);
1894 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001895 }
1896 }
1897 }
1898
1899 static void dumpServiceTimeCheckin(PrintWriter pw, String label, String packageName,
1900 int uid, String serviceName, ServiceState svc, int opCount, long[] durations,
1901 int curState, long curStartTime, long now) {
1902 if (opCount <= 0) {
1903 return;
1904 }
1905 pw.print(label);
1906 pw.print(",");
1907 pw.print(packageName);
1908 pw.print(",");
1909 pw.print(uid);
1910 pw.print(",");
1911 pw.print(serviceName);
1912 pw.print(opCount);
Dianne Hackborncfc837f2013-06-27 18:32:07 -07001913 dumpAdjTimesCheckin(pw, ",", durations, curState, curStartTime, now);
Dianne Hackborna17c0f52013-06-20 18:59:11 -07001914 pw.println();
1915 }
1916
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001917 static final class ProcessDataCollection {
1918 final int[] screenStates;
1919 final int[] memStates;
1920 final int[] procStates;
1921
1922 long totalTime;
1923 long numPss;
1924 long minPss;
1925 long avgPss;
1926 long maxPss;
Dianne Hackbornc8230512013-07-13 21:32:12 -07001927 long minUss;
1928 long avgUss;
1929 long maxUss;
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001930
1931 ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
1932 screenStates = _screenStates;
1933 memStates = _memStates;
1934 procStates = _procStates;
1935 }
1936
1937 void print(PrintWriter pw, boolean full) {
1938 TimeUtils.formatDuration(totalTime, pw);
1939 if (numPss > 0) {
1940 pw.print(" (");
1941 printSizeValue(pw, minPss * 1024);
1942 pw.print("-");
1943 printSizeValue(pw, avgPss * 1024);
1944 pw.print("-");
1945 printSizeValue(pw, maxPss * 1024);
Dianne Hackbornc8230512013-07-13 21:32:12 -07001946 pw.print("/");
1947 printSizeValue(pw, minUss * 1024);
1948 pw.print("-");
1949 printSizeValue(pw, avgUss * 1024);
1950 pw.print("-");
1951 printSizeValue(pw, maxUss * 1024);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001952 if (full) {
1953 pw.print(" over ");
1954 pw.print(numPss);
1955 }
1956 pw.print(")");
1957 }
1958 }
1959 }
1960
1961 static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
1962 data.totalTime = 0;
Dianne Hackbornc8230512013-07-13 21:32:12 -07001963 data.numPss = data.minPss = data.avgPss = data.maxPss =
1964 data.minUss = data.avgUss = data.maxUss = 0;
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001965 for (int is=0; is<data.screenStates.length; is++) {
1966 for (int im=0; im<data.memStates.length; im++) {
1967 for (int ip=0; ip<data.procStates.length; ip++) {
1968 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
1969 + data.procStates[ip];
1970 data.totalTime += proc.getDuration(bucket, now);
1971 long samples = proc.getPssSampleCount(bucket);
1972 if (samples > 0) {
1973 long minPss = proc.getPssMinimum(bucket);
1974 long avgPss = proc.getPssAverage(bucket);
1975 long maxPss = proc.getPssMaximum(bucket);
Dianne Hackbornc8230512013-07-13 21:32:12 -07001976 long minUss = proc.getPssUssMinimum(bucket);
1977 long avgUss = proc.getPssUssAverage(bucket);
1978 long maxUss = proc.getPssUssMaximum(bucket);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001979 if (data.numPss == 0) {
1980 data.minPss = minPss;
1981 data.avgPss = avgPss;
1982 data.maxPss = maxPss;
Dianne Hackbornc8230512013-07-13 21:32:12 -07001983 data.minUss = minUss;
1984 data.avgUss = avgUss;
1985 data.maxUss = maxUss;
Dianne Hackborna4cc2052013-07-08 17:31:25 -07001986 } else {
1987 if (minPss < data.minPss) {
1988 data.minPss = minPss;
1989 }
1990 data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
1991 + (avgPss*(double)samples)) / (data.numPss+samples) );
1992 if (maxPss > data.maxPss) {
1993 data.maxPss = maxPss;
1994 }
Dianne Hackbornc8230512013-07-13 21:32:12 -07001995 if (minUss < data.minUss) {
1996 data.minUss = minUss;
1997 }
1998 data.avgUss = (long)( ((data.avgUss*(double)data.numPss)
1999 + (avgUss*(double)samples)) / (data.numPss+samples) );
2000 if (maxUss > data.maxUss) {
2001 data.maxUss = maxUss;
2002 }
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002003 }
2004 data.numPss += samples;
2005 }
2006 }
2007 }
2008 }
2009 }
2010
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002011 static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002012 int[] procStates, long now) {
2013 long totalTime = 0;
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002014 /*
2015 for (int i=0; i<proc.mDurationsTableSize; i++) {
2016 int val = proc.mDurationsTable[i];
2017 totalTime += proc.mState.getLong(val, 0);
2018 if ((val&0xff) == proc.mCurState) {
2019 totalTime += now - proc.mStartTime;
2020 }
2021 }
2022 */
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002023 for (int is=0; is<screenStates.length; is++) {
2024 for (int im=0; im<memStates.length; im++) {
2025 for (int ip=0; ip<procStates.length; ip++) {
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002026 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002027 + procStates[ip];
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002028 totalTime += proc.getDuration(bucket, now);
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002029 }
2030 }
2031 }
2032 proc.mTmpTotalTime = totalTime;
2033 return totalTime;
2034 }
2035
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002036 static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc,
2037 int[] screenStates, int[] memStates, int[] procStates, long now) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002038 long totalTime = 0;
2039 int printedScreen = -1;
2040 for (int is=0; is<screenStates.length; is++) {
2041 int printedMem = -1;
2042 for (int im=0; im<memStates.length; im++) {
2043 for (int ip=0; ip<procStates.length; ip++) {
2044 final int iscreen = screenStates[is];
2045 final int imem = memStates[im];
2046 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002047 long time = proc.getDuration(bucket, now);
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002048 String running = "";
2049 if (proc.mCurState == bucket) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002050 running = " (running)";
2051 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002052 if (time != 0) {
2053 pw.print(prefix);
2054 if (screenStates.length > 1) {
2055 printScreenLabel(pw, printedScreen != iscreen
2056 ? iscreen : STATE_NOTHING);
2057 printedScreen = iscreen;
2058 }
2059 if (memStates.length > 1) {
2060 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
2061 printedMem = imem;
2062 }
2063 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
2064 TimeUtils.formatDuration(time, pw); pw.println(running);
2065 totalTime += time;
2066 }
2067 }
2068 }
2069 }
2070 if (totalTime != 0) {
2071 pw.print(prefix);
2072 if (screenStates.length > 1) {
2073 printScreenLabel(pw, STATE_NOTHING);
2074 }
2075 if (memStates.length > 1) {
2076 printMemLabel(pw, STATE_NOTHING);
2077 }
2078 pw.print("TOTAL : ");
2079 TimeUtils.formatDuration(totalTime, pw);
2080 pw.println();
2081 }
2082 }
2083
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002084 static void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002085 int[] memStates, int[] procStates) {
2086 boolean printedHeader = false;
2087 int printedScreen = -1;
2088 for (int is=0; is<screenStates.length; is++) {
2089 int printedMem = -1;
2090 for (int im=0; im<memStates.length; im++) {
2091 for (int ip=0; ip<procStates.length; ip++) {
2092 final int iscreen = screenStates[is];
2093 final int imem = memStates[im];
2094 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
2095 long count = proc.getPssSampleCount(bucket);
2096 if (count > 0) {
2097 if (!printedHeader) {
2098 pw.print(prefix);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002099 pw.print("PSS/USS (");
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002100 pw.print(proc.mPssTableSize);
Dianne Hackbornb4e12492013-06-26 15:08:19 -07002101 pw.println(" entries):");
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002102 printedHeader = true;
2103 }
2104 pw.print(prefix);
2105 pw.print(" ");
2106 if (screenStates.length > 1) {
2107 printScreenLabel(pw, printedScreen != iscreen
2108 ? iscreen : STATE_NOTHING);
2109 printedScreen = iscreen;
2110 }
2111 if (memStates.length > 1) {
2112 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
2113 printedMem = imem;
2114 }
2115 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
2116 pw.print(count);
2117 pw.print(" samples ");
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002118 printSizeValue(pw, proc.getPssMinimum(bucket) * 1024);
2119 pw.print(" ");
2120 printSizeValue(pw, proc.getPssAverage(bucket) * 1024);
2121 pw.print(" ");
2122 printSizeValue(pw, proc.getPssMaximum(bucket) * 1024);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002123 pw.print(" / ");
2124 printSizeValue(pw, proc.getPssUssMinimum(bucket) * 1024);
2125 pw.print(" ");
2126 printSizeValue(pw, proc.getPssUssAverage(bucket) * 1024);
2127 pw.print(" ");
2128 printSizeValue(pw, proc.getPssUssMaximum(bucket) * 1024);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002129 pw.println();
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002130 }
2131 }
2132 }
2133 }
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002134 if (proc.mNumExcessiveWake != 0) {
2135 pw.print(prefix); pw.print("Killed for excessive wake locks: ");
2136 pw.print(proc.mNumExcessiveWake); pw.println(" times");
2137 }
2138 if (proc.mNumExcessiveCpu != 0) {
2139 pw.print(prefix); pw.print("Killed for excessive CPU use: ");
2140 pw.print(proc.mNumExcessiveCpu); pw.println(" times");
2141 }
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002142 }
2143
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002144 static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002145 int[] memStates, int[] procStates) {
2146 final int NS = screenStates != null ? screenStates.length : 1;
2147 final int NM = memStates != null ? memStates.length : 1;
2148 final int NP = procStates != null ? procStates.length : 1;
2149 for (int is=0; is<NS; is++) {
2150 for (int im=0; im<NM; im++) {
2151 for (int ip=0; ip<NP; ip++) {
2152 pw.print(sep);
2153 boolean printed = false;
2154 if (screenStates != null && screenStates.length > 1) {
2155 printScreenLabelCsv(pw, screenStates[is]);
2156 printed = true;
2157 }
2158 if (memStates != null && memStates.length > 1) {
2159 if (printed) {
2160 pw.print("-");
2161 }
2162 printMemLabelCsv(pw, memStates[im]);
2163 printed = true;
2164 }
2165 if (procStates != null && procStates.length > 1) {
2166 if (printed) {
2167 pw.print("-");
2168 }
2169 pw.print(STATE_NAMES_CSV[procStates[ip]]);
2170 }
2171 }
2172 }
2173 }
2174 }
2175
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002176 static void dumpProcessStateCsv(PrintWriter pw, ProcessState proc,
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002177 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
2178 boolean sepProcStates, int[] procStates, long now) {
2179 final int NSS = sepScreenStates ? screenStates.length : 1;
2180 final int NMS = sepMemStates ? memStates.length : 1;
2181 final int NPS = sepProcStates ? procStates.length : 1;
2182 for (int iss=0; iss<NSS; iss++) {
2183 for (int ims=0; ims<NMS; ims++) {
2184 for (int ips=0; ips<NPS; ips++) {
2185 final int vsscreen = sepScreenStates ? screenStates[iss] : 0;
2186 final int vsmem = sepMemStates ? memStates[ims] : 0;
2187 final int vsproc = sepProcStates ? procStates[ips] : 0;
2188 final int NSA = sepScreenStates ? 1 : screenStates.length;
2189 final int NMA = sepMemStates ? 1 : memStates.length;
2190 final int NPA = sepProcStates ? 1 : procStates.length;
2191 long totalTime = 0;
2192 for (int isa=0; isa<NSA; isa++) {
2193 for (int ima=0; ima<NMA; ima++) {
2194 for (int ipa=0; ipa<NPA; ipa++) {
2195 final int vascreen = sepScreenStates ? 0 : screenStates[isa];
2196 final int vamem = sepMemStates ? 0 : memStates[ima];
2197 final int vaproc = sepProcStates ? 0 : procStates[ipa];
2198 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
2199 * STATE_COUNT) + vsproc + vaproc;
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002200 totalTime += proc.getDuration(bucket, now);
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002201 }
2202 }
2203 }
2204 pw.print(CSV_SEP);
Dianne Hackborne5a9c922013-06-24 15:54:52 -07002205 pw.print(totalTime);
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002206 }
2207 }
2208 }
2209 }
2210
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002211 static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002212 int[] screenStates, int[] memStates, int[] procStates, long now) {
2213 String innerPrefix = prefix + " ";
2214 for (int i=procs.size()-1; i>=0; i--) {
2215 ProcessState proc = procs.get(i);
2216 pw.print(prefix);
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002217 pw.print(proc.mName);
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002218 pw.print(" / ");
2219 UserHandle.formatUid(pw, proc.mUid);
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002220 pw.print(" (");
2221 pw.print(proc.mDurationsTableSize);
2222 pw.print(" entries)");
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002223 pw.println(":");
2224 dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002225 if (proc.mPssTableSize > 0) {
2226 dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates);
2227 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -07002228 }
2229 }
2230
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002231 static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix,
2232 String label, int[] screenStates, int[] memStates, int[] procStates,
2233 long now, boolean full) {
2234 ProcessDataCollection totals = new ProcessDataCollection(screenStates,
2235 memStates, procStates);
2236 computeProcessData(proc, totals, now);
2237 if (totals.totalTime != 0 || totals.numPss != 0) {
2238 if (prefix != null) {
2239 pw.print(prefix);
2240 }
2241 if (label != null) {
2242 pw.print(label);
2243 }
2244 totals.print(pw, full);
2245 if (prefix != null) {
2246 pw.println();
2247 }
2248 }
2249 }
2250
2251 static void dumpProcessSummary(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
2252 int[] screenStates, int[] memStates, int[] procStates, long now) {
2253 for (int i=procs.size()-1; i>=0; i--) {
2254 ProcessState proc = procs.get(i);
2255 pw.print(prefix);
2256 pw.print("* ");
2257 pw.print(proc.mName);
2258 pw.print(" / ");
2259 UserHandle.formatUid(pw, proc.mUid);
2260 pw.println(":");
2261 dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates,
2262 procStates, now, true);
2263 dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates,
Dianne Hackbornc8230512013-07-13 21:32:12 -07002264 new int[] { STATE_PERSISTENT }, now, true);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002265 dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates,
2266 new int[] {STATE_TOP}, now, true);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002267 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Fg: ", screenStates, memStates,
2268 new int[] { STATE_IMPORTANT_FOREGROUND }, now, true);
2269 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Bg: ", screenStates, memStates,
2270 new int[] {STATE_IMPORTANT_BACKGROUND}, now, true);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002271 dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates,
2272 new int[] {STATE_BACKUP}, now, true);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002273 dumpProcessSummaryDetails(pw, proc, prefix, " Heavy Wgt: ", screenStates, memStates,
2274 new int[] {STATE_HEAVY_WEIGHT}, now, true);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002275 dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates,
2276 new int[] {STATE_SERVICE}, now, true);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002277 dumpProcessSummaryDetails(pw, proc, prefix, " Receiver: ", screenStates, memStates,
2278 new int[] {STATE_RECEIVER}, now, true);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002279 dumpProcessSummaryDetails(pw, proc, prefix, " Home: ", screenStates, memStates,
2280 new int[] {STATE_HOME}, now, true);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002281 dumpProcessSummaryDetails(pw, proc, prefix, " Last Act: ", screenStates, memStates,
2282 new int[] {STATE_LAST_ACTIVITY}, now, true);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002283 dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates,
Dianne Hackbornc8230512013-07-13 21:32:12 -07002284 new int[] {STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_ACTIVITY_CLIENT,
2285 STATE_CACHED_EMPTY}, now, true);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002286 }
2287 }
2288
2289 private static void printSizeValue(PrintWriter pw, long number) {
2290 float result = number;
2291 String suffix = "";
2292 if (result > 900) {
2293 suffix = "KB";
2294 result = result / 1024;
2295 }
2296 if (result > 900) {
2297 suffix = "MB";
2298 result = result / 1024;
2299 }
2300 if (result > 900) {
2301 suffix = "GB";
2302 result = result / 1024;
2303 }
2304 if (result > 900) {
2305 suffix = "TB";
2306 result = result / 1024;
2307 }
2308 if (result > 900) {
2309 suffix = "PB";
2310 result = result / 1024;
2311 }
2312 String value;
2313 if (result < 1) {
2314 value = String.format("%.2f", result);
2315 } else if (result < 10) {
Dianne Hackbornc8230512013-07-13 21:32:12 -07002316 value = String.format("%.1f", result);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002317 } else if (result < 100) {
Dianne Hackbornc8230512013-07-13 21:32:12 -07002318 value = String.format("%.0f", result);
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002319 } else {
2320 value = String.format("%.0f", result);
2321 }
2322 pw.print(value);
2323 pw.print(suffix);
2324 }
2325
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002326 static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002327 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
2328 boolean sepProcStates, int[] procStates, long now) {
2329 pw.print("process");
2330 pw.print(CSV_SEP);
2331 pw.print("uid");
2332 dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
2333 sepMemStates ? memStates : null,
2334 sepProcStates ? procStates : null);
2335 pw.println();
2336 for (int i=procs.size()-1; i>=0; i--) {
2337 ProcessState proc = procs.get(i);
2338 pw.print(proc.mName);
2339 pw.print(CSV_SEP);
2340 UserHandle.formatUid(pw, proc.mUid);
2341 dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates,
2342 sepMemStates, memStates, sepProcStates, procStates, now);
2343 pw.println();
2344 }
2345 }
2346
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07002347 boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header,
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002348 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
2349 boolean sepProcStates, int[] procStates, long now, String reqPackage) {
Dianne Hackborn904a8572013-06-28 18:12:31 -07002350 ArrayList<ProcessState> procs = mState.collectProcessesLocked(screenStates, memStates,
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002351 procStates, now, reqPackage);
2352 if (procs.size() > 0) {
2353 if (header != null) {
2354 pw.println(header);
2355 }
2356 dumpProcessListCsv(pw, procs, sepScreenStates, screenStates,
2357 sepMemStates, memStates, sepProcStates, procStates, now);
2358 return true;
2359 }
2360 return false;
2361 }
2362
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002363 static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
2364 int index = value/mod;
2365 if (index >= 0 && index < array.length) {
2366 pw.print(array[index]);
2367 } else {
2368 pw.print('?');
2369 }
2370 return value - index*mod;
2371 }
2372
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002373 static void printProcStateTag(PrintWriter pw, int state) {
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002374 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT);
2375 state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT);
2376 printArrayEntry(pw, STATE_TAGS, state, 1);
2377 }
2378
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002379 static void printAdjTag(PrintWriter pw, int state) {
2380 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD);
Dianne Hackborn904a8572013-06-28 18:12:31 -07002381 printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002382 }
2383
2384 static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002385 pw.print(',');
2386 printProcStateTag(pw, state);
2387 pw.print(':');
2388 pw.print(value);
2389 }
2390
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002391 static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
2392 pw.print(',');
2393 printAdjTag(pw, state);
2394 pw.print(':');
2395 pw.print(value);
2396 }
2397
2398 static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002399 boolean didCurState = false;
2400 for (int i=0; i<proc.mDurationsTableSize; i++) {
2401 int off = proc.mDurationsTable[i];
2402 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2403 long time = proc.mState.getLong(off, 0);
2404 if (proc.mCurState == type) {
2405 didCurState = true;
2406 time += now - proc.mStartTime;
2407 }
2408 printProcStateTagAndValue(pw, type, time);
2409 }
Dianne Hackborn904a8572013-06-28 18:12:31 -07002410 if (!didCurState && proc.mCurState != STATE_NOTHING) {
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002411 printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
2412 }
2413 }
2414
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002415 static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) {
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002416 for (int i=0; i<proc.mPssTableSize; i++) {
2417 int off = proc.mPssTable[i];
2418 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2419 long count = proc.mState.getLong(off, PSS_SAMPLE_COUNT);
2420 long min = proc.mState.getLong(off, PSS_MINIMUM);
2421 long avg = proc.mState.getLong(off, PSS_AVERAGE);
2422 long max = proc.mState.getLong(off, PSS_MAXIMUM);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002423 long umin = proc.mState.getLong(off, PSS_USS_MINIMUM);
2424 long uavg = proc.mState.getLong(off, PSS_USS_AVERAGE);
2425 long umax = proc.mState.getLong(off, PSS_USS_MAXIMUM);
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002426 pw.print(',');
2427 printProcStateTag(pw, type);
2428 pw.print(':');
2429 pw.print(count);
2430 pw.print(':');
2431 pw.print(min);
2432 pw.print(':');
2433 pw.print(avg);
2434 pw.print(':');
2435 pw.print(max);
Dianne Hackbornc8230512013-07-13 21:32:12 -07002436 pw.print(':');
2437 pw.print(umin);
2438 pw.print(':');
2439 pw.print(uavg);
2440 pw.print(':');
2441 pw.print(umax);
Dianne Hackborn13ac0412013-06-25 19:34:49 -07002442 }
2443 }
2444
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002445 static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
2446 String[] outError) {
2447 ArrayList<Integer> res = new ArrayList<Integer>();
2448 int lastPos = 0;
2449 for (int i=0; i<=arg.length(); i++) {
2450 char c = i < arg.length() ? arg.charAt(i) : 0;
2451 if (c != ',' && c != '+' && c != ' ' && c != 0) {
2452 continue;
2453 }
2454 boolean isSep = c == ',';
2455 if (lastPos == 0) {
2456 // We now know the type of op.
2457 outSep[0] = isSep;
2458 } else if (c != 0 && outSep[0] != isSep) {
2459 outError[0] = "inconsistent separators (can't mix ',' with '+')";
2460 return null;
2461 }
2462 if (lastPos < (i-1)) {
2463 String str = arg.substring(lastPos, i);
2464 for (int j=0; j<states.length; j++) {
2465 if (str.equals(states[j])) {
2466 res.add(j);
2467 str = null;
2468 break;
Dianne Hackborn78a369c2013-06-11 17:10:32 -07002469 }
2470 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002471 if (str != null) {
2472 outError[0] = "invalid word \"" + str + "\"";
2473 return null;
2474 }
2475 }
2476 lastPos = i + 1;
2477 }
2478
2479 int[] finalRes = new int[res.size()];
2480 for (int i=0; i<res.size(); i++) {
2481 finalRes[i] = res.get(i) * mult;
2482 }
2483 return finalRes;
2484 }
2485
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002486 static private void dumpHelp(PrintWriter pw) {
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002487 pw.println("Process stats (procstats) dump options:");
Dianne Hackborn169c8032013-07-03 14:42:22 -07002488 pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002489 pw.println(" [--details] [--current] [--commit] [--write] [-h] [<package.name>]");
Dianne Hackborn169c8032013-07-03 14:42:22 -07002490 pw.println(" --checkin: perform a checkin: print and delete old committed states.");
2491 pw.println(" --c: print only state in checkin format.");
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002492 pw.println(" --csv: output data suitable for putting in a spreadsheet.");
2493 pw.println(" --csv-screen: on, off.");
2494 pw.println(" --csv-mem: norm, mod, low, crit.");
2495 pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
2496 pw.println(" service, home, prev, cached");
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002497 pw.println(" --details: dump all execution details, not just summary.");
2498 pw.println(" --current: only dump current state.");
Dianne Hackborn169c8032013-07-03 14:42:22 -07002499 pw.println(" --commit: commit current stats to disk and reset to start new stats.");
Dianne Hackborn904a8572013-06-28 18:12:31 -07002500 pw.println(" --write: write current in-memory stats to disk.");
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07002501 pw.println(" --read: replace current stats with last-written stats.");
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002502 pw.println(" -a: print everything.");
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002503 pw.println(" -h: print this help text.");
2504 pw.println(" <package.name>: optional name of package to filter output by.");
2505 }
2506
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002507 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002508 final long now = SystemClock.uptimeMillis();
2509
2510 boolean isCheckin = false;
Dianne Hackborn169c8032013-07-03 14:42:22 -07002511 boolean isCompact = false;
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002512 boolean isCsv = false;
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002513 boolean currentOnly = false;
2514 boolean dumpDetails = false;
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002515 boolean dumpAll = false;
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002516 String reqPackage = null;
2517 boolean csvSepScreenStats = false;
2518 int[] csvScreenStats = new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON};
2519 boolean csvSepMemStats = false;
2520 int[] csvMemStats = new int[] {ADJ_MEM_FACTOR_CRITICAL};
2521 boolean csvSepProcStats = true;
2522 int[] csvProcStats = new int[] {
Dianne Hackbornc8230512013-07-13 21:32:12 -07002523 STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
2524 STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT, STATE_SERVICE,
2525 STATE_RECEIVER, STATE_HOME, STATE_LAST_ACTIVITY,
2526 STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY };
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002527 if (args != null) {
2528 for (int i=0; i<args.length; i++) {
2529 String arg = args[i];
2530 if ("--checkin".equals(arg)) {
2531 isCheckin = true;
Dianne Hackborn169c8032013-07-03 14:42:22 -07002532 } else if ("-c".equals(arg)) {
2533 isCompact = true;
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002534 } else if ("--csv".equals(arg)) {
2535 isCsv = true;
2536 } else if ("--csv-screen".equals(arg)) {
2537 i++;
2538 if (i >= args.length) {
2539 pw.println("Error: argument required for --csv-screen");
2540 dumpHelp(pw);
2541 return;
2542 }
2543 boolean[] sep = new boolean[1];
2544 String[] error = new String[1];
2545 csvScreenStats = parseStateList(ADJ_SCREEN_NAMES_CSV, ADJ_SCREEN_MOD,
2546 args[i], sep, error);
2547 if (csvScreenStats == null) {
2548 pw.println("Error in \"" + args[i] + "\": " + error[0]);
2549 dumpHelp(pw);
2550 return;
2551 }
2552 csvSepScreenStats = sep[0];
2553 } else if ("--csv-mem".equals(arg)) {
2554 i++;
2555 if (i >= args.length) {
2556 pw.println("Error: argument required for --csv-mem");
2557 dumpHelp(pw);
2558 return;
2559 }
2560 boolean[] sep = new boolean[1];
2561 String[] error = new String[1];
2562 csvMemStats = parseStateList(ADJ_MEM_NAMES_CSV, 1, args[i], sep, error);
2563 if (csvMemStats == null) {
2564 pw.println("Error in \"" + args[i] + "\": " + error[0]);
2565 dumpHelp(pw);
2566 return;
2567 }
2568 csvSepMemStats = sep[0];
2569 } else if ("--csv-proc".equals(arg)) {
2570 i++;
2571 if (i >= args.length) {
2572 pw.println("Error: argument required for --csv-proc");
2573 dumpHelp(pw);
2574 return;
2575 }
2576 boolean[] sep = new boolean[1];
2577 String[] error = new String[1];
2578 csvProcStats = parseStateList(STATE_NAMES_CSV, 1, args[i], sep, error);
2579 if (csvProcStats == null) {
2580 pw.println("Error in \"" + args[i] + "\": " + error[0]);
2581 dumpHelp(pw);
2582 return;
2583 }
2584 csvSepProcStats = sep[0];
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002585 } else if ("--details".equals(arg)) {
2586 dumpDetails = true;
2587 } else if ("--current".equals(arg)) {
2588 currentOnly = true;
Dianne Hackborn169c8032013-07-03 14:42:22 -07002589 } else if ("--commit".equals(arg)) {
Dianne Hackbornc8230512013-07-13 21:32:12 -07002590 mState.mFlags |= State.FLAG_COMPLETE;
Dianne Hackborn169c8032013-07-03 14:42:22 -07002591 mState.writeStateLocked(true, true);
2592 pw.println("Process stats committed.");
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002593 return;
Dianne Hackborn904a8572013-06-28 18:12:31 -07002594 } else if ("--write".equals(arg)) {
2595 writeStateSyncLocked();
2596 pw.println("Process stats written.");
2597 return;
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07002598 } else if ("--read".equals(arg)) {
2599 readLocked();
2600 pw.println("Process stats read.");
2601 return;
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002602 } else if ("-h".equals(arg)) {
2603 dumpHelp(pw);
2604 return;
2605 } else if ("-a".equals(arg)) {
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002606 dumpDetails = true;
Dianne Hackborncfc837f2013-06-27 18:32:07 -07002607 dumpAll = true;
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002608 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
2609 pw.println("Unknown option: " + arg);
2610 dumpHelp(pw);
2611 return;
2612 } else {
2613 // Not an option, last argument must be a package name.
2614 try {
Dianne Hackborn904a8572013-06-28 18:12:31 -07002615 IPackageManager pm = AppGlobals.getPackageManager();
2616 if (pm.getPackageUid(arg, UserHandle.getCallingUserId()) >= 0) {
2617 reqPackage = arg;
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002618 // Include all details, since we know we are only going to
2619 // be dumping a smaller set of data. In fact only the details
2620 // container per-package data, so that are needed to be able
2621 // to dump anything at all when filtering by package.
2622 dumpDetails = true;
Dianne Hackborn904a8572013-06-28 18:12:31 -07002623 }
2624 } catch (RemoteException e) {
2625 }
2626 if (reqPackage == null) {
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002627 pw.println("Unknown package: " + arg);
2628 dumpHelp(pw);
2629 return;
2630 }
2631 }
2632 }
2633 }
2634
2635 if (isCsv) {
2636 pw.print("Processes running summed over");
2637 if (!csvSepScreenStats) {
2638 for (int i=0; i<csvScreenStats.length; i++) {
2639 pw.print(" ");
2640 printScreenLabelCsv(pw, csvScreenStats[i]);
2641 }
2642 }
2643 if (!csvSepMemStats) {
2644 for (int i=0; i<csvMemStats.length; i++) {
2645 pw.print(" ");
2646 printMemLabelCsv(pw, csvMemStats[i]);
2647 }
2648 }
2649 if (!csvSepProcStats) {
2650 for (int i=0; i<csvProcStats.length; i++) {
2651 pw.print(" ");
2652 pw.print(STATE_NAMES_CSV[csvProcStats[i]]);
2653 }
2654 }
2655 pw.println();
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002656 synchronized (mLock) {
2657 dumpFilteredProcessesCsvLocked(pw, null,
2658 csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
2659 csvSepProcStats, csvProcStats, now, reqPackage);
2660 /*
2661 dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
2662 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
2663 true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
2664 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
2665 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
2666 STATE_PREVIOUS, STATE_CACHED},
2667 now, reqPackage);
2668 dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
2669 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
2670 false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
2671 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
2672 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
2673 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
2674 STATE_PREVIOUS, STATE_CACHED},
2675 now, reqPackage);
2676 */
2677 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002678 return;
2679 }
2680
Dianne Hackborn169c8032013-07-03 14:42:22 -07002681 boolean sepNeeded = false;
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002682 if (!currentOnly || isCheckin) {
2683 mWriteLock.lock();
2684 try {
2685 ArrayList<String> files = getCommittedFiles(0, !isCheckin);
2686 if (files != null) {
2687 for (int i=0; i<files.size(); i++) {
2688 if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
2689 try {
2690 State state = new State(files.get(i));
Dianne Hackbornc8230512013-07-13 21:32:12 -07002691 if (state.mReadError != null) {
2692 pw.print("Failure reading "); pw.print(files.get(i));
2693 pw.print("; "); pw.println(state.mReadError);
2694 if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
2695 (new File(files.get(i))).delete();
2696 continue;
2697 }
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002698 String fileStr = state.mFile.getBaseFile().getPath();
2699 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
2700 if (isCheckin || isCompact) {
2701 // Don't really need to lock because we uniquely own this object.
2702 state.dumpCheckinLocked(pw, reqPackage);
Dianne Hackborn169c8032013-07-03 14:42:22 -07002703 } else {
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002704 if (sepNeeded) {
2705 pw.println();
2706 } else {
2707 sepNeeded = true;
2708 }
2709 pw.print("COMMITTED STATS FROM ");
2710 pw.print(state.mTimePeriodStartClockStr);
2711 if (checkedIn) pw.print(" (checked in)");
2712 pw.println(":");
2713 // Don't really need to lock because we uniquely own this object.
2714 if (dumpDetails) {
2715 state.dumpLocked(pw, reqPackage, now, dumpAll);
2716 } else {
2717 state.dumpSummaryLocked(pw, reqPackage, now);
2718 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07002719 }
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002720 if (isCheckin) {
2721 // Rename file suffix to mark that it has checked in.
2722 state.mFile.getBaseFile().renameTo(new File(
2723 fileStr + STATE_FILE_CHECKIN_SUFFIX));
2724 }
2725 } catch (Throwable e) {
2726 pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
2727 e.printStackTrace(pw);
Dianne Hackborn169c8032013-07-03 14:42:22 -07002728 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07002729 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07002730 }
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002731 } finally {
2732 mWriteLock.unlock();
Dianne Hackborn169c8032013-07-03 14:42:22 -07002733 }
2734 }
2735 if (!isCheckin) {
Dianne Hackborna4cc2052013-07-08 17:31:25 -07002736 synchronized (mLock) {
2737 if (isCompact) {
2738 mState.dumpCheckinLocked(pw, reqPackage);
2739 } else {
2740 if (sepNeeded) {
2741 pw.println();
2742 pw.println("CURRENT STATS:");
2743 }
2744 if (dumpDetails) {
2745 mState.dumpLocked(pw, reqPackage, now, dumpAll);
2746 } else {
2747 mState.dumpSummaryLocked(pw, reqPackage, now);
2748 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07002749 }
Dianne Hackborn169c8032013-07-03 14:42:22 -07002750 }
Dianne Hackborna17c0f52013-06-20 18:59:11 -07002751 }
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -07002752 }
2753}