blob: a87992aeb341c92188271660792d892de0c84cd7 [file] [log] [blame]
Dianne Hackbornd2932242013-08-05 18:18:42 -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.internal.app;
18
19import android.os.Parcel;
Dianne Hackborn23fb6e82013-08-07 10:08:22 -070020import android.os.Parcelable;
Dianne Hackbornd2932242013-08-05 18:18:42 -070021import android.os.SystemClock;
22import android.os.SystemProperties;
23import android.os.UserHandle;
24import android.text.format.DateFormat;
25import android.util.ArrayMap;
26import android.util.ArraySet;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -070027import android.util.Log;
Dianne Hackbornd2932242013-08-05 18:18:42 -070028import android.util.Slog;
29import android.util.SparseArray;
30import android.util.TimeUtils;
31import android.webkit.WebViewFactory;
32import com.android.internal.util.ArrayUtils;
Dianne Hackbornd2932242013-08-05 18:18:42 -070033import dalvik.system.VMRuntime;
34
Dianne Hackborn60444fd2013-08-08 21:57:14 -070035import java.io.IOException;
36import java.io.InputStream;
Dianne Hackbornd2932242013-08-05 18:18:42 -070037import java.io.PrintWriter;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.Collections;
41import java.util.Comparator;
42import java.util.Objects;
43
Dianne Hackborn8a0de582013-08-07 15:22:07 -070044public final class ProcessStats implements Parcelable {
Dianne Hackbornd2932242013-08-05 18:18:42 -070045 static final String TAG = "ProcessStats";
46 static final boolean DEBUG = false;
Dianne Hackborn164371f2013-10-01 19:10:13 -070047 static final boolean DEBUG_PARCEL = false;
Dianne Hackborn8a0de582013-08-07 15:22:07 -070048
49 public static final String SERVICE_NAME = "procstats";
50
Dianne Hackborncb428552013-09-26 11:07:17 -070051 // How often the service commits its data, giving the minimum batching
52 // that is done.
53 public static long COMMIT_PERIOD = 3*60*60*1000; // Commit current stats every 3 hours
54
Dianne Hackbornd2932242013-08-05 18:18:42 -070055 public static final int STATE_NOTHING = -1;
56 public static final int STATE_PERSISTENT = 0;
57 public static final int STATE_TOP = 1;
58 public static final int STATE_IMPORTANT_FOREGROUND = 2;
59 public static final int STATE_IMPORTANT_BACKGROUND = 3;
60 public static final int STATE_BACKUP = 4;
61 public static final int STATE_HEAVY_WEIGHT = 5;
62 public static final int STATE_SERVICE = 6;
63 public static final int STATE_SERVICE_RESTARTING = 7;
64 public static final int STATE_RECEIVER = 8;
65 public static final int STATE_HOME = 9;
66 public static final int STATE_LAST_ACTIVITY = 10;
67 public static final int STATE_CACHED_ACTIVITY = 11;
68 public static final int STATE_CACHED_ACTIVITY_CLIENT = 12;
69 public static final int STATE_CACHED_EMPTY = 13;
70 public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
71
72 public static final int PSS_SAMPLE_COUNT = 0;
73 public static final int PSS_MINIMUM = 1;
74 public static final int PSS_AVERAGE = 2;
75 public static final int PSS_MAXIMUM = 3;
76 public static final int PSS_USS_MINIMUM = 4;
77 public static final int PSS_USS_AVERAGE = 5;
78 public static final int PSS_USS_MAXIMUM = 6;
79 public static final int PSS_COUNT = PSS_USS_MAXIMUM+1;
80
81 public static final int ADJ_NOTHING = -1;
82 public static final int ADJ_MEM_FACTOR_NORMAL = 0;
83 public static final int ADJ_MEM_FACTOR_MODERATE = 1;
84 public static final int ADJ_MEM_FACTOR_LOW = 2;
85 public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
86 public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
87 public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
88 public static final int ADJ_SCREEN_OFF = 0;
89 public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
90 public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
91
92 public static final int FLAG_COMPLETE = 1<<0;
93 public static final int FLAG_SHUTDOWN = 1<<1;
94 public static final int FLAG_SYSPROPS = 1<<2;
95
Dianne Hackborn8a0de582013-08-07 15:22:07 -070096 public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
97 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
98
99 public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
100
101 public static final int[] NON_CACHED_PROC_STATES = new int[] {
102 STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700103 STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT,
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700104 STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
105 };
106
107 public static final int[] BACKGROUND_PROC_STATES = new int[] {
108 STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
109 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
Dianne Hackbornd2932242013-08-05 18:18:42 -0700110 };
111
112 // Map from process states to the states we track.
113 static final int[] PROCESS_STATE_TO_STATE = new int[] {
114 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
115 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
116 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
117 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
118 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
119 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP
120 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
121 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE
122 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER
123 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME
124 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
125 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
126 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
127 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
128 };
129
130 public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
131 STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
132 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER,
133 STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
134 STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
135 };
136
137 static final String[] STATE_NAMES = new String[] {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700138 "Persist", "Top ", "ImpFg ", "ImpBg ",
139 "Backup ", "HeavyWt", "Service", "ServRst",
140 "Receivr", "Home ",
141 "LastAct", "CchAct ", "CchCAct", "CchEmty"
Dianne Hackbornd2932242013-08-05 18:18:42 -0700142 };
143
144 public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
145 "off", "on"
146 };
147
148 public static final String[] ADJ_MEM_NAMES_CSV = new String[] {
149 "norm", "mod", "low", "crit"
150 };
151
152 public static final String[] STATE_NAMES_CSV = new String[] {
153 "pers", "top", "impfg", "impbg", "backup", "heavy",
154 "service", "service-rs", "receiver", "home", "lastact",
155 "cch-activity", "cch-aclient", "cch-empty"
156 };
157
158 static final String[] ADJ_SCREEN_TAGS = new String[] {
159 "0", "1"
160 };
161
162 static final String[] ADJ_MEM_TAGS = new String[] {
163 "n", "m", "l", "c"
164 };
165
166 static final String[] STATE_TAGS = new String[] {
167 "p", "t", "f", "b", "u", "w",
168 "s", "x", "r", "h", "l", "a", "c", "e"
169 };
170
171 static final String CSV_SEP = "\t";
172
173 // Current version of the parcel format.
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -0700174 private static final int PARCEL_VERSION = 13;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700175 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
176 private static final int MAGIC = 0x50535453;
177
178 // Where the "type"/"state" part of the data appears in an offset integer.
179 static int OFFSET_TYPE_SHIFT = 0;
180 static int OFFSET_TYPE_MASK = 0xff;
181 // Where the "which array" part of the data appears in an offset integer.
182 static int OFFSET_ARRAY_SHIFT = 8;
183 static int OFFSET_ARRAY_MASK = 0xff;
184 // Where the "index into array" part of the data appears in an offset integer.
185 static int OFFSET_INDEX_SHIFT = 16;
186 static int OFFSET_INDEX_MASK = 0xffff;
187
188 public String mReadError;
189 public String mTimePeriodStartClockStr;
190 public int mFlags;
191
192 public final ProcessMap<PackageState> mPackages = new ProcessMap<PackageState>();
193 public final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
194
195 public final long[] mMemFactorDurations = new long[ADJ_COUNT];
196 public int mMemFactor = STATE_NOTHING;
197 public long mStartTime;
198
199 public long mTimePeriodStartClock;
200 public long mTimePeriodStartRealtime;
201 public long mTimePeriodEndRealtime;
202 String mRuntime;
203 String mWebView;
204 boolean mRunning;
205
206 static final int LONGS_SIZE = 4096;
207 final ArrayList<long[]> mLongs = new ArrayList<long[]>();
208 int mNextLong;
209
210 int[] mAddLongTable;
211 int mAddLongTableSize;
212
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -0700213 // For writing parcels.
214 ArrayMap<String, Integer> mCommonStringToIndex;
215
216 // For reading parcels.
217 ArrayList<String> mIndexToCommonString;
218
Dianne Hackbornd2932242013-08-05 18:18:42 -0700219 public ProcessStats(boolean running) {
220 mRunning = running;
221 reset();
222 }
223
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700224 public ProcessStats(Parcel in) {
225 reset();
226 readFromParcel(in);
227 }
228
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700229 public void add(ProcessStats other) {
230 ArrayMap<String, SparseArray<PackageState>> pkgMap = other.mPackages.getMap();
231 for (int ip=0; ip<pkgMap.size(); ip++) {
232 String pkgName = pkgMap.keyAt(ip);
233 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
234 for (int iu=0; iu<uids.size(); iu++) {
235 int uid = uids.keyAt(iu);
236 PackageState otherState = uids.valueAt(iu);
237 final int NPROCS = otherState.mProcesses.size();
238 final int NSRVS = otherState.mServices.size();
239 for (int iproc=0; iproc<NPROCS; iproc++) {
240 ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
241 if (otherProc.mCommonProcess != otherProc) {
242 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
243 + " proc " + otherProc.mName);
244 ProcessState thisProc = getProcessStateLocked(pkgName, uid,
245 otherProc.mName);
246 if (thisProc.mCommonProcess == thisProc) {
247 if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
248 thisProc.mMultiPackage = true;
249 long now = SystemClock.uptimeMillis();
250 final PackageState pkgState = getPackageStateLocked(pkgName, uid);
251 thisProc = thisProc.clone(thisProc.mPackage, now);
252 pkgState.mProcesses.put(thisProc.mName, thisProc);
253 }
254 thisProc.add(otherProc);
255 }
256 }
257 for (int isvc=0; isvc<NSRVS; isvc++) {
258 ServiceState otherSvc = otherState.mServices.valueAt(isvc);
259 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
260 + " service " + otherSvc.mName);
261 ServiceState thisSvc = getServiceStateLocked(pkgName, uid,
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -0700262 otherSvc.mProcessName, otherSvc.mName);
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700263 thisSvc.add(otherSvc);
264 }
265 }
266 }
267
268 ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
269 for (int ip=0; ip<procMap.size(); ip++) {
270 SparseArray<ProcessState> uids = procMap.valueAt(ip);
271 for (int iu=0; iu<uids.size(); iu++) {
272 int uid = uids.keyAt(iu);
273 ProcessState otherProc = uids.valueAt(iu);
274 ProcessState thisProc = mProcesses.get(otherProc.mName, uid);
275 if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName);
276 if (thisProc == null) {
277 if (DEBUG) Slog.d(TAG, "Creating new process!");
278 thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mName);
279 mProcesses.put(otherProc.mName, uid, thisProc);
280 PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid);
281 if (!thisState.mProcesses.containsKey(otherProc.mName)) {
282 thisState.mProcesses.put(otherProc.mName, thisProc);
283 }
284 }
285 thisProc.add(otherProc);
286 }
287 }
288
289 for (int i=0; i<ADJ_COUNT; i++) {
290 if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
291 + other.mMemFactorDurations[i] + " from "
292 + mMemFactorDurations[i]);
293 mMemFactorDurations[i] += other.mMemFactorDurations[i];
294 }
295
296 if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
297 mTimePeriodStartClock = other.mTimePeriodStartClock;
298 mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
299 }
300 mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
301 }
302
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700303 public static final Parcelable.Creator<ProcessStats> CREATOR
304 = new Parcelable.Creator<ProcessStats>() {
305 public ProcessStats createFromParcel(Parcel in) {
306 return new ProcessStats(in);
307 }
308
309 public ProcessStats[] newArray(int size) {
310 return new ProcessStats[size];
311 }
312 };
313
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700314 private static void printScreenLabel(PrintWriter pw, int offset) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700315 switch (offset) {
316 case ADJ_NOTHING:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700317 pw.print(" ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700318 break;
319 case ADJ_SCREEN_OFF:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700320 pw.print("SOff/");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700321 break;
322 case ADJ_SCREEN_ON:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700323 pw.print("SOn /");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700324 break;
325 default:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700326 pw.print("????/");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700327 break;
328 }
329 }
330
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700331 public static void printScreenLabelCsv(PrintWriter pw, int offset) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700332 switch (offset) {
333 case ADJ_NOTHING:
334 break;
335 case ADJ_SCREEN_OFF:
336 pw.print(ADJ_SCREEN_NAMES_CSV[0]);
337 break;
338 case ADJ_SCREEN_ON:
339 pw.print(ADJ_SCREEN_NAMES_CSV[1]);
340 break;
341 default:
342 pw.print("???");
343 break;
344 }
345 }
346
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700347 private static void printMemLabel(PrintWriter pw, int offset, char sep) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700348 switch (offset) {
349 case ADJ_NOTHING:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700350 pw.print(" ");
351 if (sep != 0) pw.print(' ');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700352 break;
353 case ADJ_MEM_FACTOR_NORMAL:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700354 pw.print("Norm");
355 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700356 break;
357 case ADJ_MEM_FACTOR_MODERATE:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700358 pw.print("Mod ");
359 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700360 break;
361 case ADJ_MEM_FACTOR_LOW:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700362 pw.print("Low ");
363 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700364 break;
365 case ADJ_MEM_FACTOR_CRITICAL:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700366 pw.print("Crit");
367 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700368 break;
369 default:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700370 pw.print("????");
371 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700372 break;
373 }
374 }
375
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700376 public static void printMemLabelCsv(PrintWriter pw, int offset) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700377 if (offset >= ADJ_MEM_FACTOR_NORMAL) {
378 if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
379 pw.print(ADJ_MEM_NAMES_CSV[offset]);
380 } else {
381 pw.print("???");
382 }
383 }
384 }
385
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700386 public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700387 int curState, long curStartTime, long now) {
388 long totalTime = 0;
389 int printedScreen = -1;
390 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
391 int printedMem = -1;
392 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
393 int state = imem+iscreen;
394 long time = durations[state];
395 String running = "";
396 if (curState == state) {
397 time += now - curStartTime;
398 if (pw != null) {
399 running = " (running)";
400 }
401 }
402 if (time != 0) {
403 if (pw != null) {
404 pw.print(prefix);
405 printScreenLabel(pw, printedScreen != iscreen
406 ? iscreen : STATE_NOTHING);
407 printedScreen = iscreen;
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700408 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700409 printedMem = imem;
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700410 pw.print(": ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700411 TimeUtils.formatDuration(time, pw); pw.println(running);
412 }
413 totalTime += time;
414 }
415 }
416 }
417 if (totalTime != 0 && pw != null) {
418 pw.print(prefix);
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700419 pw.print(" TOTAL: ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700420 TimeUtils.formatDuration(totalTime, pw);
421 pw.println();
422 }
423 return totalTime;
424 }
425
426 static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,
427 int curState, long curStartTime, long now) {
428 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
429 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
430 int state = imem+iscreen;
431 long time = durations[state];
432 if (curState == state) {
433 time += now - curStartTime;
434 }
435 if (time != 0) {
436 printAdjTagAndValue(pw, state, time);
437 }
438 }
439 }
440 }
441
442 static void dumpServiceTimeCheckin(PrintWriter pw, String label, String packageName,
443 int uid, String serviceName, ServiceState svc, int serviceType, int opCount,
444 int curState, long curStartTime, long now) {
445 if (opCount <= 0) {
446 return;
447 }
448 pw.print(label);
449 pw.print(",");
450 pw.print(packageName);
451 pw.print(",");
452 pw.print(uid);
453 pw.print(",");
454 pw.print(serviceName);
455 pw.print(",");
456 pw.print(opCount);
457 boolean didCurState = false;
458 for (int i=0; i<svc.mDurationsTableSize; i++) {
459 int off = svc.mDurationsTable[i];
460 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
461 int memFactor = type / ServiceState.SERVICE_COUNT;
462 type %= ServiceState.SERVICE_COUNT;
463 if (type != serviceType) {
464 continue;
465 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700466 long time = svc.mStats.getLong(off, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700467 if (curState == memFactor) {
468 didCurState = true;
469 time += now - curStartTime;
470 }
471 printAdjTagAndValue(pw, memFactor, time);
472 }
473 if (!didCurState && curState != STATE_NOTHING) {
474 printAdjTagAndValue(pw, curState, now - curStartTime);
475 }
476 pw.println();
477 }
478
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700479 public static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700480 data.totalTime = 0;
481 data.numPss = data.minPss = data.avgPss = data.maxPss =
482 data.minUss = data.avgUss = data.maxUss = 0;
483 for (int is=0; is<data.screenStates.length; is++) {
484 for (int im=0; im<data.memStates.length; im++) {
485 for (int ip=0; ip<data.procStates.length; ip++) {
486 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
487 + data.procStates[ip];
488 data.totalTime += proc.getDuration(bucket, now);
489 long samples = proc.getPssSampleCount(bucket);
490 if (samples > 0) {
491 long minPss = proc.getPssMinimum(bucket);
492 long avgPss = proc.getPssAverage(bucket);
493 long maxPss = proc.getPssMaximum(bucket);
494 long minUss = proc.getPssUssMinimum(bucket);
495 long avgUss = proc.getPssUssAverage(bucket);
496 long maxUss = proc.getPssUssMaximum(bucket);
497 if (data.numPss == 0) {
498 data.minPss = minPss;
499 data.avgPss = avgPss;
500 data.maxPss = maxPss;
501 data.minUss = minUss;
502 data.avgUss = avgUss;
503 data.maxUss = maxUss;
504 } else {
505 if (minPss < data.minPss) {
506 data.minPss = minPss;
507 }
508 data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
509 + (avgPss*(double)samples)) / (data.numPss+samples) );
510 if (maxPss > data.maxPss) {
511 data.maxPss = maxPss;
512 }
513 if (minUss < data.minUss) {
514 data.minUss = minUss;
515 }
516 data.avgUss = (long)( ((data.avgUss*(double)data.numPss)
517 + (avgUss*(double)samples)) / (data.numPss+samples) );
518 if (maxUss > data.maxUss) {
519 data.maxUss = maxUss;
520 }
521 }
522 data.numPss += samples;
523 }
524 }
525 }
526 }
527 }
528
529 static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
530 int[] procStates, long now) {
531 long totalTime = 0;
532 /*
533 for (int i=0; i<proc.mDurationsTableSize; i++) {
534 int val = proc.mDurationsTable[i];
535 totalTime += proc.mState.getLong(val, 0);
536 if ((val&0xff) == proc.mCurState) {
537 totalTime += now - proc.mStartTime;
538 }
539 }
540 */
541 for (int is=0; is<screenStates.length; is++) {
542 for (int im=0; im<memStates.length; im++) {
543 for (int ip=0; ip<procStates.length; ip++) {
544 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
545 + procStates[ip];
546 totalTime += proc.getDuration(bucket, now);
547 }
548 }
549 }
550 proc.mTmpTotalTime = totalTime;
551 return totalTime;
552 }
553
554 static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc,
555 int[] screenStates, int[] memStates, int[] procStates, long now) {
556 long totalTime = 0;
557 int printedScreen = -1;
558 for (int is=0; is<screenStates.length; is++) {
559 int printedMem = -1;
560 for (int im=0; im<memStates.length; im++) {
561 for (int ip=0; ip<procStates.length; ip++) {
562 final int iscreen = screenStates[is];
563 final int imem = memStates[im];
564 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
565 long time = proc.getDuration(bucket, now);
566 String running = "";
567 if (proc.mCurState == bucket) {
568 running = " (running)";
569 }
570 if (time != 0) {
571 pw.print(prefix);
572 if (screenStates.length > 1) {
573 printScreenLabel(pw, printedScreen != iscreen
574 ? iscreen : STATE_NOTHING);
575 printedScreen = iscreen;
576 }
577 if (memStates.length > 1) {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700578 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700579 printedMem = imem;
580 }
581 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
582 TimeUtils.formatDuration(time, pw); pw.println(running);
583 totalTime += time;
584 }
585 }
586 }
587 }
588 if (totalTime != 0) {
589 pw.print(prefix);
590 if (screenStates.length > 1) {
591 printScreenLabel(pw, STATE_NOTHING);
592 }
593 if (memStates.length > 1) {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700594 printMemLabel(pw, STATE_NOTHING, '/');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700595 }
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700596 pw.print("TOTAL : ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700597 TimeUtils.formatDuration(totalTime, pw);
598 pw.println();
599 }
600 }
601
602 static void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
603 int[] memStates, int[] procStates) {
604 boolean printedHeader = false;
605 int printedScreen = -1;
606 for (int is=0; is<screenStates.length; is++) {
607 int printedMem = -1;
608 for (int im=0; im<memStates.length; im++) {
609 for (int ip=0; ip<procStates.length; ip++) {
610 final int iscreen = screenStates[is];
611 final int imem = memStates[im];
612 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
613 long count = proc.getPssSampleCount(bucket);
614 if (count > 0) {
615 if (!printedHeader) {
616 pw.print(prefix);
617 pw.print("PSS/USS (");
618 pw.print(proc.mPssTableSize);
619 pw.println(" entries):");
620 printedHeader = true;
621 }
622 pw.print(prefix);
623 pw.print(" ");
624 if (screenStates.length > 1) {
625 printScreenLabel(pw, printedScreen != iscreen
626 ? iscreen : STATE_NOTHING);
627 printedScreen = iscreen;
628 }
629 if (memStates.length > 1) {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700630 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700631 printedMem = imem;
632 }
633 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
634 pw.print(count);
635 pw.print(" samples ");
636 printSizeValue(pw, proc.getPssMinimum(bucket) * 1024);
637 pw.print(" ");
638 printSizeValue(pw, proc.getPssAverage(bucket) * 1024);
639 pw.print(" ");
640 printSizeValue(pw, proc.getPssMaximum(bucket) * 1024);
641 pw.print(" / ");
642 printSizeValue(pw, proc.getPssUssMinimum(bucket) * 1024);
643 pw.print(" ");
644 printSizeValue(pw, proc.getPssUssAverage(bucket) * 1024);
645 pw.print(" ");
646 printSizeValue(pw, proc.getPssUssMaximum(bucket) * 1024);
647 pw.println();
648 }
649 }
650 }
651 }
652 if (proc.mNumExcessiveWake != 0) {
653 pw.print(prefix); pw.print("Killed for excessive wake locks: ");
654 pw.print(proc.mNumExcessiveWake); pw.println(" times");
655 }
656 if (proc.mNumExcessiveCpu != 0) {
657 pw.print(prefix); pw.print("Killed for excessive CPU use: ");
658 pw.print(proc.mNumExcessiveCpu); pw.println(" times");
659 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -0700660 if (proc.mNumCachedKill != 0) {
661 pw.print(prefix); pw.print("Killed from cached state: ");
662 pw.print(proc.mNumCachedKill); pw.print(" times from pss ");
663 printSizeValue(pw, proc.mMinCachedKillPss * 1024); pw.print("-");
664 printSizeValue(pw, proc.mAvgCachedKillPss * 1024); pw.print("-");
665 printSizeValue(pw, proc.mMaxCachedKillPss * 1024); pw.println();
666 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700667 }
668
669 static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
670 int[] memStates, int[] procStates) {
671 final int NS = screenStates != null ? screenStates.length : 1;
672 final int NM = memStates != null ? memStates.length : 1;
673 final int NP = procStates != null ? procStates.length : 1;
674 for (int is=0; is<NS; is++) {
675 for (int im=0; im<NM; im++) {
676 for (int ip=0; ip<NP; ip++) {
677 pw.print(sep);
678 boolean printed = false;
679 if (screenStates != null && screenStates.length > 1) {
680 printScreenLabelCsv(pw, screenStates[is]);
681 printed = true;
682 }
683 if (memStates != null && memStates.length > 1) {
684 if (printed) {
685 pw.print("-");
686 }
687 printMemLabelCsv(pw, memStates[im]);
688 printed = true;
689 }
690 if (procStates != null && procStates.length > 1) {
691 if (printed) {
692 pw.print("-");
693 }
694 pw.print(STATE_NAMES_CSV[procStates[ip]]);
695 }
696 }
697 }
698 }
699 }
700
701 static void dumpProcessStateCsv(PrintWriter pw, ProcessState proc,
702 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
703 boolean sepProcStates, int[] procStates, long now) {
704 final int NSS = sepScreenStates ? screenStates.length : 1;
705 final int NMS = sepMemStates ? memStates.length : 1;
706 final int NPS = sepProcStates ? procStates.length : 1;
707 for (int iss=0; iss<NSS; iss++) {
708 for (int ims=0; ims<NMS; ims++) {
709 for (int ips=0; ips<NPS; ips++) {
710 final int vsscreen = sepScreenStates ? screenStates[iss] : 0;
711 final int vsmem = sepMemStates ? memStates[ims] : 0;
712 final int vsproc = sepProcStates ? procStates[ips] : 0;
713 final int NSA = sepScreenStates ? 1 : screenStates.length;
714 final int NMA = sepMemStates ? 1 : memStates.length;
715 final int NPA = sepProcStates ? 1 : procStates.length;
716 long totalTime = 0;
717 for (int isa=0; isa<NSA; isa++) {
718 for (int ima=0; ima<NMA; ima++) {
719 for (int ipa=0; ipa<NPA; ipa++) {
720 final int vascreen = sepScreenStates ? 0 : screenStates[isa];
721 final int vamem = sepMemStates ? 0 : memStates[ima];
722 final int vaproc = sepProcStates ? 0 : procStates[ipa];
723 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
724 * STATE_COUNT) + vsproc + vaproc;
725 totalTime += proc.getDuration(bucket, now);
726 }
727 }
728 }
729 pw.print(CSV_SEP);
730 pw.print(totalTime);
731 }
732 }
733 }
734 }
735
736 static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
737 int[] screenStates, int[] memStates, int[] procStates, long now) {
738 String innerPrefix = prefix + " ";
739 for (int i=procs.size()-1; i>=0; i--) {
740 ProcessState proc = procs.get(i);
741 pw.print(prefix);
742 pw.print(proc.mName);
743 pw.print(" / ");
744 UserHandle.formatUid(pw, proc.mUid);
745 pw.print(" (");
746 pw.print(proc.mDurationsTableSize);
747 pw.print(" entries)");
748 pw.println(":");
749 dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
750 if (proc.mPssTableSize > 0) {
751 dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates);
752 }
753 }
754 }
755
756 static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix,
757 String label, int[] screenStates, int[] memStates, int[] procStates,
758 long now, long totalTime, boolean full) {
759 ProcessDataCollection totals = new ProcessDataCollection(screenStates,
760 memStates, procStates);
761 computeProcessData(proc, totals, now);
762 if (totals.totalTime != 0 || totals.numPss != 0) {
763 if (prefix != null) {
764 pw.print(prefix);
765 }
766 if (label != null) {
767 pw.print(label);
768 }
769 totals.print(pw, totalTime, full);
770 if (prefix != null) {
771 pw.println();
772 }
773 }
774 }
775
776 static void dumpProcessSummaryLocked(PrintWriter pw, String prefix,
777 ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
778 long now, long totalTime) {
779 for (int i=procs.size()-1; i>=0; i--) {
780 ProcessState proc = procs.get(i);
781 pw.print(prefix);
782 pw.print("* ");
783 pw.print(proc.mName);
784 pw.print(" / ");
785 UserHandle.formatUid(pw, proc.mUid);
786 pw.println(":");
787 dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates,
788 procStates, now, totalTime, true);
789 dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates,
790 new int[] { STATE_PERSISTENT }, now, totalTime, true);
791 dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates,
792 new int[] {STATE_TOP}, now, totalTime, true);
793 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Fg: ", screenStates, memStates,
794 new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true);
795 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Bg: ", screenStates, memStates,
796 new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true);
797 dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates,
798 new int[] {STATE_BACKUP}, now, totalTime, true);
799 dumpProcessSummaryDetails(pw, proc, prefix, " Heavy Wgt: ", screenStates, memStates,
800 new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
801 dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates,
802 new int[] {STATE_SERVICE}, now, totalTime, true);
803 dumpProcessSummaryDetails(pw, proc, prefix, " Service Rs: ", screenStates, memStates,
804 new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
805 dumpProcessSummaryDetails(pw, proc, prefix, " Receiver: ", screenStates, memStates,
806 new int[] {STATE_RECEIVER}, now, totalTime, true);
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700807 dumpProcessSummaryDetails(pw, proc, prefix, " (Home): ", screenStates, memStates,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700808 new int[] {STATE_HOME}, now, totalTime, true);
809 dumpProcessSummaryDetails(pw, proc, prefix, " (Last Act): ", screenStates, memStates,
810 new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
811 dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates,
812 new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT,
813 STATE_CACHED_EMPTY}, now, totalTime, true);
814 }
815 }
816
817 static void printPercent(PrintWriter pw, double fraction) {
818 fraction *= 100;
819 if (fraction < 1) {
820 pw.print(String.format("%.2f", fraction));
821 } else if (fraction < 10) {
822 pw.print(String.format("%.1f", fraction));
823 } else {
824 pw.print(String.format("%.0f", fraction));
825 }
826 pw.print("%");
827 }
828
829 static void printSizeValue(PrintWriter pw, long number) {
830 float result = number;
831 String suffix = "";
832 if (result > 900) {
833 suffix = "KB";
834 result = result / 1024;
835 }
836 if (result > 900) {
837 suffix = "MB";
838 result = result / 1024;
839 }
840 if (result > 900) {
841 suffix = "GB";
842 result = result / 1024;
843 }
844 if (result > 900) {
845 suffix = "TB";
846 result = result / 1024;
847 }
848 if (result > 900) {
849 suffix = "PB";
850 result = result / 1024;
851 }
852 String value;
853 if (result < 1) {
854 value = String.format("%.2f", result);
855 } else if (result < 10) {
856 value = String.format("%.1f", result);
857 } else if (result < 100) {
858 value = String.format("%.0f", result);
859 } else {
860 value = String.format("%.0f", result);
861 }
862 pw.print(value);
863 pw.print(suffix);
864 }
865
866 public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
867 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
868 boolean sepProcStates, int[] procStates, long now) {
869 pw.print("process");
870 pw.print(CSV_SEP);
871 pw.print("uid");
872 dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
873 sepMemStates ? memStates : null,
874 sepProcStates ? procStates : null);
875 pw.println();
876 for (int i=procs.size()-1; i>=0; i--) {
877 ProcessState proc = procs.get(i);
878 pw.print(proc.mName);
879 pw.print(CSV_SEP);
880 UserHandle.formatUid(pw, proc.mUid);
881 dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates,
882 sepMemStates, memStates, sepProcStates, procStates, now);
883 pw.println();
884 }
885 }
886
887 static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
888 int index = value/mod;
889 if (index >= 0 && index < array.length) {
890 pw.print(array[index]);
891 } else {
892 pw.print('?');
893 }
894 return value - index*mod;
895 }
896
897 static void printProcStateTag(PrintWriter pw, int state) {
898 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT);
899 state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT);
900 printArrayEntry(pw, STATE_TAGS, state, 1);
901 }
902
903 static void printAdjTag(PrintWriter pw, int state) {
904 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD);
905 printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
906 }
907
908 static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
909 pw.print(',');
910 printProcStateTag(pw, state);
911 pw.print(':');
912 pw.print(value);
913 }
914
915 static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
916 pw.print(',');
917 printAdjTag(pw, state);
918 pw.print(':');
919 pw.print(value);
920 }
921
922 static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
923 boolean didCurState = false;
924 for (int i=0; i<proc.mDurationsTableSize; i++) {
925 int off = proc.mDurationsTable[i];
926 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700927 long time = proc.mStats.getLong(off, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700928 if (proc.mCurState == type) {
929 didCurState = true;
930 time += now - proc.mStartTime;
931 }
932 printProcStateTagAndValue(pw, type, time);
933 }
934 if (!didCurState && proc.mCurState != STATE_NOTHING) {
935 printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
936 }
937 }
938
939 static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) {
940 for (int i=0; i<proc.mPssTableSize; i++) {
941 int off = proc.mPssTable[i];
942 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700943 long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT);
944 long min = proc.mStats.getLong(off, PSS_MINIMUM);
945 long avg = proc.mStats.getLong(off, PSS_AVERAGE);
946 long max = proc.mStats.getLong(off, PSS_MAXIMUM);
947 long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM);
948 long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE);
949 long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700950 pw.print(',');
951 printProcStateTag(pw, type);
952 pw.print(':');
953 pw.print(count);
954 pw.print(':');
955 pw.print(min);
956 pw.print(':');
957 pw.print(avg);
958 pw.print(':');
959 pw.print(max);
960 pw.print(':');
961 pw.print(umin);
962 pw.print(':');
963 pw.print(uavg);
964 pw.print(':');
965 pw.print(umax);
966 }
967 }
968
969 public void reset() {
970 if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr);
971 resetCommon();
972 mPackages.getMap().clear();
973 mProcesses.getMap().clear();
974 mMemFactor = STATE_NOTHING;
975 mStartTime = 0;
976 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
977 }
978
979 public void resetSafely() {
980 if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
981 resetCommon();
982 long now = SystemClock.uptimeMillis();
983 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
984 for (int ip=procMap.size()-1; ip>=0; ip--) {
985 SparseArray<ProcessState> uids = procMap.valueAt(ip);
986 for (int iu=uids.size()-1; iu>=0; iu--) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -0700987 ProcessState ps = uids.valueAt(iu);
988 if (ps.isInUse()) {
989 uids.valueAt(iu).resetSafely(now);
990 } else {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700991 uids.valueAt(iu).makeDead();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -0700992 uids.removeAt(iu);
993 }
994 }
995 if (uids.size() <= 0) {
996 procMap.removeAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700997 }
998 }
999 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
1000 for (int ip=pkgMap.size()-1; ip>=0; ip--) {
1001 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
1002 for (int iu=uids.size()-1; iu>=0; iu--) {
1003 PackageState pkgState = uids.valueAt(iu);
1004 for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001005 ProcessState ps = pkgState.mProcesses.valueAt(iproc);
Dianne Hackborna0332372013-09-13 18:34:13 -07001006 if (ps.isInUse() || ps.mCommonProcess.isInUse()) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001007 pkgState.mProcesses.valueAt(iproc).resetSafely(now);
1008 } else {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07001009 pkgState.mProcesses.valueAt(iproc).makeDead();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001010 pkgState.mProcesses.removeAt(iproc);
1011 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001012 }
1013 for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
1014 ServiceState ss = pkgState.mServices.valueAt(isvc);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001015 if (ss.isInUse()) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001016 pkgState.mServices.valueAt(isvc).resetSafely(now);
1017 } else {
1018 pkgState.mServices.removeAt(isvc);
1019 }
1020 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001021 if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
1022 uids.removeAt(iu);
1023 }
1024 }
1025 if (uids.size() <= 0) {
1026 pkgMap.removeAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001027 }
1028 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001029 mStartTime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001030 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
1031 }
1032
1033 private void resetCommon() {
1034 mTimePeriodStartClock = System.currentTimeMillis();
1035 buildTimePeriodStartClockStr();
1036 mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
1037 mLongs.clear();
1038 mLongs.add(new long[LONGS_SIZE]);
1039 mNextLong = 0;
1040 Arrays.fill(mMemFactorDurations, 0);
1041 mStartTime = 0;
1042 mReadError = null;
1043 mFlags = 0;
1044 evaluateSystemProperties(true);
1045 }
1046
1047 public boolean evaluateSystemProperties(boolean update) {
1048 boolean changed = false;
Brian Carlstromc6c63362014-01-30 13:14:01 -08001049 String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.1",
Dianne Hackbornd2932242013-08-05 18:18:42 -07001050 VMRuntime.getRuntime().vmLibrary());
1051 if (!Objects.equals(runtime, mRuntime)) {
1052 changed = true;
1053 if (update) {
1054 mRuntime = runtime;
1055 }
1056 }
1057 String webview = WebViewFactory.useExperimentalWebView() ? "chromeview" : "webview";
1058 if (!Objects.equals(webview, mWebView)) {
1059 changed = true;
1060 if (update) {
1061 mWebView = webview;
1062 }
1063 }
1064 return changed;
1065 }
1066
1067 private void buildTimePeriodStartClockStr() {
1068 mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
1069 mTimePeriodStartClock).toString();
1070 }
1071
1072 static final int[] BAD_TABLE = new int[0];
1073
1074 private int[] readTableFromParcel(Parcel in, String name, String what) {
1075 final int size = in.readInt();
1076 if (size < 0) {
1077 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size);
1078 return BAD_TABLE;
1079 }
1080 if (size == 0) {
1081 return null;
1082 }
1083 final int[] table = new int[size];
1084 for (int i=0; i<size; i++) {
1085 table[i] = in.readInt();
Dianne Hackborn164371f2013-10-01 19:10:13 -07001086 if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
Dianne Hackbornd2932242013-08-05 18:18:42 -07001087 + ProcessStats.printLongOffset(table[i]));
1088 if (!validateLongOffset(table[i])) {
1089 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
1090 + ProcessStats.printLongOffset(table[i]));
1091 return null;
1092 }
1093 }
1094 return table;
1095 }
1096
Dianne Hackborn53459a72013-09-17 17:14:57 -07001097 private void writeCompactedLongArray(Parcel out, long[] array, int num) {
1098 for (int i=0; i<num; i++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001099 long val = array[i];
1100 if (val < 0) {
1101 Slog.w(TAG, "Time val negative: " + val);
1102 val = 0;
1103 }
1104 if (val <= Integer.MAX_VALUE) {
1105 out.writeInt((int)val);
1106 } else {
1107 int top = ~((int)((val>>32)&0x7fffffff));
1108 int bottom = (int)(val&0xfffffff);
1109 out.writeInt(top);
1110 out.writeInt(bottom);
1111 }
1112 }
1113 }
1114
Dianne Hackborn53459a72013-09-17 17:14:57 -07001115 private void readCompactedLongArray(Parcel in, int version, long[] array, int num) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001116 if (version <= 10) {
1117 in.readLongArray(array);
1118 return;
1119 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001120 final int alen = array.length;
1121 if (num > alen) {
1122 throw new RuntimeException("bad array lengths: got " + num + " array is " + alen);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001123 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001124 int i;
1125 for (i=0; i<num; i++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001126 int val = in.readInt();
1127 if (val >= 0) {
1128 array[i] = val;
1129 } else {
1130 int bottom = in.readInt();
1131 array[i] = (((long)~val)<<32) | bottom;
1132 }
1133 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001134 while (i < alen) {
1135 array[i] = 0;
1136 i++;
1137 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001138 }
1139
1140 private void writeCommonString(Parcel out, String name) {
1141 Integer index = mCommonStringToIndex.get(name);
1142 if (index != null) {
1143 out.writeInt(index);
1144 return;
1145 }
1146 index = mCommonStringToIndex.size();
1147 mCommonStringToIndex.put(name, index);
1148 out.writeInt(~index);
1149 out.writeString(name);
1150 }
1151
1152 private String readCommonString(Parcel in, int version) {
1153 if (version <= 9) {
1154 return in.readString();
1155 }
1156 int index = in.readInt();
1157 if (index >= 0) {
1158 return mIndexToCommonString.get(index);
1159 }
1160 index = ~index;
1161 String name = in.readString();
1162 while (mIndexToCommonString.size() <= index) {
1163 mIndexToCommonString.add(null);
1164 }
1165 mIndexToCommonString.set(index, name);
1166 return name;
1167 }
1168
Dianne Hackborn23fb6e82013-08-07 10:08:22 -07001169 @Override
1170 public int describeContents() {
1171 return 0;
1172 }
1173
1174 @Override
1175 public void writeToParcel(Parcel out, int flags) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001176 long now = SystemClock.uptimeMillis();
1177 out.writeInt(MAGIC);
1178 out.writeInt(PARCEL_VERSION);
1179 out.writeInt(STATE_COUNT);
1180 out.writeInt(ADJ_COUNT);
1181 out.writeInt(PSS_COUNT);
1182 out.writeInt(LONGS_SIZE);
1183
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001184 mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size());
1185
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001186 // First commit all running times.
1187 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1188 final int NPROC = procMap.size();
1189 for (int ip=0; ip<NPROC; ip++) {
1190 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1191 final int NUID = uids.size();
1192 for (int iu=0; iu<NUID; iu++) {
1193 uids.valueAt(iu).commitStateTime(now);
1194 }
1195 }
1196 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
1197 final int NPKG = pkgMap.size();
1198 for (int ip=0; ip<NPKG; ip++) {
1199 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
1200 final int NUID = uids.size();
1201 for (int iu=0; iu<NUID; iu++) {
1202 PackageState pkgState = uids.valueAt(iu);
1203 final int NPROCS = pkgState.mProcesses.size();
1204 for (int iproc=0; iproc<NPROCS; iproc++) {
1205 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1206 if (proc.mCommonProcess != proc) {
1207 proc.commitStateTime(now);
1208 }
1209 }
1210 final int NSRVS = pkgState.mServices.size();
1211 for (int isvc=0; isvc<NSRVS; isvc++) {
1212 pkgState.mServices.valueAt(isvc).commitStateTime(now);
1213 }
1214 }
1215 }
1216
Dianne Hackbornd2932242013-08-05 18:18:42 -07001217 out.writeLong(mTimePeriodStartClock);
1218 out.writeLong(mTimePeriodStartRealtime);
1219 out.writeLong(mTimePeriodEndRealtime);
1220 out.writeString(mRuntime);
1221 out.writeString(mWebView);
1222 out.writeInt(mFlags);
1223
1224 out.writeInt(mLongs.size());
1225 out.writeInt(mNextLong);
1226 for (int i=0; i<(mLongs.size()-1); i++) {
Dianne Hackborn53459a72013-09-17 17:14:57 -07001227 long[] array = mLongs.get(i);
1228 writeCompactedLongArray(out, array, array.length);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001229 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001230 long[] lastLongs = mLongs.get(mLongs.size() - 1);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001231 writeCompactedLongArray(out, lastLongs, mNextLong);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001232
1233 if (mMemFactor != STATE_NOTHING) {
1234 mMemFactorDurations[mMemFactor] += now - mStartTime;
1235 mStartTime = now;
1236 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001237 writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001238
Dianne Hackbornd2932242013-08-05 18:18:42 -07001239 out.writeInt(NPROC);
1240 for (int ip=0; ip<NPROC; ip++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001241 writeCommonString(out, procMap.keyAt(ip));
Dianne Hackbornd2932242013-08-05 18:18:42 -07001242 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1243 final int NUID = uids.size();
1244 out.writeInt(NUID);
1245 for (int iu=0; iu<NUID; iu++) {
1246 out.writeInt(uids.keyAt(iu));
1247 ProcessState proc = uids.valueAt(iu);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001248 writeCommonString(out, proc.mPackage);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001249 proc.writeToParcel(out, now);
1250 }
1251 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001252 out.writeInt(NPKG);
1253 for (int ip=0; ip<NPKG; ip++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001254 writeCommonString(out, pkgMap.keyAt(ip));
Dianne Hackbornd2932242013-08-05 18:18:42 -07001255 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
1256 final int NUID = uids.size();
1257 out.writeInt(NUID);
1258 for (int iu=0; iu<NUID; iu++) {
1259 out.writeInt(uids.keyAt(iu));
1260 PackageState pkgState = uids.valueAt(iu);
1261 final int NPROCS = pkgState.mProcesses.size();
1262 out.writeInt(NPROCS);
1263 for (int iproc=0; iproc<NPROCS; iproc++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001264 writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
Dianne Hackbornd2932242013-08-05 18:18:42 -07001265 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1266 if (proc.mCommonProcess == proc) {
1267 // This is the same as the common process we wrote above.
1268 out.writeInt(0);
1269 } else {
1270 // There is separate data for this package's process.
1271 out.writeInt(1);
1272 proc.writeToParcel(out, now);
1273 }
1274 }
1275 final int NSRVS = pkgState.mServices.size();
1276 out.writeInt(NSRVS);
1277 for (int isvc=0; isvc<NSRVS; isvc++) {
1278 out.writeString(pkgState.mServices.keyAt(isvc));
1279 ServiceState svc = pkgState.mServices.valueAt(isvc);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001280 writeCommonString(out, svc.mProcessName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001281 svc.writeToParcel(out, now);
1282 }
1283 }
1284 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001285
1286 mCommonStringToIndex = null;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001287 }
1288
1289 private boolean readCheckedInt(Parcel in, int val, String what) {
1290 int got;
1291 if ((got=in.readInt()) != val) {
1292 mReadError = "bad " + what + ": " + got;
1293 return false;
1294 }
1295 return true;
1296 }
1297
Dianne Hackborn53459a72013-09-17 17:14:57 -07001298 static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001299 int pos = 0;
Dianne Hackborn53459a72013-09-17 17:14:57 -07001300 final int initialAvail = stream.available();
1301 byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001302 while (true) {
1303 int amt = stream.read(data, pos, data.length-pos);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001304 if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
Dianne Hackborn53459a72013-09-17 17:14:57 -07001305 + " of avail " + data.length);
1306 if (amt < 0) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001307 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
Dianne Hackborn53459a72013-09-17 17:14:57 -07001308 + " len=" + data.length);
1309 outLen[0] = pos;
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001310 return data;
1311 }
1312 pos += amt;
Dianne Hackborn53459a72013-09-17 17:14:57 -07001313 if (pos >= data.length) {
1314 byte[] newData = new byte[pos+16384];
Dianne Hackborn164371f2013-10-01 19:10:13 -07001315 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
Dianne Hackborn53459a72013-09-17 17:14:57 -07001316 + newData.length);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001317 System.arraycopy(data, 0, newData, 0, pos);
1318 data = newData;
1319 }
1320 }
1321 }
1322
1323 public void read(InputStream stream) {
1324 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -07001325 int[] len = new int[1];
1326 byte[] raw = readFully(stream, len);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001327 Parcel in = Parcel.obtain();
Dianne Hackborn53459a72013-09-17 17:14:57 -07001328 in.unmarshall(raw, 0, len[0]);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001329 in.setDataPosition(0);
1330 stream.close();
1331
1332 readFromParcel(in);
1333 } catch (IOException e) {
1334 mReadError = "caught exception: " + e;
1335 }
1336 }
1337
Dianne Hackbornd2932242013-08-05 18:18:42 -07001338 public void readFromParcel(Parcel in) {
1339 final boolean hadData = mPackages.getMap().size() > 0
1340 || mProcesses.getMap().size() > 0;
1341 if (hadData) {
1342 resetSafely();
1343 }
1344
1345 if (!readCheckedInt(in, MAGIC, "magic number")) {
1346 return;
1347 }
1348 int version = in.readInt();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001349 if (version != PARCEL_VERSION) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001350 mReadError = "bad version: " + version;
1351 return;
1352 }
1353 if (!readCheckedInt(in, STATE_COUNT, "state count")) {
1354 return;
1355 }
1356 if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
1357 return;
1358 }
1359 if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
1360 return;
1361 }
1362 if (!readCheckedInt(in, LONGS_SIZE, "longs size")) {
1363 return;
1364 }
1365
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001366 mIndexToCommonString = new ArrayList<String>();
1367
Dianne Hackbornd2932242013-08-05 18:18:42 -07001368 mTimePeriodStartClock = in.readLong();
1369 buildTimePeriodStartClockStr();
1370 mTimePeriodStartRealtime = in.readLong();
1371 mTimePeriodEndRealtime = in.readLong();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001372 mRuntime = in.readString();
1373 mWebView = in.readString();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001374 mFlags = in.readInt();
1375
1376 final int NLONGS = in.readInt();
1377 final int NEXTLONG = in.readInt();
1378 mLongs.clear();
1379 for (int i=0; i<(NLONGS-1); i++) {
1380 while (i >= mLongs.size()) {
1381 mLongs.add(new long[LONGS_SIZE]);
1382 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001383 readCompactedLongArray(in, version, mLongs.get(i), LONGS_SIZE);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001384 }
1385 long[] longs = new long[LONGS_SIZE];
1386 mNextLong = NEXTLONG;
Dianne Hackborn53459a72013-09-17 17:14:57 -07001387 readCompactedLongArray(in, version, longs, NEXTLONG);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001388 mLongs.add(longs);
1389
Dianne Hackborn53459a72013-09-17 17:14:57 -07001390 readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001391
1392 int NPROC = in.readInt();
1393 if (NPROC < 0) {
1394 mReadError = "bad process count: " + NPROC;
1395 return;
1396 }
1397 while (NPROC > 0) {
1398 NPROC--;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001399 String procName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001400 if (procName == null) {
1401 mReadError = "bad process name";
1402 return;
1403 }
1404 int NUID = in.readInt();
1405 if (NUID < 0) {
1406 mReadError = "bad uid count: " + NUID;
1407 return;
1408 }
1409 while (NUID > 0) {
1410 NUID--;
1411 int uid = in.readInt();
1412 if (uid < 0) {
1413 mReadError = "bad uid: " + uid;
1414 return;
1415 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001416 String pkgName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001417 if (pkgName == null) {
1418 mReadError = "bad process package name";
1419 return;
1420 }
1421 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
1422 if (proc != null) {
1423 if (!proc.readFromParcel(in, false)) {
1424 return;
1425 }
1426 } else {
1427 proc = new ProcessState(this, pkgName, uid, procName);
1428 if (!proc.readFromParcel(in, true)) {
1429 return;
1430 }
1431 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001432 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
1433 + " " + proc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001434 mProcesses.put(procName, uid, proc);
1435 }
1436 }
1437
Dianne Hackborn164371f2013-10-01 19:10:13 -07001438 if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001439
1440 int NPKG = in.readInt();
1441 if (NPKG < 0) {
1442 mReadError = "bad package count: " + NPKG;
1443 return;
1444 }
1445 while (NPKG > 0) {
1446 NPKG--;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001447 String pkgName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001448 if (pkgName == null) {
1449 mReadError = "bad package name";
1450 return;
1451 }
1452 int NUID = in.readInt();
1453 if (NUID < 0) {
1454 mReadError = "bad uid count: " + NUID;
1455 return;
1456 }
1457 while (NUID > 0) {
1458 NUID--;
1459 int uid = in.readInt();
1460 if (uid < 0) {
1461 mReadError = "bad uid: " + uid;
1462 return;
1463 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001464 PackageState pkgState = new PackageState(pkgName, uid);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001465 mPackages.put(pkgName, uid, pkgState);
1466 int NPROCS = in.readInt();
1467 if (NPROCS < 0) {
1468 mReadError = "bad package process count: " + NPROCS;
1469 return;
1470 }
1471 while (NPROCS > 0) {
1472 NPROCS--;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001473 String procName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001474 if (procName == null) {
1475 mReadError = "bad package process name";
1476 return;
1477 }
1478 int hasProc = in.readInt();
Dianne Hackborn164371f2013-10-01 19:10:13 -07001479 if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
Dianne Hackbornd2932242013-08-05 18:18:42 -07001480 + " process " + procName + " hasProc=" + hasProc);
1481 ProcessState commonProc = mProcesses.get(procName, uid);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001482 if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
Dianne Hackbornd2932242013-08-05 18:18:42 -07001483 + ": " + commonProc);
1484 if (commonProc == null) {
1485 mReadError = "no common proc: " + procName;
1486 return;
1487 }
1488 if (hasProc != 0) {
1489 // The process for this package is unique to the package; we
1490 // need to load it. We don't need to do anything about it if
1491 // it is not unique because if someone later looks for it
1492 // they will find and use it from the global procs.
1493 ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
1494 if (proc != null) {
1495 if (!proc.readFromParcel(in, false)) {
1496 return;
1497 }
1498 } else {
1499 proc = new ProcessState(commonProc, pkgName, uid, procName, 0);
1500 if (!proc.readFromParcel(in, true)) {
1501 return;
1502 }
1503 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001504 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
Dianne Hackbornd2932242013-08-05 18:18:42 -07001505 + procName + " " + uid + " " + proc);
1506 pkgState.mProcesses.put(procName, proc);
1507 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001508 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
Dianne Hackbornd2932242013-08-05 18:18:42 -07001509 + procName + " " + uid + " " + commonProc);
1510 pkgState.mProcesses.put(procName, commonProc);
1511 }
1512 }
1513 int NSRVS = in.readInt();
1514 if (NSRVS < 0) {
1515 mReadError = "bad package service count: " + NSRVS;
1516 return;
1517 }
1518 while (NSRVS > 0) {
1519 NSRVS--;
1520 String serviceName = in.readString();
1521 if (serviceName == null) {
1522 mReadError = "bad package service name";
1523 return;
1524 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001525 String processName = version > 9 ? readCommonString(in, version) : null;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001526 ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
1527 if (serv == null) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001528 serv = new ServiceState(this, pkgName, serviceName, processName, null);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001529 }
1530 if (!serv.readFromParcel(in)) {
1531 return;
1532 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001533 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
Dianne Hackbornd2932242013-08-05 18:18:42 -07001534 + serviceName + " " + uid + " " + serv);
1535 pkgState.mServices.put(serviceName, serv);
1536 }
1537 }
1538 }
1539
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001540 mIndexToCommonString = null;
1541
Dianne Hackborn164371f2013-10-01 19:10:13 -07001542 if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001543 }
1544
1545 int addLongData(int index, int type, int num) {
1546 int tableLen = mAddLongTable != null ? mAddLongTable.length : 0;
1547 if (mAddLongTableSize >= tableLen) {
1548 int newSize = ArrayUtils.idealIntArraySize(tableLen + 1);
1549 int[] newTable = new int[newSize];
1550 if (tableLen > 0) {
1551 System.arraycopy(mAddLongTable, 0, newTable, 0, tableLen);
1552 }
1553 mAddLongTable = newTable;
1554 }
1555 if (mAddLongTableSize > 0 && mAddLongTableSize - index != 0) {
1556 System.arraycopy(mAddLongTable, index, mAddLongTable, index + 1,
1557 mAddLongTableSize - index);
1558 }
1559 int off = allocLongData(num);
1560 mAddLongTable[index] = type | off;
1561 mAddLongTableSize++;
1562 return off;
1563 }
1564
1565 int allocLongData(int num) {
1566 int whichLongs = mLongs.size()-1;
1567 long[] longs = mLongs.get(whichLongs);
1568 if (mNextLong + num > longs.length) {
1569 longs = new long[LONGS_SIZE];
1570 mLongs.add(longs);
1571 whichLongs++;
1572 mNextLong = 0;
1573 }
1574 int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
1575 mNextLong += num;
1576 return off;
1577 }
1578
1579 boolean validateLongOffset(int off) {
1580 int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK;
1581 if (arr >= mLongs.size()) {
1582 return false;
1583 }
1584 int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
1585 if (idx >= LONGS_SIZE) {
1586 return false;
1587 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001588 if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off)
Dianne Hackbornd2932242013-08-05 18:18:42 -07001589 + ": " + getLong(off, 0));
1590 return true;
1591 }
1592
1593 static String printLongOffset(int off) {
1594 StringBuilder sb = new StringBuilder(16);
1595 sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1596 sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK);
1597 sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK);
1598 return sb.toString();
1599 }
1600
1601 void setLong(int off, int index, long value) {
1602 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1603 longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
1604 }
1605
1606 long getLong(int off, int index) {
1607 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1608 return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
1609 }
1610
1611 static int binarySearch(int[] array, int size, int value) {
1612 int lo = 0;
1613 int hi = size - 1;
1614
1615 while (lo <= hi) {
1616 int mid = (lo + hi) >>> 1;
1617 int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
1618
1619 if (midVal < value) {
1620 lo = mid + 1;
1621 } else if (midVal > value) {
1622 hi = mid - 1;
1623 } else {
1624 return mid; // value found
1625 }
1626 }
1627 return ~lo; // value not present
1628 }
1629
1630 public PackageState getPackageStateLocked(String packageName, int uid) {
1631 PackageState as = mPackages.get(packageName, uid);
1632 if (as != null) {
1633 return as;
1634 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001635 as = new PackageState(packageName, uid);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001636 mPackages.put(packageName, uid, as);
1637 return as;
1638 }
1639
1640 public ProcessState getProcessStateLocked(String packageName, int uid, String processName) {
1641 final PackageState pkgState = getPackageStateLocked(packageName, uid);
1642 ProcessState ps = pkgState.mProcesses.get(processName);
1643 if (ps != null) {
1644 return ps;
1645 }
1646 ProcessState commonProc = mProcesses.get(processName, uid);
1647 if (commonProc == null) {
1648 commonProc = new ProcessState(this, packageName, uid, processName);
1649 mProcesses.put(processName, uid, commonProc);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001650 if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001651 }
1652 if (!commonProc.mMultiPackage) {
1653 if (packageName.equals(commonProc.mPackage)) {
1654 // This common process is not in use by multiple packages, and
1655 // is for the calling package, so we can just use it directly.
1656 ps = commonProc;
Dianne Hackborn164371f2013-10-01 19:10:13 -07001657 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001658 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001659 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001660 // This common process has not been in use by multiple packages,
1661 // but it was created for a different package than the caller.
1662 // We need to convert it to a multi-package process.
1663 commonProc.mMultiPackage = true;
Dianne Hackborncb428552013-09-26 11:07:17 -07001664 // To do this, we need to make two new process states, one a copy
1665 // of the current state for the process under the original package
1666 // name, and the second a free new process state for it as the
1667 // new package name.
Dianne Hackbornd2932242013-08-05 18:18:42 -07001668 long now = SystemClock.uptimeMillis();
Dianne Hackborncb428552013-09-26 11:07:17 -07001669 // First let's make a copy of the current process state and put
1670 // that under the now unique state for its original package name.
1671 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage, uid);
1672 if (commonPkgState != null) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001673 ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
1674 if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
1675 + ": " + cloned);
1676 commonPkgState.mProcesses.put(commonProc.mName, cloned);
1677 // If this has active services, we need to update their process pointer
1678 // to point to the new package-specific process state.
1679 for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
1680 ServiceState ss = commonPkgState.mServices.valueAt(i);
1681 if (ss.mProc == commonProc) {
1682 if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
1683 + ss);
1684 ss.mProc = cloned;
1685 } else if (DEBUG) {
1686 Slog.d(TAG, "GETPROC leaving proc of " + ss);
1687 }
1688 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001689 } else {
1690 Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
1691 + "/" + uid + " for proc " + commonProc.mName);
1692 }
1693 // And now make a fresh new process state for the new package name.
Dianne Hackbornd2932242013-08-05 18:18:42 -07001694 ps = new ProcessState(commonProc, packageName, uid, processName, now);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001695 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001696 }
1697 } else {
1698 // The common process is for multiple packages, we need to create a
1699 // separate object for the per-package data.
1700 ps = new ProcessState(commonProc, packageName, uid, processName,
1701 SystemClock.uptimeMillis());
Dianne Hackborn164371f2013-10-01 19:10:13 -07001702 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001703 }
1704 pkgState.mProcesses.put(processName, ps);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001705 if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001706 return ps;
1707 }
1708
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001709 public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
1710 String processName, String className) {
1711 final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
1712 ProcessStats.ServiceState ss = as.mServices.get(className);
1713 if (ss != null) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001714 if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001715 return ss;
1716 }
1717 final ProcessStats.ProcessState ps = processName != null
1718 ? getProcessStateLocked(packageName, uid, processName) : null;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001719 ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001720 as.mServices.put(className, ss);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001721 if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001722 return ss;
1723 }
1724
Dianne Hackborncb428552013-09-26 11:07:17 -07001725 private void dumpProcessInternalLocked(PrintWriter pw, String prefix, ProcessState proc,
1726 boolean dumpAll) {
1727 if (dumpAll) {
1728 pw.print(prefix); pw.print("myID=");
1729 pw.print(Integer.toHexString(System.identityHashCode(proc)));
1730 pw.print(" mCommonProcess=");
1731 pw.print(Integer.toHexString(System.identityHashCode(proc.mCommonProcess)));
1732 pw.print(" mPackage="); pw.println(proc.mPackage);
1733 if (proc.mMultiPackage) {
1734 pw.print(prefix); pw.print("mMultiPackage="); pw.println(proc.mMultiPackage);
1735 }
1736 if (proc != proc.mCommonProcess) {
1737 pw.print(prefix); pw.print("Common Proc: "); pw.print(proc.mCommonProcess.mName);
1738 pw.print("/"); pw.print(proc.mCommonProcess.mUid);
1739 pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage);
1740 }
1741 }
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001742 if (proc.mActive) {
1743 pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive);
1744 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001745 if (proc.mDead) {
1746 pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead);
1747 }
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001748 if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) {
1749 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices);
1750 pw.print(" mNumStartedServices=");
1751 pw.println(proc.mNumStartedServices);
1752 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001753 }
1754
Dianne Hackborn53459a72013-09-17 17:14:57 -07001755 public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
Dianne Hackborn164371f2013-10-01 19:10:13 -07001756 boolean dumpAll, boolean activeOnly) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001757 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
1758 mStartTime, now);
1759 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
1760 boolean printedHeader = false;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001761 boolean sepNeeded = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001762 for (int ip=0; ip<pkgMap.size(); ip++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001763 final String pkgName = pkgMap.keyAt(ip);
1764 final SparseArray<PackageState> uids = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001765 for (int iu=0; iu<uids.size(); iu++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001766 final int uid = uids.keyAt(iu);
1767 final PackageState pkgState = uids.valueAt(iu);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001768 final int NPROCS = pkgState.mProcesses.size();
1769 final int NSRVS = pkgState.mServices.size();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001770 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
1771 if (!pkgMatch) {
1772 boolean procMatch = false;
1773 for (int iproc=0; iproc<NPROCS; iproc++) {
1774 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1775 if (reqPackage.equals(proc.mName)) {
1776 procMatch = true;
1777 break;
1778 }
1779 }
1780 if (!procMatch) {
1781 continue;
1782 }
1783 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001784 if (NPROCS > 0 || NSRVS > 0) {
1785 if (!printedHeader) {
Dianne Hackbornae36b232013-09-03 18:12:53 -07001786 pw.println("Per-Package Stats:");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001787 printedHeader = true;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001788 sepNeeded = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001789 }
1790 pw.print(" * "); pw.print(pkgName); pw.print(" / ");
1791 UserHandle.formatUid(pw, uid); pw.println(":");
1792 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001793 if (!dumpSummary || dumpAll) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001794 for (int iproc=0; iproc<NPROCS; iproc++) {
1795 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001796 if (!pkgMatch && !reqPackage.equals(proc.mName)) {
1797 continue;
1798 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001799 if (activeOnly && !proc.isInUse()) {
1800 pw.print(" (Not active: ");
1801 pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
1802 continue;
1803 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001804 pw.print(" Process ");
1805 pw.print(pkgState.mProcesses.keyAt(iproc));
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001806 if (proc.mCommonProcess.mMultiPackage) {
1807 pw.print(" (multi, ");
1808 } else {
1809 pw.print(" (unique, ");
1810 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001811 pw.print(proc.mDurationsTableSize);
1812 pw.print(" entries)");
1813 pw.println(":");
1814 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1815 ALL_PROC_STATES, now);
1816 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1817 ALL_PROC_STATES);
Dianne Hackborncb428552013-09-26 11:07:17 -07001818 dumpProcessInternalLocked(pw, " ", proc, dumpAll);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001819 }
1820 } else {
1821 ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
1822 for (int iproc=0; iproc<NPROCS; iproc++) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001823 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001824 if (!pkgMatch && !reqPackage.equals(proc.mName)) {
1825 continue;
1826 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001827 if (activeOnly && !proc.isInUse()) {
1828 continue;
1829 }
1830 procs.add(proc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001831 }
1832 dumpProcessSummaryLocked(pw, " ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1833 NON_CACHED_PROC_STATES, now, totalTime);
1834 }
1835 for (int isvc=0; isvc<NSRVS; isvc++) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001836 ServiceState svc = pkgState.mServices.valueAt(isvc);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001837 if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
1838 continue;
1839 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001840 if (activeOnly && !svc.isInUse()) {
1841 pw.print(" (Not active: ");
1842 pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
1843 continue;
1844 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001845 if (dumpAll) {
1846 pw.print(" Service ");
1847 } else {
1848 pw.print(" * ");
1849 }
1850 pw.print(pkgState.mServices.keyAt(isvc));
1851 pw.println(":");
Dianne Hackborncb428552013-09-26 11:07:17 -07001852 pw.print(" Process: "); pw.println(svc.mProcessName);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001853 dumpServiceStats(pw, " ", " ", " ", "Running", svc,
1854 svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
Dianne Hackborn53459a72013-09-17 17:14:57 -07001855 svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001856 dumpServiceStats(pw, " ", " ", " ", "Started", svc,
1857 svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState,
Dianne Hackborn53459a72013-09-17 17:14:57 -07001858 svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001859 dumpServiceStats(pw, " ", " ", " ", "Bound", svc,
1860 svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState,
Dianne Hackborn53459a72013-09-17 17:14:57 -07001861 svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001862 dumpServiceStats(pw, " ", " ", " ", "Executing", svc,
1863 svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
Dianne Hackborn53459a72013-09-17 17:14:57 -07001864 svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001865 if (dumpAll) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001866 if (svc.mOwner != null) {
1867 pw.print(" mOwner="); pw.println(svc.mOwner);
1868 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001869 if (svc.mStarted || svc.mRestarting) {
1870 pw.print(" mStarted="); pw.print(svc.mStarted);
1871 pw.print(" mRestarting="); pw.println(svc.mRestarting);
1872 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001873 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001874 }
1875 }
1876 }
1877
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001878 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1879 printedHeader = false;
1880 int numShownProcs = 0, numTotalProcs = 0;
1881 for (int ip=0; ip<procMap.size(); ip++) {
1882 String procName = procMap.keyAt(ip);
1883 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1884 for (int iu=0; iu<uids.size(); iu++) {
1885 int uid = uids.keyAt(iu);
1886 numTotalProcs++;
1887 ProcessState proc = uids.valueAt(iu);
1888 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
1889 && proc.mPssTableSize == 0) {
1890 continue;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001891 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001892 if (!proc.mMultiPackage) {
1893 continue;
1894 }
1895 if (reqPackage != null && !reqPackage.equals(procName)
1896 && !reqPackage.equals(proc.mPackage)) {
1897 continue;
1898 }
1899 numShownProcs++;
1900 if (sepNeeded) {
1901 pw.println();
1902 }
1903 sepNeeded = true;
1904 if (!printedHeader) {
1905 pw.println("Multi-Package Common Processes:");
1906 printedHeader = true;
1907 }
1908 if (activeOnly && !proc.isInUse()) {
1909 pw.print(" (Not active: "); pw.print(procName); pw.println(")");
1910 continue;
1911 }
1912 pw.print(" * "); pw.print(procName); pw.print(" / ");
1913 UserHandle.formatUid(pw, uid);
1914 pw.print(" ("); pw.print(proc.mDurationsTableSize);
1915 pw.print(" entries)"); pw.println(":");
1916 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1917 ALL_PROC_STATES, now);
1918 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1919 ALL_PROC_STATES);
1920 dumpProcessInternalLocked(pw, " ", proc, dumpAll);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001921 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001922 }
1923 if (dumpAll) {
1924 pw.println();
1925 pw.print(" Total procs: "); pw.print(numShownProcs);
1926 pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
1927 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001928
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001929 if (sepNeeded) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001930 pw.println();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001931 }
1932 if (dumpSummary) {
1933 pw.println("Summary:");
1934 dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001935 } else {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001936 dumpTotalsLocked(pw, now);
1937 }
1938
1939 if (dumpAll) {
1940 pw.println();
1941 pw.println("Internal state:");
1942 pw.print(" Num long arrays: "); pw.println(mLongs.size());
1943 pw.print(" Next long entry: "); pw.println(mNextLong);
1944 pw.print(" mRunning="); pw.println(mRunning);
1945 }
1946 }
1947
Dianne Hackborn69cb00b2013-08-09 16:16:56 -07001948 public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
Dianne Hackbornd2932242013-08-05 18:18:42 -07001949 int serviceType, int curState, long curStartTime, long now) {
1950 long totalTime = 0;
1951 int printedScreen = -1;
1952 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
1953 int printedMem = -1;
1954 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
1955 int state = imem+iscreen;
1956 long time = service.getDuration(serviceType, curState, curStartTime,
1957 state, now);
1958 String running = "";
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001959 if (curState == state && pw != null) {
1960 running = " (running)";
Dianne Hackbornd2932242013-08-05 18:18:42 -07001961 }
1962 if (time != 0) {
1963 if (pw != null) {
1964 pw.print(prefix);
1965 printScreenLabel(pw, printedScreen != iscreen
1966 ? iscreen : STATE_NOTHING);
1967 printedScreen = iscreen;
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001968 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001969 printedMem = imem;
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001970 pw.print(": ");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001971 TimeUtils.formatDuration(time, pw); pw.println(running);
1972 }
1973 totalTime += time;
1974 }
1975 }
1976 }
1977 if (totalTime != 0 && pw != null) {
1978 pw.print(prefix);
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001979 pw.print(" TOTAL: ");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001980 TimeUtils.formatDuration(totalTime, pw);
1981 pw.println();
1982 }
1983 return totalTime;
1984 }
1985
1986 void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner,
1987 String headerPrefix, String header, ServiceState service,
1988 int count, int serviceType, int state, long startTime, long now, long totalTime,
1989 boolean dumpAll) {
1990 if (count != 0) {
1991 if (dumpAll) {
1992 pw.print(prefix); pw.print(header);
1993 pw.print(" op count "); pw.print(count); pw.println(":");
1994 dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime,
1995 now);
1996 } else {
1997 long myTime = dumpSingleServiceTime(null, null, service, serviceType, state,
1998 startTime, now);
1999 pw.print(prefix); pw.print(headerPrefix); pw.print(header);
2000 pw.print(" count "); pw.print(count);
2001 pw.print(" / time ");
2002 printPercent(pw, (double)myTime/(double)totalTime);
2003 pw.println();
2004 }
2005 }
2006 }
2007
Dianne Hackborn164371f2013-10-01 19:10:13 -07002008 public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002009 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
2010 mStartTime, now);
2011 dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002012 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002013 pw.println();
2014 dumpTotalsLocked(pw, now);
2015 }
2016
2017 void dumpTotalsLocked(PrintWriter pw, long now) {
2018 pw.println("Run time Stats:");
2019 dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now);
2020 pw.println();
2021 pw.print(" Start time: ");
2022 pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
2023 pw.println();
2024 pw.print(" Total elapsed time: ");
2025 TimeUtils.formatDuration(
2026 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
2027 - mTimePeriodStartRealtime, pw);
2028 boolean partial = true;
2029 if ((mFlags&FLAG_SHUTDOWN) != 0) {
2030 pw.print(" (shutdown)");
2031 partial = false;
2032 }
2033 if ((mFlags&FLAG_SYSPROPS) != 0) {
2034 pw.print(" (sysprops)");
2035 partial = false;
2036 }
2037 if ((mFlags&FLAG_COMPLETE) != 0) {
2038 pw.print(" (complete)");
2039 partial = false;
2040 }
2041 if (partial) {
2042 pw.print(" (partial)");
2043 }
2044 pw.print(' ');
2045 pw.print(mRuntime);
2046 pw.print(' ');
2047 pw.print(mWebView);
2048 pw.println();
2049 }
2050
2051 void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
Dianne Hackborncb428552013-09-26 11:07:17 -07002052 int[] screenStates, int[] memStates, int[] procStates,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002053 int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002054 ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002055 procStates, sortProcStates, now, reqPackage, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002056 if (procs.size() > 0) {
2057 if (header != null) {
2058 pw.println();
2059 pw.println(header);
2060 }
Dianne Hackborncb428552013-09-26 11:07:17 -07002061 dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
2062 sortProcStates, now, totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002063 }
2064 }
2065
2066 public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002067 int[] procStates, int sortProcStates[], long now, String reqPackage,
2068 boolean activeOnly) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002069 final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
2070 final ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002071 for (int ip=0; ip<pkgMap.size(); ip++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002072 final String pkgName = pkgMap.keyAt(ip);
2073 final SparseArray<PackageState> procs = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002074 for (int iu=0; iu<procs.size(); iu++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002075 final PackageState state = procs.valueAt(iu);
2076 final int NPROCS = state.mProcesses.size();
2077 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
2078 for (int iproc=0; iproc<NPROCS; iproc++) {
2079 final ProcessState proc = state.mProcesses.valueAt(iproc);
2080 if (!pkgMatch && !reqPackage.equals(proc.mName)) {
2081 continue;
2082 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002083 if (activeOnly && !proc.isInUse()) {
2084 continue;
2085 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002086 foundProcs.add(proc.mCommonProcess);
2087 }
2088 }
2089 }
2090 ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
2091 for (int i=0; i<foundProcs.size(); i++) {
2092 ProcessState proc = foundProcs.valueAt(i);
Dianne Hackborn164371f2013-10-01 19:10:13 -07002093 if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002094 outProcs.add(proc);
Dianne Hackborncb428552013-09-26 11:07:17 -07002095 if (procStates != sortProcStates) {
2096 computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
2097 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002098 }
2099 }
2100 Collections.sort(outProcs, new Comparator<ProcessState>() {
2101 @Override
2102 public int compare(ProcessState lhs, ProcessState rhs) {
2103 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
2104 return -1;
2105 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
2106 return 1;
2107 }
2108 return 0;
2109 }
2110 });
2111 return outProcs;
2112 }
2113
2114 String collapseString(String pkgName, String itemName) {
2115 if (itemName.startsWith(pkgName)) {
2116 final int ITEMLEN = itemName.length();
2117 final int PKGLEN = pkgName.length();
2118 if (ITEMLEN == PKGLEN) {
2119 return "";
2120 } else if (ITEMLEN >= PKGLEN) {
2121 if (itemName.charAt(PKGLEN) == '.') {
2122 return itemName.substring(PKGLEN);
2123 }
2124 }
2125 }
2126 return itemName;
2127 }
2128
2129 public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
2130 final long now = SystemClock.uptimeMillis();
2131 ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
2132 pw.println("vers,3");
2133 pw.print("period,"); pw.print(mTimePeriodStartClockStr);
2134 pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
2135 pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
2136 boolean partial = true;
2137 if ((mFlags&FLAG_SHUTDOWN) != 0) {
2138 pw.print(",shutdown");
2139 partial = false;
2140 }
2141 if ((mFlags&FLAG_SYSPROPS) != 0) {
2142 pw.print(",sysprops");
2143 partial = false;
2144 }
2145 if ((mFlags&FLAG_COMPLETE) != 0) {
2146 pw.print(",complete");
2147 partial = false;
2148 }
2149 if (partial) {
2150 pw.print(",partial");
2151 }
2152 pw.println();
2153 pw.print("config,"); pw.print(mRuntime); pw.print(','); pw.println(mWebView);
2154 for (int ip=0; ip<pkgMap.size(); ip++) {
2155 String pkgName = pkgMap.keyAt(ip);
2156 if (reqPackage != null && !reqPackage.equals(pkgName)) {
2157 continue;
2158 }
2159 SparseArray<PackageState> uids = pkgMap.valueAt(ip);
2160 for (int iu=0; iu<uids.size(); iu++) {
2161 int uid = uids.keyAt(iu);
2162 PackageState pkgState = uids.valueAt(iu);
2163 final int NPROCS = pkgState.mProcesses.size();
2164 final int NSRVS = pkgState.mServices.size();
2165 for (int iproc=0; iproc<NPROCS; iproc++) {
2166 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2167 pw.print("pkgproc,");
2168 pw.print(pkgName);
2169 pw.print(",");
2170 pw.print(uid);
2171 pw.print(",");
2172 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2173 dumpAllProcessStateCheckin(pw, proc, now);
2174 pw.println();
2175 if (proc.mPssTableSize > 0) {
2176 pw.print("pkgpss,");
2177 pw.print(pkgName);
2178 pw.print(",");
2179 pw.print(uid);
2180 pw.print(",");
2181 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2182 dumpAllProcessPssCheckin(pw, proc);
2183 pw.println();
2184 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002185 if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0
2186 || proc.mNumCachedKill > 0) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002187 pw.print("pkgkills,");
2188 pw.print(pkgName);
2189 pw.print(",");
2190 pw.print(uid);
2191 pw.print(",");
2192 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2193 pw.print(",");
2194 pw.print(proc.mNumExcessiveWake);
2195 pw.print(",");
2196 pw.print(proc.mNumExcessiveCpu);
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002197 pw.print(",");
2198 pw.print(proc.mNumCachedKill);
2199 pw.print(",");
2200 pw.print(proc.mMinCachedKillPss);
2201 pw.print(":");
2202 pw.print(proc.mAvgCachedKillPss);
2203 pw.print(":");
2204 pw.print(proc.mMaxCachedKillPss);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002205 pw.println();
2206 }
2207 }
2208 for (int isvc=0; isvc<NSRVS; isvc++) {
2209 String serviceName = collapseString(pkgName,
2210 pkgState.mServices.keyAt(isvc));
2211 ServiceState svc = pkgState.mServices.valueAt(isvc);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002212 dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, serviceName,
2213 svc, ServiceState.SERVICE_RUN, svc.mRunCount,
2214 svc.mRunState, svc.mRunStartTime, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002215 dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, serviceName,
2216 svc, ServiceState.SERVICE_STARTED, svc.mStartedCount,
2217 svc.mStartedState, svc.mStartedStartTime, now);
2218 dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, serviceName,
2219 svc, ServiceState.SERVICE_BOUND, svc.mBoundCount,
2220 svc.mBoundState, svc.mBoundStartTime, now);
2221 dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, serviceName,
2222 svc, ServiceState.SERVICE_EXEC, svc.mExecCount,
2223 svc.mExecState, svc.mExecStartTime, now);
2224 }
2225 }
2226 }
2227
2228 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2229 for (int ip=0; ip<procMap.size(); ip++) {
2230 String procName = procMap.keyAt(ip);
2231 SparseArray<ProcessState> uids = procMap.valueAt(ip);
2232 for (int iu=0; iu<uids.size(); iu++) {
2233 int uid = uids.keyAt(iu);
2234 ProcessState procState = uids.valueAt(iu);
2235 if (procState.mDurationsTableSize > 0) {
2236 pw.print("proc,");
2237 pw.print(procName);
2238 pw.print(",");
2239 pw.print(uid);
2240 dumpAllProcessStateCheckin(pw, procState, now);
2241 pw.println();
2242 }
2243 if (procState.mPssTableSize > 0) {
2244 pw.print("pss,");
2245 pw.print(procName);
2246 pw.print(",");
2247 pw.print(uid);
2248 dumpAllProcessPssCheckin(pw, procState);
2249 pw.println();
2250 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002251 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0
2252 || procState.mNumCachedKill > 0) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002253 pw.print("kills,");
2254 pw.print(procName);
2255 pw.print(",");
2256 pw.print(uid);
2257 pw.print(",");
2258 pw.print(procState.mNumExcessiveWake);
2259 pw.print(",");
2260 pw.print(procState.mNumExcessiveCpu);
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002261 pw.print(",");
2262 pw.print(procState.mNumCachedKill);
2263 pw.print(",");
2264 pw.print(procState.mMinCachedKillPss);
2265 pw.print(":");
2266 pw.print(procState.mAvgCachedKillPss);
2267 pw.print(":");
2268 pw.print(procState.mMaxCachedKillPss);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002269 pw.println();
2270 }
2271 }
2272 }
2273 pw.print("total");
2274 dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor,
2275 mStartTime, now);
2276 pw.println();
2277 }
2278
Dianne Hackborncb428552013-09-26 11:07:17 -07002279 public static class DurationsTable {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002280 public final ProcessStats mStats;
Dianne Hackborncb428552013-09-26 11:07:17 -07002281 public final String mName;
2282 public int[] mDurationsTable;
2283 public int mDurationsTableSize;
2284
2285 public DurationsTable(ProcessStats stats, String name) {
2286 mStats = stats;
2287 mName = name;
2288 }
2289
2290 void copyDurationsTo(DurationsTable other) {
2291 if (mDurationsTable != null) {
2292 mStats.mAddLongTable = new int[mDurationsTable.length];
2293 mStats.mAddLongTableSize = 0;
2294 for (int i=0; i<mDurationsTableSize; i++) {
2295 int origEnt = mDurationsTable[i];
2296 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2297 int newOff = mStats.addLongData(i, type, 1);
2298 mStats.mAddLongTable[i] = newOff | type;
2299 mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0));
2300 }
2301 other.mDurationsTable = mStats.mAddLongTable;
2302 other.mDurationsTableSize = mStats.mAddLongTableSize;
2303 } else {
2304 other.mDurationsTable = null;
2305 other.mDurationsTableSize = 0;
2306 }
2307 }
2308
2309 void addDurations(DurationsTable other) {
2310 for (int i=0; i<other.mDurationsTableSize; i++) {
2311 int ent = other.mDurationsTable[i];
2312 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2313 if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
2314 + other.mStats.getLong(ent, 0));
2315 addDuration(state, other.mStats.getLong(ent, 0));
2316 }
2317 }
2318
2319 void resetDurationsSafely() {
2320 mDurationsTable = null;
2321 mDurationsTableSize = 0;
2322 }
2323
2324 void writeDurationsToParcel(Parcel out) {
2325 out.writeInt(mDurationsTableSize);
2326 for (int i=0; i<mDurationsTableSize; i++) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002327 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
Dianne Hackborncb428552013-09-26 11:07:17 -07002328 + printLongOffset(mDurationsTable[i]));
2329 out.writeInt(mDurationsTable[i]);
2330 }
2331 }
2332
2333 boolean readDurationsFromParcel(Parcel in) {
2334 mDurationsTable = mStats.readTableFromParcel(in, mName, "durations");
2335 if (mDurationsTable == BAD_TABLE) {
2336 return false;
2337 }
2338 mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
2339 return true;
2340 }
2341
2342 void addDuration(int state, long dur) {
2343 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
2344 int off;
2345 if (idx >= 0) {
2346 off = mDurationsTable[idx];
2347 } else {
2348 mStats.mAddLongTable = mDurationsTable;
2349 mStats.mAddLongTableSize = mDurationsTableSize;
2350 off = mStats.addLongData(~idx, state, 1);
2351 mDurationsTable = mStats.mAddLongTable;
2352 mDurationsTableSize = mStats.mAddLongTableSize;
2353 }
2354 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
2355 if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
2356 + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
2357 longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
2358 }
2359
2360 long getDuration(int state, long now) {
2361 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
2362 return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
2363 }
2364 }
2365
2366 public static final class ProcessState extends DurationsTable {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002367 public final ProcessState mCommonProcess;
2368 public final String mPackage;
2369 public final int mUid;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002370
2371 //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
2372 int mCurState = STATE_NOTHING;
2373 long mStartTime;
2374
2375 int mLastPssState = STATE_NOTHING;
2376 long mLastPssTime;
2377 int[] mPssTable;
2378 int mPssTableSize;
2379
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002380 boolean mActive;
2381 int mNumActiveServices;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002382 int mNumStartedServices;
2383
2384 int mNumExcessiveWake;
2385 int mNumExcessiveCpu;
2386
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002387 int mNumCachedKill;
2388 long mMinCachedKillPss;
2389 long mAvgCachedKillPss;
2390 long mMaxCachedKillPss;
2391
Dianne Hackbornd2932242013-08-05 18:18:42 -07002392 boolean mMultiPackage;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002393 boolean mDead;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002394
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002395 public long mTmpTotalTime;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002396
2397 /**
2398 * Create a new top-level process state, for the initial case where there is only
2399 * a single package running in a process. The initial state is not running.
2400 */
2401 public ProcessState(ProcessStats processStats, String pkg, int uid, String name) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002402 super(processStats, name);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002403 mCommonProcess = this;
2404 mPackage = pkg;
2405 mUid = uid;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002406 }
2407
2408 /**
2409 * Create a new per-package process state for an existing top-level process
2410 * state. The current running state of the top-level process is also copied,
2411 * marked as started running at 'now'.
2412 */
2413 public ProcessState(ProcessState commonProcess, String pkg, int uid, String name,
2414 long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002415 super(commonProcess.mStats, name);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002416 mCommonProcess = commonProcess;
2417 mPackage = pkg;
2418 mUid = uid;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002419 mCurState = commonProcess.mCurState;
2420 mStartTime = now;
2421 }
2422
2423 ProcessState clone(String pkg, long now) {
2424 ProcessState pnew = new ProcessState(this, pkg, mUid, mName, now);
Dianne Hackborncb428552013-09-26 11:07:17 -07002425 copyDurationsTo(pnew);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002426 if (mPssTable != null) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002427 mStats.mAddLongTable = new int[mPssTable.length];
2428 mStats.mAddLongTableSize = 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002429 for (int i=0; i<mPssTableSize; i++) {
2430 int origEnt = mPssTable[i];
2431 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002432 int newOff = mStats.addLongData(i, type, PSS_COUNT);
2433 mStats.mAddLongTable[i] = newOff | type;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002434 for (int j=0; j<PSS_COUNT; j++) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002435 mStats.setLong(newOff, j, mStats.getLong(origEnt, j));
Dianne Hackbornd2932242013-08-05 18:18:42 -07002436 }
2437 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002438 pnew.mPssTable = mStats.mAddLongTable;
2439 pnew.mPssTableSize = mStats.mAddLongTableSize;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002440 }
2441 pnew.mNumExcessiveWake = mNumExcessiveWake;
2442 pnew.mNumExcessiveCpu = mNumExcessiveCpu;
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002443 pnew.mNumCachedKill = mNumCachedKill;
2444 pnew.mMinCachedKillPss = mMinCachedKillPss;
2445 pnew.mAvgCachedKillPss = mAvgCachedKillPss;
2446 pnew.mMaxCachedKillPss = mMaxCachedKillPss;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002447 pnew.mActive = mActive;
Dianne Hackborn164371f2013-10-01 19:10:13 -07002448 pnew.mNumActiveServices = mNumActiveServices;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002449 pnew.mNumStartedServices = mNumStartedServices;
2450 return pnew;
2451 }
2452
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002453 void add(ProcessState other) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002454 addDurations(other);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002455 for (int i=0; i<other.mPssTableSize; i++) {
2456 int ent = other.mPssTable[i];
2457 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2458 addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
2459 other.mStats.getLong(ent, PSS_MINIMUM),
2460 other.mStats.getLong(ent, PSS_AVERAGE),
2461 other.mStats.getLong(ent, PSS_MAXIMUM),
2462 other.mStats.getLong(ent, PSS_USS_MINIMUM),
2463 other.mStats.getLong(ent, PSS_USS_AVERAGE),
2464 other.mStats.getLong(ent, PSS_USS_MAXIMUM));
2465 }
2466 mNumExcessiveWake += other.mNumExcessiveWake;
2467 mNumExcessiveCpu += other.mNumExcessiveCpu;
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002468 if (other.mNumCachedKill > 0) {
2469 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
2470 other.mAvgCachedKillPss, other.mMaxCachedKillPss);
2471 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002472 }
2473
Dianne Hackbornd2932242013-08-05 18:18:42 -07002474 void resetSafely(long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002475 resetDurationsSafely();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002476 mStartTime = now;
2477 mLastPssState = STATE_NOTHING;
2478 mLastPssTime = 0;
2479 mPssTable = null;
2480 mPssTableSize = 0;
2481 mNumExcessiveWake = 0;
2482 mNumExcessiveCpu = 0;
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002483 mNumCachedKill = 0;
2484 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002485 }
2486
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002487 void makeDead() {
2488 mDead = true;
2489 }
2490
2491 private void ensureNotDead() {
2492 if (!mDead) {
2493 return;
2494 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002495 Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002496 + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
2497 }
2498
Dianne Hackbornd2932242013-08-05 18:18:42 -07002499 void writeToParcel(Parcel out, long now) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002500 out.writeInt(mMultiPackage ? 1 : 0);
Dianne Hackborncb428552013-09-26 11:07:17 -07002501 writeDurationsToParcel(out);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002502 out.writeInt(mPssTableSize);
2503 for (int i=0; i<mPssTableSize; i++) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002504 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
Dianne Hackbornd2932242013-08-05 18:18:42 -07002505 + printLongOffset(mPssTable[i]));
2506 out.writeInt(mPssTable[i]);
2507 }
2508 out.writeInt(mNumExcessiveWake);
2509 out.writeInt(mNumExcessiveCpu);
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002510 out.writeInt(mNumCachedKill);
2511 if (mNumCachedKill > 0) {
2512 out.writeLong(mMinCachedKillPss);
2513 out.writeLong(mAvgCachedKillPss);
2514 out.writeLong(mMaxCachedKillPss);
2515 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002516 }
2517
2518 boolean readFromParcel(Parcel in, boolean fully) {
2519 boolean multiPackage = in.readInt() != 0;
2520 if (fully) {
2521 mMultiPackage = multiPackage;
2522 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002523 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
Dianne Hackborncb428552013-09-26 11:07:17 -07002524 if (!readDurationsFromParcel(in)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002525 return false;
2526 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002527 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002528 mPssTable = mStats.readTableFromParcel(in, mName, "pss");
Dianne Hackbornd2932242013-08-05 18:18:42 -07002529 if (mPssTable == BAD_TABLE) {
2530 return false;
2531 }
2532 mPssTableSize = mPssTable != null ? mPssTable.length : 0;
2533 mNumExcessiveWake = in.readInt();
2534 mNumExcessiveCpu = in.readInt();
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002535 mNumCachedKill = in.readInt();
2536 if (mNumCachedKill > 0) {
2537 mMinCachedKillPss = in.readLong();
2538 mAvgCachedKillPss = in.readLong();
2539 mMaxCachedKillPss = in.readLong();
2540 } else {
2541 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
2542 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002543 return true;
2544 }
2545
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002546 public void makeActive() {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002547 ensureNotDead();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002548 mActive = true;
2549 }
2550
2551 public void makeInactive() {
2552 mActive = false;
2553 }
2554
2555 public boolean isInUse() {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002556 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
2557 || mCurState != STATE_NOTHING;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002558 }
2559
Dianne Hackbornd2932242013-08-05 18:18:42 -07002560 /**
2561 * Update the current state of the given list of processes.
2562 *
2563 * @param state Current ActivityManager.PROCESS_STATE_*
2564 * @param memFactor Current mem factor constant.
2565 * @param now Current time.
2566 * @param pkgList Processes to update.
2567 */
2568 public void setState(int state, int memFactor, long now,
2569 ArrayMap<String, ProcessState> pkgList) {
2570 if (state < 0) {
2571 state = mNumStartedServices > 0
2572 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
2573 } else {
2574 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
2575 }
2576
2577 // First update the common process.
2578 mCommonProcess.setState(state, now);
2579
2580 // If the common process is not multi-package, there is nothing else to do.
2581 if (!mCommonProcess.mMultiPackage) {
2582 return;
2583 }
2584
2585 if (pkgList != null) {
2586 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2587 pullFixedProc(pkgList, ip).setState(state, now);
2588 }
2589 }
2590 }
2591
2592 void setState(int state, long now) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002593 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002594 if (mCurState != state) {
2595 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
2596 commitStateTime(now);
2597 mCurState = state;
2598 }
2599 }
2600
2601 void commitStateTime(long now) {
2602 if (mCurState != STATE_NOTHING) {
2603 long dur = now - mStartTime;
2604 if (dur > 0) {
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002605 addDuration(mCurState, dur);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002606 }
2607 }
2608 mStartTime = now;
2609 }
2610
Dianne Hackborn164371f2013-10-01 19:10:13 -07002611 void incActiveServices(String serviceName) {
2612 if (DEBUG && "".equals(mName)) {
2613 RuntimeException here = new RuntimeException("here");
2614 here.fillInStackTrace();
2615 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
2616 + " to " + (mNumActiveServices+1), here);
2617 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002618 if (mCommonProcess != this) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002619 mCommonProcess.incActiveServices(serviceName);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002620 }
2621 mNumActiveServices++;
2622 }
2623
Dianne Hackborn164371f2013-10-01 19:10:13 -07002624 void decActiveServices(String serviceName) {
2625 if (DEBUG && "".equals(mName)) {
2626 RuntimeException here = new RuntimeException("here");
2627 here.fillInStackTrace();
2628 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
2629 + " to " + (mNumActiveServices-1), here);
2630 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002631 if (mCommonProcess != this) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002632 mCommonProcess.decActiveServices(serviceName);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002633 }
2634 mNumActiveServices--;
2635 if (mNumActiveServices < 0) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002636 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
2637 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
2638 mNumActiveServices = 0;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002639 }
2640 }
2641
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002642 void incStartedServices(int memFactor, long now, String serviceName) {
2643 if (false) {
2644 RuntimeException here = new RuntimeException("here");
2645 here.fillInStackTrace();
2646 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
2647 + " to " + (mNumStartedServices+1), here);
2648 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002649 if (mCommonProcess != this) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002650 mCommonProcess.incStartedServices(memFactor, now, serviceName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002651 }
2652 mNumStartedServices++;
2653 if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002654 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002655 }
2656 }
2657
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002658 void decStartedServices(int memFactor, long now, String serviceName) {
2659 if (false) {
2660 RuntimeException here = new RuntimeException("here");
2661 here.fillInStackTrace();
2662 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
2663 + " to " + (mNumStartedServices-1), here);
2664 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002665 if (mCommonProcess != this) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002666 mCommonProcess.decStartedServices(memFactor, now, serviceName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002667 }
2668 mNumStartedServices--;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002669 if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
2670 setState(STATE_NOTHING, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002671 } else if (mNumStartedServices < 0) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002672 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
Dianne Hackbornd2932242013-08-05 18:18:42 -07002673 + mPackage + " uid=" + mUid + " name=" + mName);
Dianne Hackborn164371f2013-10-01 19:10:13 -07002674 mNumStartedServices = 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002675 }
2676 }
2677
Dianne Hackborncb428552013-09-26 11:07:17 -07002678 public void addPss(long pss, long uss, boolean always,
2679 ArrayMap<String, ProcessState> pkgList) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002680 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002681 if (!always) {
2682 if (mLastPssState == mCurState && SystemClock.uptimeMillis()
2683 < (mLastPssTime+(30*1000))) {
2684 return;
2685 }
2686 }
2687 mLastPssState = mCurState;
2688 mLastPssTime = SystemClock.uptimeMillis();
2689 if (mCurState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002690 // First update the common process.
2691 mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
2692
2693 // If the common process is not multi-package, there is nothing else to do.
2694 if (!mCommonProcess.mMultiPackage) {
2695 return;
2696 }
2697
2698 if (pkgList != null) {
2699 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2700 pullFixedProc(pkgList, ip).addPss(mCurState, 1,
2701 pss, pss, pss, uss, uss, uss);
2702 }
2703 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002704 }
2705 }
2706
2707 void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
2708 long avgUss, long maxUss) {
2709 int idx = binarySearch(mPssTable, mPssTableSize, state);
2710 int off;
2711 if (idx >= 0) {
2712 off = mPssTable[idx];
2713 } else {
2714 mStats.mAddLongTable = mPssTable;
2715 mStats.mAddLongTableSize = mPssTableSize;
2716 off = mStats.addLongData(~idx, state, PSS_COUNT);
2717 mPssTable = mStats.mAddLongTable;
2718 mPssTableSize = mStats.mAddLongTableSize;
2719 }
2720 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
2721 idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
2722 long count = longs[idx+PSS_SAMPLE_COUNT];
2723 if (count == 0) {
2724 longs[idx+PSS_SAMPLE_COUNT] = inCount;
2725 longs[idx+PSS_MINIMUM] = minPss;
2726 longs[idx+PSS_AVERAGE] = avgPss;
2727 longs[idx+PSS_MAXIMUM] = maxPss;
2728 longs[idx+PSS_USS_MINIMUM] = minUss;
2729 longs[idx+PSS_USS_AVERAGE] = avgUss;
2730 longs[idx+PSS_USS_MAXIMUM] = maxUss;
2731 } else {
2732 longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
2733 if (longs[idx+PSS_MINIMUM] > minPss) {
2734 longs[idx+PSS_MINIMUM] = minPss;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002735 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002736 longs[idx+PSS_AVERAGE] = (long)(
2737 ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
2738 / (count+inCount) );
2739 if (longs[idx+PSS_MAXIMUM] < maxPss) {
2740 longs[idx+PSS_MAXIMUM] = maxPss;
2741 }
2742 if (longs[idx+PSS_USS_MINIMUM] > minUss) {
2743 longs[idx+PSS_USS_MINIMUM] = minUss;
2744 }
2745 longs[idx+PSS_USS_AVERAGE] = (long)(
2746 ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
2747 / (count+inCount) );
2748 if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
2749 longs[idx+PSS_USS_MAXIMUM] = maxUss;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002750 }
2751 }
2752 }
2753
2754 public void reportExcessiveWake(ArrayMap<String, ProcessState> pkgList) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002755 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002756 mCommonProcess.mNumExcessiveWake++;
2757 if (!mCommonProcess.mMultiPackage) {
2758 return;
2759 }
2760
2761 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2762 pullFixedProc(pkgList, ip).mNumExcessiveWake++;
2763 }
2764 }
2765
2766 public void reportExcessiveCpu(ArrayMap<String, ProcessState> pkgList) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002767 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002768 mCommonProcess.mNumExcessiveCpu++;
2769 if (!mCommonProcess.mMultiPackage) {
2770 return;
2771 }
2772
2773 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2774 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
2775 }
2776 }
2777
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002778 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
2779 if (mNumCachedKill <= 0) {
2780 mNumCachedKill = num;
2781 mMinCachedKillPss = minPss;
2782 mAvgCachedKillPss = avgPss;
2783 mMaxCachedKillPss = maxPss;
2784 } else {
2785 if (minPss < mMinCachedKillPss) {
2786 mMinCachedKillPss = minPss;
2787 }
2788 if (maxPss > mMaxCachedKillPss) {
2789 mMaxCachedKillPss = maxPss;
2790 }
2791 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
2792 / (mNumCachedKill+num) );
2793 mNumCachedKill += num;
2794 }
2795 }
2796
2797 public void reportCachedKill(ArrayMap<String, ProcessState> pkgList, long pss) {
2798 ensureNotDead();
2799 mCommonProcess.addCachedKill(1, pss, pss, pss);
2800 if (!mCommonProcess.mMultiPackage) {
2801 return;
2802 }
2803
2804 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2805 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
2806 }
2807 }
2808
Dianne Hackbornd2932242013-08-05 18:18:42 -07002809 ProcessState pullFixedProc(String pkgName) {
2810 if (mMultiPackage) {
2811 // The array map is still pointing to a common process state
2812 // that is now shared across packages. Update it to point to
2813 // the new per-package state.
Dianne Hackborn164371f2013-10-01 19:10:13 -07002814 ProcessState proc = mStats.mPackages.get(pkgName, mUid).mProcesses.get(mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002815 if (proc == null) {
2816 throw new IllegalStateException("Didn't create per-package process");
2817 }
2818 return proc;
2819 }
2820 return this;
2821 }
2822
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002823 private ProcessState pullFixedProc(ArrayMap<String, ProcessState> pkgList, int index) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002824 ProcessState proc = pkgList.valueAt(index);
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002825 if (mDead && proc.mCommonProcess != proc) {
Dianne Hackborn53459a72013-09-17 17:14:57 -07002826 // Somehow we are contining to use a process state that is dead, because
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002827 // it was not being told it was active during the last commit. We can recover
2828 // from this by generating a fresh new state, but this is bad because we
2829 // are losing whatever data we had in the old process state.
2830 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
2831 + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
2832 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mName);
2833 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002834 if (proc.mMultiPackage) {
2835 // The array map is still pointing to a common process state
2836 // that is now shared across packages. Update it to point to
2837 // the new per-package state.
Dianne Hackborna0332372013-09-13 18:34:13 -07002838 PackageState pkg = mStats.mPackages.get(pkgList.keyAt(index), proc.mUid);
2839 if (pkg == null) {
2840 throw new IllegalStateException("No existing package "
Dianne Hackborn164371f2013-10-01 19:10:13 -07002841 + pkgList.keyAt(index) + "/" + proc.mUid
2842 + " for multi-proc " + proc.mName);
Dianne Hackborna0332372013-09-13 18:34:13 -07002843 }
2844 proc = pkg.mProcesses.get(proc.mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002845 if (proc == null) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002846 throw new IllegalStateException("Didn't create per-package process "
2847 + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002848 }
2849 pkgList.setValueAt(index, proc);
2850 }
2851 return proc;
2852 }
2853
2854 long getDuration(int state, long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002855 long time = super.getDuration(state, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002856 if (mCurState == state) {
2857 time += now - mStartTime;
2858 }
2859 return time;
2860 }
2861
2862 long getPssSampleCount(int state) {
2863 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002864 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002865 }
2866
2867 long getPssMinimum(int state) {
2868 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002869 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002870 }
2871
2872 long getPssAverage(int state) {
2873 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002874 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002875 }
2876
2877 long getPssMaximum(int state) {
2878 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002879 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002880 }
2881
2882 long getPssUssMinimum(int state) {
2883 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002884 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002885 }
2886
2887 long getPssUssAverage(int state) {
2888 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002889 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002890 }
2891
2892 long getPssUssMaximum(int state) {
2893 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002894 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002895 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002896
2897 public String toString() {
2898 StringBuilder sb = new StringBuilder(128);
2899 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
2900 .append(" ").append(mName).append("/").append(mUid)
2901 .append(" pkg=").append(mPackage);
2902 if (mMultiPackage) sb.append(" (multi)");
2903 if (mCommonProcess != this) sb.append(" (sub)");
2904 sb.append("}");
2905 return sb.toString();
2906 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002907 }
2908
Dianne Hackborncb428552013-09-26 11:07:17 -07002909 public static final class ServiceState extends DurationsTable {
Dianne Hackborn69cb00b2013-08-09 16:16:56 -07002910 public final String mPackage;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002911 public final String mProcessName;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002912 ProcessState mProc;
2913
Dianne Hackborn164371f2013-10-01 19:10:13 -07002914 Object mOwner;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002915
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002916 public static final int SERVICE_RUN = 0;
2917 public static final int SERVICE_STARTED = 1;
2918 public static final int SERVICE_BOUND = 2;
2919 public static final int SERVICE_EXEC = 3;
2920 static final int SERVICE_COUNT = 4;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002921
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002922 int mRunCount;
2923 public int mRunState = STATE_NOTHING;
2924 long mRunStartTime;
2925
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002926 boolean mStarted;
2927 boolean mRestarting;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002928 int mStartedCount;
2929 public int mStartedState = STATE_NOTHING;
2930 long mStartedStartTime;
2931
2932 int mBoundCount;
2933 public int mBoundState = STATE_NOTHING;
2934 long mBoundStartTime;
2935
2936 int mExecCount;
2937 public int mExecState = STATE_NOTHING;
2938 long mExecStartTime;
2939
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002940 public ServiceState(ProcessStats processStats, String pkg, String name,
2941 String processName, ProcessState proc) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002942 super(processStats, name);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002943 mPackage = pkg;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002944 mProcessName = processName;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002945 mProc = proc;
2946 }
2947
Dianne Hackborn164371f2013-10-01 19:10:13 -07002948 public void applyNewOwner(Object newOwner) {
2949 if (mOwner != newOwner) {
2950 if (mOwner == null) {
2951 mOwner = newOwner;
2952 mProc.incActiveServices(mName);
2953 } else {
2954 // There was already an old owner, reset this object for its
2955 // new owner.
2956 mOwner = newOwner;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002957 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002958 long now = SystemClock.uptimeMillis();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002959 if (mStarted) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002960 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
2961 + " from " + mOwner + " while started: pkg="
2962 + mPackage + " service=" + mName + " proc=" + mProc);
2963 setStarted(false, 0, now);
2964 }
2965 if (mBoundState != STATE_NOTHING) {
2966 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
2967 + " from " + mOwner + " while bound: pkg="
2968 + mPackage + " service=" + mName + " proc=" + mProc);
2969 setBound(false, 0, now);
2970 }
2971 if (mExecState != STATE_NOTHING) {
2972 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
2973 + " from " + mOwner + " while executing: pkg="
2974 + mPackage + " service=" + mName + " proc=" + mProc);
2975 setExecuting(false, 0, now);
2976 }
2977 }
2978 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002979 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002980 }
2981
Dianne Hackborn878deb32013-10-14 16:55:09 -07002982 public void clearCurrentOwner(Object owner, boolean silently) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002983 if (mOwner == owner) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002984 mProc.decActiveServices(mName);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002985 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002986 long now = SystemClock.uptimeMillis();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002987 if (mStarted) {
Dianne Hackborn878deb32013-10-14 16:55:09 -07002988 if (!silently) {
2989 Slog.wtfStack(TAG, "Service owner " + owner
2990 + " cleared while started: pkg=" + mPackage + " service="
2991 + mName + " proc=" + mProc);
2992 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002993 setStarted(false, 0, now);
2994 }
2995 if (mBoundState != STATE_NOTHING) {
Dianne Hackborn878deb32013-10-14 16:55:09 -07002996 if (!silently) {
2997 Slog.wtfStack(TAG, "Service owner " + owner
2998 + " cleared while bound: pkg=" + mPackage + " service="
2999 + mName + " proc=" + mProc);
3000 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003001 setBound(false, 0, now);
3002 }
3003 if (mExecState != STATE_NOTHING) {
Dianne Hackborn878deb32013-10-14 16:55:09 -07003004 if (!silently) {
3005 Slog.wtfStack(TAG, "Service owner " + owner
3006 + " cleared while exec: pkg=" + mPackage + " service="
3007 + mName + " proc=" + mProc);
3008 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003009 setExecuting(false, 0, now);
3010 }
3011 }
Dianne Hackborn878deb32013-10-14 16:55:09 -07003012 mOwner = null;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003013 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003014 }
3015
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003016 public boolean isInUse() {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003017 return mOwner != null;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003018 }
3019
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003020 void add(ServiceState other) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003021 addDurations(other);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003022 mRunCount += other.mRunCount;
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003023 mStartedCount += other.mStartedCount;
3024 mBoundCount += other.mBoundCount;
3025 mExecCount += other.mExecCount;
3026 }
3027
Dianne Hackbornd2932242013-08-05 18:18:42 -07003028 void resetSafely(long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003029 resetDurationsSafely();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003030 mRunCount = mRunState != STATE_NOTHING ? 1 : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003031 mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
3032 mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
3033 mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
Dianne Hackborncb428552013-09-26 11:07:17 -07003034 mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003035 }
3036
3037 void writeToParcel(Parcel out, long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003038 writeDurationsToParcel(out);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003039 out.writeInt(mRunCount);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003040 out.writeInt(mStartedCount);
3041 out.writeInt(mBoundCount);
3042 out.writeInt(mExecCount);
3043 }
3044
3045 boolean readFromParcel(Parcel in) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003046 if (!readDurationsFromParcel(in)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003047 return false;
3048 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003049 mRunCount = in.readInt();
Dianne Hackbornd2932242013-08-05 18:18:42 -07003050 mStartedCount = in.readInt();
3051 mBoundCount = in.readInt();
3052 mExecCount = in.readInt();
3053 return true;
3054 }
3055
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003056 void commitStateTime(long now) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003057 if (mRunState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003058 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003059 mRunStartTime = now;
3060 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003061 if (mStartedState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003062 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003063 now - mStartedStartTime);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003064 mStartedStartTime = now;
3065 }
3066 if (mBoundState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003067 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003068 mBoundStartTime = now;
3069 }
3070 if (mExecState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003071 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003072 mExecStartTime = now;
3073 }
3074 }
3075
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003076 private void updateRunning(int memFactor, long now) {
3077 final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
3078 || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
3079 if (mRunState != state) {
3080 if (mRunState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003081 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT),
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003082 now - mRunStartTime);
3083 } else if (state != STATE_NOTHING) {
3084 mRunCount++;
3085 }
3086 mRunState = state;
3087 mRunStartTime = now;
3088 }
3089 }
3090
Dianne Hackbornd2932242013-08-05 18:18:42 -07003091 public void setStarted(boolean started, int memFactor, long now) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003092 if (mOwner == null) {
3093 Slog.wtf(TAG, "Starting service " + this + " without owner");
Dianne Hackbornd2932242013-08-05 18:18:42 -07003094 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003095 mStarted = started;
3096 updateStartedState(memFactor, now);
3097 }
3098
3099 public void setRestarting(boolean restarting, int memFactor, long now) {
3100 mRestarting = restarting;
3101 updateStartedState(memFactor, now);
3102 }
3103
3104 void updateStartedState(int memFactor, long now) {
Dianne Hackbornae36b232013-09-03 18:12:53 -07003105 final boolean wasStarted = mStartedState != STATE_NOTHING;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003106 final boolean started = mStarted || mRestarting;
Dianne Hackbornae36b232013-09-03 18:12:53 -07003107 final int state = started ? memFactor : STATE_NOTHING;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003108 if (mStartedState != state) {
3109 if (mStartedState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003110 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003111 now - mStartedStartTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003112 } else if (started) {
3113 mStartedCount++;
3114 }
3115 mStartedState = state;
3116 mStartedStartTime = now;
Dianne Hackbornae36b232013-09-03 18:12:53 -07003117 mProc = mProc.pullFixedProc(mPackage);
3118 if (wasStarted != started) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003119 if (started) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003120 mProc.incStartedServices(memFactor, now, mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003121 } else {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003122 mProc.decStartedServices(memFactor, now, mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003123 }
3124 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003125 updateRunning(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003126 }
3127 }
3128
3129 public void setBound(boolean bound, int memFactor, long now) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003130 if (mOwner == null) {
3131 Slog.wtf(TAG, "Binding service " + this + " without owner");
Dianne Hackbornd2932242013-08-05 18:18:42 -07003132 }
Dianne Hackbornae36b232013-09-03 18:12:53 -07003133 final int state = bound ? memFactor : STATE_NOTHING;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003134 if (mBoundState != state) {
3135 if (mBoundState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003136 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003137 now - mBoundStartTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003138 } else if (bound) {
3139 mBoundCount++;
3140 }
3141 mBoundState = state;
3142 mBoundStartTime = now;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003143 updateRunning(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003144 }
3145 }
3146
3147 public void setExecuting(boolean executing, int memFactor, long now) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003148 if (mOwner == null) {
3149 Slog.wtf(TAG, "Executing service " + this + " without owner");
Dianne Hackbornd2932242013-08-05 18:18:42 -07003150 }
Dianne Hackbornae36b232013-09-03 18:12:53 -07003151 final int state = executing ? memFactor : STATE_NOTHING;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003152 if (mExecState != state) {
3153 if (mExecState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003154 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003155 } else if (executing) {
3156 mExecCount++;
3157 }
3158 mExecState = state;
3159 mExecStartTime = now;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003160 updateRunning(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003161 }
3162 }
3163
Dianne Hackbornd2932242013-08-05 18:18:42 -07003164 private long getDuration(int opType, int curState, long startTime, int memFactor,
3165 long now) {
3166 int state = opType + (memFactor*SERVICE_COUNT);
Dianne Hackborncb428552013-09-26 11:07:17 -07003167 long time = getDuration(state, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003168 if (curState == memFactor) {
3169 time += now - startTime;
3170 }
3171 return time;
3172 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003173
3174 public String toString() {
3175 return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
3176 + " " + mName + " pkg=" + mPackage + " proc="
3177 + Integer.toHexString(System.identityHashCode(this)) + "}";
3178 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003179 }
3180
3181 public static final class PackageState {
3182 public final ArrayMap<String, ProcessState> mProcesses
3183 = new ArrayMap<String, ProcessState>();
3184 public final ArrayMap<String, ServiceState> mServices
3185 = new ArrayMap<String, ServiceState>();
Dianne Hackborncb428552013-09-26 11:07:17 -07003186 public final String mPackageName;
3187 public final int mUid;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003188
Dianne Hackborncb428552013-09-26 11:07:17 -07003189 public PackageState(String packageName, int uid) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003190 mUid = uid;
Dianne Hackborncb428552013-09-26 11:07:17 -07003191 mPackageName = packageName;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003192 }
3193 }
3194
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003195 public static final class ProcessDataCollection {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003196 final int[] screenStates;
3197 final int[] memStates;
3198 final int[] procStates;
3199
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003200 public long totalTime;
3201 public long numPss;
3202 public long minPss;
3203 public long avgPss;
3204 public long maxPss;
3205 public long minUss;
3206 public long avgUss;
3207 public long maxUss;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003208
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003209 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003210 screenStates = _screenStates;
3211 memStates = _memStates;
3212 procStates = _procStates;
3213 }
3214
3215 void print(PrintWriter pw, long overallTime, boolean full) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003216 if (totalTime > overallTime) {
3217 pw.print("*");
3218 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003219 printPercent(pw, (double) totalTime / (double) overallTime);
3220 if (numPss > 0) {
3221 pw.print(" (");
3222 printSizeValue(pw, minPss * 1024);
3223 pw.print("-");
3224 printSizeValue(pw, avgPss * 1024);
3225 pw.print("-");
3226 printSizeValue(pw, maxPss * 1024);
3227 pw.print("/");
3228 printSizeValue(pw, minUss * 1024);
3229 pw.print("-");
3230 printSizeValue(pw, avgUss * 1024);
3231 pw.print("-");
3232 printSizeValue(pw, maxUss * 1024);
3233 if (full) {
3234 pw.print(" over ");
3235 pw.print(numPss);
3236 }
3237 pw.print(")");
3238 }
3239 }
3240 }
3241}