blob: 882bec913f69fcfcc484dfc388127f39669d5307 [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;
Adam Lesinski776abc22014-03-07 11:30:59 -050032
33import com.android.internal.util.GrowingArrayUtils;
34
Dianne Hackbornd2932242013-08-05 18:18:42 -070035import dalvik.system.VMRuntime;
Adam Lesinski776abc22014-03-07 11:30:59 -050036import libcore.util.EmptyArray;
Dianne Hackbornd2932242013-08-05 18:18:42 -070037
Dianne Hackborn60444fd2013-08-08 21:57:14 -070038import java.io.IOException;
39import java.io.InputStream;
Dianne Hackbornd2932242013-08-05 18:18:42 -070040import java.io.PrintWriter;
41import java.util.ArrayList;
42import java.util.Arrays;
43import java.util.Collections;
44import java.util.Comparator;
45import java.util.Objects;
46
Dianne Hackborn8a0de582013-08-07 15:22:07 -070047public final class ProcessStats implements Parcelable {
Dianne Hackbornd2932242013-08-05 18:18:42 -070048 static final String TAG = "ProcessStats";
49 static final boolean DEBUG = false;
Dianne Hackborn164371f2013-10-01 19:10:13 -070050 static final boolean DEBUG_PARCEL = false;
Dianne Hackborn8a0de582013-08-07 15:22:07 -070051
52 public static final String SERVICE_NAME = "procstats";
53
Dianne Hackborncb428552013-09-26 11:07:17 -070054 // How often the service commits its data, giving the minimum batching
55 // that is done.
56 public static long COMMIT_PERIOD = 3*60*60*1000; // Commit current stats every 3 hours
57
Dianne Hackbornd2932242013-08-05 18:18:42 -070058 public static final int STATE_NOTHING = -1;
59 public static final int STATE_PERSISTENT = 0;
60 public static final int STATE_TOP = 1;
61 public static final int STATE_IMPORTANT_FOREGROUND = 2;
62 public static final int STATE_IMPORTANT_BACKGROUND = 3;
63 public static final int STATE_BACKUP = 4;
64 public static final int STATE_HEAVY_WEIGHT = 5;
65 public static final int STATE_SERVICE = 6;
66 public static final int STATE_SERVICE_RESTARTING = 7;
67 public static final int STATE_RECEIVER = 8;
68 public static final int STATE_HOME = 9;
69 public static final int STATE_LAST_ACTIVITY = 10;
70 public static final int STATE_CACHED_ACTIVITY = 11;
71 public static final int STATE_CACHED_ACTIVITY_CLIENT = 12;
72 public static final int STATE_CACHED_EMPTY = 13;
73 public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
74
75 public static final int PSS_SAMPLE_COUNT = 0;
76 public static final int PSS_MINIMUM = 1;
77 public static final int PSS_AVERAGE = 2;
78 public static final int PSS_MAXIMUM = 3;
79 public static final int PSS_USS_MINIMUM = 4;
80 public static final int PSS_USS_AVERAGE = 5;
81 public static final int PSS_USS_MAXIMUM = 6;
82 public static final int PSS_COUNT = PSS_USS_MAXIMUM+1;
83
84 public static final int ADJ_NOTHING = -1;
85 public static final int ADJ_MEM_FACTOR_NORMAL = 0;
86 public static final int ADJ_MEM_FACTOR_MODERATE = 1;
87 public static final int ADJ_MEM_FACTOR_LOW = 2;
88 public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
89 public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
90 public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
91 public static final int ADJ_SCREEN_OFF = 0;
92 public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
93 public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
94
95 public static final int FLAG_COMPLETE = 1<<0;
96 public static final int FLAG_SHUTDOWN = 1<<1;
97 public static final int FLAG_SYSPROPS = 1<<2;
98
Dianne Hackborn8a0de582013-08-07 15:22:07 -070099 public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
100 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
101
102 public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
103
104 public static final int[] NON_CACHED_PROC_STATES = new int[] {
105 STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700106 STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT,
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700107 STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
108 };
109
110 public static final int[] BACKGROUND_PROC_STATES = new int[] {
111 STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
112 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
Dianne Hackbornd2932242013-08-05 18:18:42 -0700113 };
114
115 // Map from process states to the states we track.
116 static final int[] PROCESS_STATE_TO_STATE = new int[] {
117 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
118 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
119 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
120 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
121 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
122 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP
123 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
124 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE
125 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER
126 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME
127 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
128 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
129 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
130 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
131 };
132
133 public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
134 STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
135 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER,
136 STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
137 STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
138 };
139
140 static final String[] STATE_NAMES = new String[] {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700141 "Persist", "Top ", "ImpFg ", "ImpBg ",
142 "Backup ", "HeavyWt", "Service", "ServRst",
143 "Receivr", "Home ",
144 "LastAct", "CchAct ", "CchCAct", "CchEmty"
Dianne Hackbornd2932242013-08-05 18:18:42 -0700145 };
146
147 public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
148 "off", "on"
149 };
150
151 public static final String[] ADJ_MEM_NAMES_CSV = new String[] {
152 "norm", "mod", "low", "crit"
153 };
154
155 public static final String[] STATE_NAMES_CSV = new String[] {
156 "pers", "top", "impfg", "impbg", "backup", "heavy",
157 "service", "service-rs", "receiver", "home", "lastact",
158 "cch-activity", "cch-aclient", "cch-empty"
159 };
160
161 static final String[] ADJ_SCREEN_TAGS = new String[] {
162 "0", "1"
163 };
164
165 static final String[] ADJ_MEM_TAGS = new String[] {
166 "n", "m", "l", "c"
167 };
168
169 static final String[] STATE_TAGS = new String[] {
170 "p", "t", "f", "b", "u", "w",
171 "s", "x", "r", "h", "l", "a", "c", "e"
172 };
173
174 static final String CSV_SEP = "\t";
175
176 // Current version of the parcel format.
Dianne Hackborn8472e612014-01-23 17:57:20 -0800177 private static final int PARCEL_VERSION = 14;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700178 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
179 private static final int MAGIC = 0x50535453;
180
181 // Where the "type"/"state" part of the data appears in an offset integer.
182 static int OFFSET_TYPE_SHIFT = 0;
183 static int OFFSET_TYPE_MASK = 0xff;
184 // Where the "which array" part of the data appears in an offset integer.
185 static int OFFSET_ARRAY_SHIFT = 8;
186 static int OFFSET_ARRAY_MASK = 0xff;
187 // Where the "index into array" part of the data appears in an offset integer.
188 static int OFFSET_INDEX_SHIFT = 16;
189 static int OFFSET_INDEX_MASK = 0xffff;
190
191 public String mReadError;
192 public String mTimePeriodStartClockStr;
193 public int mFlags;
194
Dianne Hackborn8472e612014-01-23 17:57:20 -0800195 public final ProcessMap<SparseArray<PackageState>> mPackages
196 = new ProcessMap<SparseArray<PackageState>>();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700197 public final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
198
199 public final long[] mMemFactorDurations = new long[ADJ_COUNT];
200 public int mMemFactor = STATE_NOTHING;
201 public long mStartTime;
202
203 public long mTimePeriodStartClock;
204 public long mTimePeriodStartRealtime;
205 public long mTimePeriodEndRealtime;
206 String mRuntime;
207 String mWebView;
208 boolean mRunning;
209
210 static final int LONGS_SIZE = 4096;
211 final ArrayList<long[]> mLongs = new ArrayList<long[]>();
212 int mNextLong;
213
214 int[] mAddLongTable;
215 int mAddLongTableSize;
216
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -0700217 // For writing parcels.
218 ArrayMap<String, Integer> mCommonStringToIndex;
219
220 // For reading parcels.
221 ArrayList<String> mIndexToCommonString;
222
Dianne Hackbornd2932242013-08-05 18:18:42 -0700223 public ProcessStats(boolean running) {
224 mRunning = running;
225 reset();
226 }
227
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700228 public ProcessStats(Parcel in) {
229 reset();
230 readFromParcel(in);
231 }
232
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700233 public void add(ProcessStats other) {
Dianne Hackborn8472e612014-01-23 17:57:20 -0800234 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = other.mPackages.getMap();
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700235 for (int ip=0; ip<pkgMap.size(); ip++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -0800236 final String pkgName = pkgMap.keyAt(ip);
237 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700238 for (int iu=0; iu<uids.size(); iu++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -0800239 final int uid = uids.keyAt(iu);
240 final SparseArray<PackageState> versions = uids.valueAt(iu);
241 for (int iv=0; iv<versions.size(); iv++) {
242 final int vers = versions.keyAt(iv);
243 final PackageState otherState = versions.valueAt(iv);
244 final int NPROCS = otherState.mProcesses.size();
245 final int NSRVS = otherState.mServices.size();
246 for (int iproc=0; iproc<NPROCS; iproc++) {
247 ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
248 if (otherProc.mCommonProcess != otherProc) {
249 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
250 + " vers " + vers + " proc " + otherProc.mName);
251 ProcessState thisProc = getProcessStateLocked(pkgName, uid, vers,
252 otherProc.mName);
253 if (thisProc.mCommonProcess == thisProc) {
254 if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
255 thisProc.mMultiPackage = true;
256 long now = SystemClock.uptimeMillis();
257 final PackageState pkgState = getPackageStateLocked(pkgName, uid,
258 vers);
259 thisProc = thisProc.clone(thisProc.mPackage, now);
260 pkgState.mProcesses.put(thisProc.mName, thisProc);
261 }
262 thisProc.add(otherProc);
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700263 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700264 }
Dianne Hackborn8472e612014-01-23 17:57:20 -0800265 for (int isvc=0; isvc<NSRVS; isvc++) {
266 ServiceState otherSvc = otherState.mServices.valueAt(isvc);
267 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
268 + " service " + otherSvc.mName);
269 ServiceState thisSvc = getServiceStateLocked(pkgName, uid, vers,
270 otherSvc.mProcessName, otherSvc.mName);
271 thisSvc.add(otherSvc);
272 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700273 }
274 }
275 }
276
277 ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
278 for (int ip=0; ip<procMap.size(); ip++) {
279 SparseArray<ProcessState> uids = procMap.valueAt(ip);
280 for (int iu=0; iu<uids.size(); iu++) {
281 int uid = uids.keyAt(iu);
282 ProcessState otherProc = uids.valueAt(iu);
283 ProcessState thisProc = mProcesses.get(otherProc.mName, uid);
284 if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName);
285 if (thisProc == null) {
286 if (DEBUG) Slog.d(TAG, "Creating new process!");
Dianne Hackborn8472e612014-01-23 17:57:20 -0800287 thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mVersion,
288 otherProc.mName);
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700289 mProcesses.put(otherProc.mName, uid, thisProc);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800290 PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid,
291 otherProc.mVersion);
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700292 if (!thisState.mProcesses.containsKey(otherProc.mName)) {
293 thisState.mProcesses.put(otherProc.mName, thisProc);
294 }
295 }
296 thisProc.add(otherProc);
297 }
298 }
299
300 for (int i=0; i<ADJ_COUNT; i++) {
301 if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
302 + other.mMemFactorDurations[i] + " from "
303 + mMemFactorDurations[i]);
304 mMemFactorDurations[i] += other.mMemFactorDurations[i];
305 }
306
307 if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
308 mTimePeriodStartClock = other.mTimePeriodStartClock;
309 mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
310 }
311 mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
312 }
313
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700314 public static final Parcelable.Creator<ProcessStats> CREATOR
315 = new Parcelable.Creator<ProcessStats>() {
316 public ProcessStats createFromParcel(Parcel in) {
317 return new ProcessStats(in);
318 }
319
320 public ProcessStats[] newArray(int size) {
321 return new ProcessStats[size];
322 }
323 };
324
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700325 private static void printScreenLabel(PrintWriter pw, int offset) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700326 switch (offset) {
327 case ADJ_NOTHING:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700328 pw.print(" ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700329 break;
330 case ADJ_SCREEN_OFF:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700331 pw.print("SOff/");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700332 break;
333 case ADJ_SCREEN_ON:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700334 pw.print("SOn /");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700335 break;
336 default:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700337 pw.print("????/");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700338 break;
339 }
340 }
341
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700342 public static void printScreenLabelCsv(PrintWriter pw, int offset) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700343 switch (offset) {
344 case ADJ_NOTHING:
345 break;
346 case ADJ_SCREEN_OFF:
347 pw.print(ADJ_SCREEN_NAMES_CSV[0]);
348 break;
349 case ADJ_SCREEN_ON:
350 pw.print(ADJ_SCREEN_NAMES_CSV[1]);
351 break;
352 default:
353 pw.print("???");
354 break;
355 }
356 }
357
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700358 private static void printMemLabel(PrintWriter pw, int offset, char sep) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700359 switch (offset) {
360 case ADJ_NOTHING:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700361 pw.print(" ");
362 if (sep != 0) pw.print(' ');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700363 break;
364 case ADJ_MEM_FACTOR_NORMAL:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700365 pw.print("Norm");
366 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700367 break;
368 case ADJ_MEM_FACTOR_MODERATE:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700369 pw.print("Mod ");
370 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700371 break;
372 case ADJ_MEM_FACTOR_LOW:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700373 pw.print("Low ");
374 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700375 break;
376 case ADJ_MEM_FACTOR_CRITICAL:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700377 pw.print("Crit");
378 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700379 break;
380 default:
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700381 pw.print("????");
382 if (sep != 0) pw.print(sep);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700383 break;
384 }
385 }
386
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700387 public static void printMemLabelCsv(PrintWriter pw, int offset) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700388 if (offset >= ADJ_MEM_FACTOR_NORMAL) {
389 if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
390 pw.print(ADJ_MEM_NAMES_CSV[offset]);
391 } else {
392 pw.print("???");
393 }
394 }
395 }
396
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700397 public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700398 int curState, long curStartTime, long now) {
399 long totalTime = 0;
400 int printedScreen = -1;
401 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
402 int printedMem = -1;
403 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
404 int state = imem+iscreen;
405 long time = durations[state];
406 String running = "";
407 if (curState == state) {
408 time += now - curStartTime;
409 if (pw != null) {
410 running = " (running)";
411 }
412 }
413 if (time != 0) {
414 if (pw != null) {
415 pw.print(prefix);
416 printScreenLabel(pw, printedScreen != iscreen
417 ? iscreen : STATE_NOTHING);
418 printedScreen = iscreen;
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700419 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700420 printedMem = imem;
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700421 pw.print(": ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700422 TimeUtils.formatDuration(time, pw); pw.println(running);
423 }
424 totalTime += time;
425 }
426 }
427 }
428 if (totalTime != 0 && pw != null) {
429 pw.print(prefix);
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700430 pw.print(" TOTAL: ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700431 TimeUtils.formatDuration(totalTime, pw);
432 pw.println();
433 }
434 return totalTime;
435 }
436
437 static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,
438 int curState, long curStartTime, long now) {
439 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
440 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
441 int state = imem+iscreen;
442 long time = durations[state];
443 if (curState == state) {
444 time += now - curStartTime;
445 }
446 if (time != 0) {
447 printAdjTagAndValue(pw, state, time);
448 }
449 }
450 }
451 }
452
453 static void dumpServiceTimeCheckin(PrintWriter pw, String label, String packageName,
Dianne Hackborn8472e612014-01-23 17:57:20 -0800454 int uid, int vers, String serviceName, ServiceState svc, int serviceType, int opCount,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700455 int curState, long curStartTime, long now) {
456 if (opCount <= 0) {
457 return;
458 }
459 pw.print(label);
460 pw.print(",");
461 pw.print(packageName);
462 pw.print(",");
463 pw.print(uid);
464 pw.print(",");
Dianne Hackborn8472e612014-01-23 17:57:20 -0800465 pw.print(vers);
466 pw.print(",");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700467 pw.print(serviceName);
468 pw.print(",");
469 pw.print(opCount);
470 boolean didCurState = false;
471 for (int i=0; i<svc.mDurationsTableSize; i++) {
472 int off = svc.mDurationsTable[i];
473 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
474 int memFactor = type / ServiceState.SERVICE_COUNT;
475 type %= ServiceState.SERVICE_COUNT;
476 if (type != serviceType) {
477 continue;
478 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700479 long time = svc.mStats.getLong(off, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700480 if (curState == memFactor) {
481 didCurState = true;
482 time += now - curStartTime;
483 }
484 printAdjTagAndValue(pw, memFactor, time);
485 }
486 if (!didCurState && curState != STATE_NOTHING) {
487 printAdjTagAndValue(pw, curState, now - curStartTime);
488 }
489 pw.println();
490 }
491
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700492 public static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700493 data.totalTime = 0;
494 data.numPss = data.minPss = data.avgPss = data.maxPss =
495 data.minUss = data.avgUss = data.maxUss = 0;
496 for (int is=0; is<data.screenStates.length; is++) {
497 for (int im=0; im<data.memStates.length; im++) {
498 for (int ip=0; ip<data.procStates.length; ip++) {
499 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
500 + data.procStates[ip];
501 data.totalTime += proc.getDuration(bucket, now);
502 long samples = proc.getPssSampleCount(bucket);
503 if (samples > 0) {
504 long minPss = proc.getPssMinimum(bucket);
505 long avgPss = proc.getPssAverage(bucket);
506 long maxPss = proc.getPssMaximum(bucket);
507 long minUss = proc.getPssUssMinimum(bucket);
508 long avgUss = proc.getPssUssAverage(bucket);
509 long maxUss = proc.getPssUssMaximum(bucket);
510 if (data.numPss == 0) {
511 data.minPss = minPss;
512 data.avgPss = avgPss;
513 data.maxPss = maxPss;
514 data.minUss = minUss;
515 data.avgUss = avgUss;
516 data.maxUss = maxUss;
517 } else {
518 if (minPss < data.minPss) {
519 data.minPss = minPss;
520 }
521 data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
522 + (avgPss*(double)samples)) / (data.numPss+samples) );
523 if (maxPss > data.maxPss) {
524 data.maxPss = maxPss;
525 }
526 if (minUss < data.minUss) {
527 data.minUss = minUss;
528 }
529 data.avgUss = (long)( ((data.avgUss*(double)data.numPss)
530 + (avgUss*(double)samples)) / (data.numPss+samples) );
531 if (maxUss > data.maxUss) {
532 data.maxUss = maxUss;
533 }
534 }
535 data.numPss += samples;
536 }
537 }
538 }
539 }
540 }
541
542 static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
543 int[] procStates, long now) {
544 long totalTime = 0;
545 /*
546 for (int i=0; i<proc.mDurationsTableSize; i++) {
547 int val = proc.mDurationsTable[i];
548 totalTime += proc.mState.getLong(val, 0);
549 if ((val&0xff) == proc.mCurState) {
550 totalTime += now - proc.mStartTime;
551 }
552 }
553 */
554 for (int is=0; is<screenStates.length; is++) {
555 for (int im=0; im<memStates.length; im++) {
556 for (int ip=0; ip<procStates.length; ip++) {
557 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
558 + procStates[ip];
559 totalTime += proc.getDuration(bucket, now);
560 }
561 }
562 }
563 proc.mTmpTotalTime = totalTime;
564 return totalTime;
565 }
566
567 static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc,
568 int[] screenStates, int[] memStates, int[] procStates, long now) {
569 long totalTime = 0;
570 int printedScreen = -1;
571 for (int is=0; is<screenStates.length; is++) {
572 int printedMem = -1;
573 for (int im=0; im<memStates.length; im++) {
574 for (int ip=0; ip<procStates.length; ip++) {
575 final int iscreen = screenStates[is];
576 final int imem = memStates[im];
577 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
578 long time = proc.getDuration(bucket, now);
579 String running = "";
580 if (proc.mCurState == bucket) {
581 running = " (running)";
582 }
583 if (time != 0) {
584 pw.print(prefix);
585 if (screenStates.length > 1) {
586 printScreenLabel(pw, printedScreen != iscreen
587 ? iscreen : STATE_NOTHING);
588 printedScreen = iscreen;
589 }
590 if (memStates.length > 1) {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700591 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700592 printedMem = imem;
593 }
594 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
595 TimeUtils.formatDuration(time, pw); pw.println(running);
596 totalTime += time;
597 }
598 }
599 }
600 }
601 if (totalTime != 0) {
602 pw.print(prefix);
603 if (screenStates.length > 1) {
604 printScreenLabel(pw, STATE_NOTHING);
605 }
606 if (memStates.length > 1) {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700607 printMemLabel(pw, STATE_NOTHING, '/');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700608 }
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700609 pw.print("TOTAL : ");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700610 TimeUtils.formatDuration(totalTime, pw);
611 pw.println();
612 }
613 }
614
615 static void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
616 int[] memStates, int[] procStates) {
617 boolean printedHeader = false;
618 int printedScreen = -1;
619 for (int is=0; is<screenStates.length; is++) {
620 int printedMem = -1;
621 for (int im=0; im<memStates.length; im++) {
622 for (int ip=0; ip<procStates.length; ip++) {
623 final int iscreen = screenStates[is];
624 final int imem = memStates[im];
625 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
626 long count = proc.getPssSampleCount(bucket);
627 if (count > 0) {
628 if (!printedHeader) {
629 pw.print(prefix);
630 pw.print("PSS/USS (");
631 pw.print(proc.mPssTableSize);
632 pw.println(" entries):");
633 printedHeader = true;
634 }
635 pw.print(prefix);
636 pw.print(" ");
637 if (screenStates.length > 1) {
638 printScreenLabel(pw, printedScreen != iscreen
639 ? iscreen : STATE_NOTHING);
640 printedScreen = iscreen;
641 }
642 if (memStates.length > 1) {
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700643 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
Dianne Hackbornd2932242013-08-05 18:18:42 -0700644 printedMem = imem;
645 }
646 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
647 pw.print(count);
648 pw.print(" samples ");
649 printSizeValue(pw, proc.getPssMinimum(bucket) * 1024);
650 pw.print(" ");
651 printSizeValue(pw, proc.getPssAverage(bucket) * 1024);
652 pw.print(" ");
653 printSizeValue(pw, proc.getPssMaximum(bucket) * 1024);
654 pw.print(" / ");
655 printSizeValue(pw, proc.getPssUssMinimum(bucket) * 1024);
656 pw.print(" ");
657 printSizeValue(pw, proc.getPssUssAverage(bucket) * 1024);
658 pw.print(" ");
659 printSizeValue(pw, proc.getPssUssMaximum(bucket) * 1024);
660 pw.println();
661 }
662 }
663 }
664 }
665 if (proc.mNumExcessiveWake != 0) {
666 pw.print(prefix); pw.print("Killed for excessive wake locks: ");
667 pw.print(proc.mNumExcessiveWake); pw.println(" times");
668 }
669 if (proc.mNumExcessiveCpu != 0) {
670 pw.print(prefix); pw.print("Killed for excessive CPU use: ");
671 pw.print(proc.mNumExcessiveCpu); pw.println(" times");
672 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -0700673 if (proc.mNumCachedKill != 0) {
674 pw.print(prefix); pw.print("Killed from cached state: ");
675 pw.print(proc.mNumCachedKill); pw.print(" times from pss ");
676 printSizeValue(pw, proc.mMinCachedKillPss * 1024); pw.print("-");
677 printSizeValue(pw, proc.mAvgCachedKillPss * 1024); pw.print("-");
678 printSizeValue(pw, proc.mMaxCachedKillPss * 1024); pw.println();
679 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700680 }
681
682 static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
683 int[] memStates, int[] procStates) {
684 final int NS = screenStates != null ? screenStates.length : 1;
685 final int NM = memStates != null ? memStates.length : 1;
686 final int NP = procStates != null ? procStates.length : 1;
687 for (int is=0; is<NS; is++) {
688 for (int im=0; im<NM; im++) {
689 for (int ip=0; ip<NP; ip++) {
690 pw.print(sep);
691 boolean printed = false;
692 if (screenStates != null && screenStates.length > 1) {
693 printScreenLabelCsv(pw, screenStates[is]);
694 printed = true;
695 }
696 if (memStates != null && memStates.length > 1) {
697 if (printed) {
698 pw.print("-");
699 }
700 printMemLabelCsv(pw, memStates[im]);
701 printed = true;
702 }
703 if (procStates != null && procStates.length > 1) {
704 if (printed) {
705 pw.print("-");
706 }
707 pw.print(STATE_NAMES_CSV[procStates[ip]]);
708 }
709 }
710 }
711 }
712 }
713
714 static void dumpProcessStateCsv(PrintWriter pw, ProcessState proc,
715 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
716 boolean sepProcStates, int[] procStates, long now) {
717 final int NSS = sepScreenStates ? screenStates.length : 1;
718 final int NMS = sepMemStates ? memStates.length : 1;
719 final int NPS = sepProcStates ? procStates.length : 1;
720 for (int iss=0; iss<NSS; iss++) {
721 for (int ims=0; ims<NMS; ims++) {
722 for (int ips=0; ips<NPS; ips++) {
723 final int vsscreen = sepScreenStates ? screenStates[iss] : 0;
724 final int vsmem = sepMemStates ? memStates[ims] : 0;
725 final int vsproc = sepProcStates ? procStates[ips] : 0;
726 final int NSA = sepScreenStates ? 1 : screenStates.length;
727 final int NMA = sepMemStates ? 1 : memStates.length;
728 final int NPA = sepProcStates ? 1 : procStates.length;
729 long totalTime = 0;
730 for (int isa=0; isa<NSA; isa++) {
731 for (int ima=0; ima<NMA; ima++) {
732 for (int ipa=0; ipa<NPA; ipa++) {
733 final int vascreen = sepScreenStates ? 0 : screenStates[isa];
734 final int vamem = sepMemStates ? 0 : memStates[ima];
735 final int vaproc = sepProcStates ? 0 : procStates[ipa];
736 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
737 * STATE_COUNT) + vsproc + vaproc;
738 totalTime += proc.getDuration(bucket, now);
739 }
740 }
741 }
742 pw.print(CSV_SEP);
743 pw.print(totalTime);
744 }
745 }
746 }
747 }
748
749 static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
750 int[] screenStates, int[] memStates, int[] procStates, long now) {
751 String innerPrefix = prefix + " ";
752 for (int i=procs.size()-1; i>=0; i--) {
753 ProcessState proc = procs.get(i);
754 pw.print(prefix);
755 pw.print(proc.mName);
756 pw.print(" / ");
757 UserHandle.formatUid(pw, proc.mUid);
758 pw.print(" (");
759 pw.print(proc.mDurationsTableSize);
760 pw.print(" entries)");
761 pw.println(":");
762 dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
763 if (proc.mPssTableSize > 0) {
764 dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates);
765 }
766 }
767 }
768
769 static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix,
770 String label, int[] screenStates, int[] memStates, int[] procStates,
771 long now, long totalTime, boolean full) {
772 ProcessDataCollection totals = new ProcessDataCollection(screenStates,
773 memStates, procStates);
774 computeProcessData(proc, totals, now);
775 if (totals.totalTime != 0 || totals.numPss != 0) {
776 if (prefix != null) {
777 pw.print(prefix);
778 }
779 if (label != null) {
780 pw.print(label);
781 }
782 totals.print(pw, totalTime, full);
783 if (prefix != null) {
784 pw.println();
785 }
786 }
787 }
788
789 static void dumpProcessSummaryLocked(PrintWriter pw, String prefix,
790 ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
Dianne Hackborn8472e612014-01-23 17:57:20 -0800791 boolean inclUidVers, long now, long totalTime) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700792 for (int i=procs.size()-1; i>=0; i--) {
793 ProcessState proc = procs.get(i);
794 pw.print(prefix);
795 pw.print("* ");
796 pw.print(proc.mName);
797 pw.print(" / ");
798 UserHandle.formatUid(pw, proc.mUid);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800799 pw.print(" / v");
800 pw.print(proc.mVersion);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700801 pw.println(":");
802 dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates,
803 procStates, now, totalTime, true);
804 dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates,
805 new int[] { STATE_PERSISTENT }, now, totalTime, true);
806 dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates,
807 new int[] {STATE_TOP}, now, totalTime, true);
808 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Fg: ", screenStates, memStates,
809 new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true);
810 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Bg: ", screenStates, memStates,
811 new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true);
812 dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates,
813 new int[] {STATE_BACKUP}, now, totalTime, true);
814 dumpProcessSummaryDetails(pw, proc, prefix, " Heavy Wgt: ", screenStates, memStates,
815 new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
816 dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates,
817 new int[] {STATE_SERVICE}, now, totalTime, true);
818 dumpProcessSummaryDetails(pw, proc, prefix, " Service Rs: ", screenStates, memStates,
819 new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
820 dumpProcessSummaryDetails(pw, proc, prefix, " Receiver: ", screenStates, memStates,
821 new int[] {STATE_RECEIVER}, now, totalTime, true);
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700822 dumpProcessSummaryDetails(pw, proc, prefix, " (Home): ", screenStates, memStates,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700823 new int[] {STATE_HOME}, now, totalTime, true);
824 dumpProcessSummaryDetails(pw, proc, prefix, " (Last Act): ", screenStates, memStates,
825 new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
826 dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates,
827 new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT,
828 STATE_CACHED_EMPTY}, now, totalTime, true);
829 }
830 }
831
832 static void printPercent(PrintWriter pw, double fraction) {
833 fraction *= 100;
834 if (fraction < 1) {
835 pw.print(String.format("%.2f", fraction));
836 } else if (fraction < 10) {
837 pw.print(String.format("%.1f", fraction));
838 } else {
839 pw.print(String.format("%.0f", fraction));
840 }
841 pw.print("%");
842 }
843
844 static void printSizeValue(PrintWriter pw, long number) {
845 float result = number;
846 String suffix = "";
847 if (result > 900) {
848 suffix = "KB";
849 result = result / 1024;
850 }
851 if (result > 900) {
852 suffix = "MB";
853 result = result / 1024;
854 }
855 if (result > 900) {
856 suffix = "GB";
857 result = result / 1024;
858 }
859 if (result > 900) {
860 suffix = "TB";
861 result = result / 1024;
862 }
863 if (result > 900) {
864 suffix = "PB";
865 result = result / 1024;
866 }
867 String value;
868 if (result < 1) {
869 value = String.format("%.2f", result);
870 } else if (result < 10) {
871 value = String.format("%.1f", result);
872 } else if (result < 100) {
873 value = String.format("%.0f", result);
874 } else {
875 value = String.format("%.0f", result);
876 }
877 pw.print(value);
878 pw.print(suffix);
879 }
880
881 public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
882 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
883 boolean sepProcStates, int[] procStates, long now) {
884 pw.print("process");
885 pw.print(CSV_SEP);
886 pw.print("uid");
Dianne Hackborn8472e612014-01-23 17:57:20 -0800887 pw.print(CSV_SEP);
888 pw.print("vers");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700889 dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
890 sepMemStates ? memStates : null,
891 sepProcStates ? procStates : null);
892 pw.println();
893 for (int i=procs.size()-1; i>=0; i--) {
894 ProcessState proc = procs.get(i);
895 pw.print(proc.mName);
896 pw.print(CSV_SEP);
897 UserHandle.formatUid(pw, proc.mUid);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800898 pw.print(CSV_SEP);
899 pw.print(proc.mVersion);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700900 dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates,
901 sepMemStates, memStates, sepProcStates, procStates, now);
902 pw.println();
903 }
904 }
905
906 static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
907 int index = value/mod;
908 if (index >= 0 && index < array.length) {
909 pw.print(array[index]);
910 } else {
911 pw.print('?');
912 }
913 return value - index*mod;
914 }
915
916 static void printProcStateTag(PrintWriter pw, int state) {
917 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT);
918 state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT);
919 printArrayEntry(pw, STATE_TAGS, state, 1);
920 }
921
922 static void printAdjTag(PrintWriter pw, int state) {
923 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD);
924 printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
925 }
926
927 static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
928 pw.print(',');
929 printProcStateTag(pw, state);
930 pw.print(':');
931 pw.print(value);
932 }
933
934 static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
935 pw.print(',');
936 printAdjTag(pw, state);
937 pw.print(':');
938 pw.print(value);
939 }
940
941 static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
942 boolean didCurState = false;
943 for (int i=0; i<proc.mDurationsTableSize; i++) {
944 int off = proc.mDurationsTable[i];
945 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700946 long time = proc.mStats.getLong(off, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700947 if (proc.mCurState == type) {
948 didCurState = true;
949 time += now - proc.mStartTime;
950 }
951 printProcStateTagAndValue(pw, type, time);
952 }
953 if (!didCurState && proc.mCurState != STATE_NOTHING) {
954 printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
955 }
956 }
957
958 static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) {
959 for (int i=0; i<proc.mPssTableSize; i++) {
960 int off = proc.mPssTable[i];
961 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700962 long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT);
963 long min = proc.mStats.getLong(off, PSS_MINIMUM);
964 long avg = proc.mStats.getLong(off, PSS_AVERAGE);
965 long max = proc.mStats.getLong(off, PSS_MAXIMUM);
966 long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM);
967 long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE);
968 long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700969 pw.print(',');
970 printProcStateTag(pw, type);
971 pw.print(':');
972 pw.print(count);
973 pw.print(':');
974 pw.print(min);
975 pw.print(':');
976 pw.print(avg);
977 pw.print(':');
978 pw.print(max);
979 pw.print(':');
980 pw.print(umin);
981 pw.print(':');
982 pw.print(uavg);
983 pw.print(':');
984 pw.print(umax);
985 }
986 }
987
988 public void reset() {
989 if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr);
990 resetCommon();
991 mPackages.getMap().clear();
992 mProcesses.getMap().clear();
993 mMemFactor = STATE_NOTHING;
994 mStartTime = 0;
995 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
996 }
997
998 public void resetSafely() {
999 if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
1000 resetCommon();
Dianne Hackborn8472e612014-01-23 17:57:20 -08001001
1002 // First initialize use count of all common processes.
1003 final long now = SystemClock.uptimeMillis();
1004 final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001005 for (int ip=procMap.size()-1; ip>=0; ip--) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001006 final SparseArray<ProcessState> uids = procMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001007 for (int iu=uids.size()-1; iu>=0; iu--) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001008 uids.valueAt(iu).mTmpNumInUse = 0;
1009 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001010 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001011
1012 // Next reset or prune all per-package processes, and for the ones that are reset
1013 // track this back to the common processes.
1014 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001015 for (int ip=pkgMap.size()-1; ip>=0; ip--) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001016 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001017 for (int iu=uids.size()-1; iu>=0; iu--) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001018 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
1019 for (int iv=vpkgs.size()-1; iv>=0; iv--) {
1020 final PackageState pkgState = vpkgs.valueAt(iv);
1021 for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
1022 final ProcessState ps = pkgState.mProcesses.valueAt(iproc);
1023 if (ps.isInUse()) {
Dianne Hackborndfc60ec2014-02-18 17:42:55 -08001024 ps.resetSafely(now);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001025 ps.mCommonProcess.mTmpNumInUse++;
1026 ps.mCommonProcess.mTmpFoundSubProc = ps;
1027 } else {
1028 pkgState.mProcesses.valueAt(iproc).makeDead();
1029 pkgState.mProcesses.removeAt(iproc);
1030 }
1031 }
1032 for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
1033 final ServiceState ss = pkgState.mServices.valueAt(isvc);
1034 if (ss.isInUse()) {
Dianne Hackborndfc60ec2014-02-18 17:42:55 -08001035 ss.resetSafely(now);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001036 } else {
1037 pkgState.mServices.removeAt(isvc);
1038 }
1039 }
1040 if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
1041 vpkgs.removeAt(iv);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001042 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001043 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001044 if (vpkgs.size() <= 0) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001045 uids.removeAt(iu);
1046 }
1047 }
1048 if (uids.size() <= 0) {
1049 pkgMap.removeAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001050 }
1051 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001052
1053 // Finally prune out any common processes that are no longer in use.
1054 for (int ip=procMap.size()-1; ip>=0; ip--) {
1055 final SparseArray<ProcessState> uids = procMap.valueAt(ip);
1056 for (int iu=uids.size()-1; iu>=0; iu--) {
1057 ProcessState ps = uids.valueAt(iu);
1058 if (ps.isInUse() || ps.mTmpNumInUse > 0) {
1059 // If this is a process for multiple packages, we could at this point
1060 // be back down to one package. In that case, we want to revert back
1061 // to a single shared ProcessState. We can do this by converting the
1062 // current package-specific ProcessState up to the shared ProcessState,
1063 // throwing away the current one we have here (because nobody else is
1064 // using it).
1065 if (!ps.mActive && ps.mMultiPackage && ps.mTmpNumInUse == 1) {
1066 // Here we go...
1067 ps = ps.mTmpFoundSubProc;
1068 ps.mCommonProcess = ps;
1069 uids.setValueAt(iu, ps);
1070 } else {
1071 ps.resetSafely(now);
1072 }
1073 } else {
1074 ps.makeDead();
1075 uids.removeAt(iu);
1076 }
1077 }
1078 if (uids.size() <= 0) {
1079 procMap.removeAt(ip);
1080 }
1081 }
1082
Dianne Hackborncb428552013-09-26 11:07:17 -07001083 mStartTime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001084 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
1085 }
1086
1087 private void resetCommon() {
1088 mTimePeriodStartClock = System.currentTimeMillis();
1089 buildTimePeriodStartClockStr();
1090 mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
1091 mLongs.clear();
1092 mLongs.add(new long[LONGS_SIZE]);
1093 mNextLong = 0;
1094 Arrays.fill(mMemFactorDurations, 0);
1095 mStartTime = 0;
1096 mReadError = null;
1097 mFlags = 0;
1098 evaluateSystemProperties(true);
1099 }
1100
1101 public boolean evaluateSystemProperties(boolean update) {
1102 boolean changed = false;
Brian Carlstromfdb98d42014-01-30 13:14:01 -08001103 String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.1",
Dianne Hackbornd2932242013-08-05 18:18:42 -07001104 VMRuntime.getRuntime().vmLibrary());
1105 if (!Objects.equals(runtime, mRuntime)) {
1106 changed = true;
1107 if (update) {
1108 mRuntime = runtime;
1109 }
1110 }
1111 String webview = WebViewFactory.useExperimentalWebView() ? "chromeview" : "webview";
1112 if (!Objects.equals(webview, mWebView)) {
1113 changed = true;
1114 if (update) {
1115 mWebView = webview;
1116 }
1117 }
1118 return changed;
1119 }
1120
1121 private void buildTimePeriodStartClockStr() {
1122 mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
1123 mTimePeriodStartClock).toString();
1124 }
1125
1126 static final int[] BAD_TABLE = new int[0];
1127
1128 private int[] readTableFromParcel(Parcel in, String name, String what) {
1129 final int size = in.readInt();
1130 if (size < 0) {
1131 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size);
1132 return BAD_TABLE;
1133 }
1134 if (size == 0) {
1135 return null;
1136 }
1137 final int[] table = new int[size];
1138 for (int i=0; i<size; i++) {
1139 table[i] = in.readInt();
Dianne Hackborn164371f2013-10-01 19:10:13 -07001140 if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
Dianne Hackbornd2932242013-08-05 18:18:42 -07001141 + ProcessStats.printLongOffset(table[i]));
1142 if (!validateLongOffset(table[i])) {
1143 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
1144 + ProcessStats.printLongOffset(table[i]));
1145 return null;
1146 }
1147 }
1148 return table;
1149 }
1150
Dianne Hackborn53459a72013-09-17 17:14:57 -07001151 private void writeCompactedLongArray(Parcel out, long[] array, int num) {
1152 for (int i=0; i<num; i++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001153 long val = array[i];
1154 if (val < 0) {
1155 Slog.w(TAG, "Time val negative: " + val);
1156 val = 0;
1157 }
1158 if (val <= Integer.MAX_VALUE) {
1159 out.writeInt((int)val);
1160 } else {
1161 int top = ~((int)((val>>32)&0x7fffffff));
1162 int bottom = (int)(val&0xfffffff);
1163 out.writeInt(top);
1164 out.writeInt(bottom);
1165 }
1166 }
1167 }
1168
Dianne Hackborn53459a72013-09-17 17:14:57 -07001169 private void readCompactedLongArray(Parcel in, int version, long[] array, int num) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001170 if (version <= 10) {
1171 in.readLongArray(array);
1172 return;
1173 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001174 final int alen = array.length;
1175 if (num > alen) {
1176 throw new RuntimeException("bad array lengths: got " + num + " array is " + alen);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001177 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001178 int i;
1179 for (i=0; i<num; i++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001180 int val = in.readInt();
1181 if (val >= 0) {
1182 array[i] = val;
1183 } else {
1184 int bottom = in.readInt();
1185 array[i] = (((long)~val)<<32) | bottom;
1186 }
1187 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001188 while (i < alen) {
1189 array[i] = 0;
1190 i++;
1191 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001192 }
1193
1194 private void writeCommonString(Parcel out, String name) {
1195 Integer index = mCommonStringToIndex.get(name);
1196 if (index != null) {
1197 out.writeInt(index);
1198 return;
1199 }
1200 index = mCommonStringToIndex.size();
1201 mCommonStringToIndex.put(name, index);
1202 out.writeInt(~index);
1203 out.writeString(name);
1204 }
1205
1206 private String readCommonString(Parcel in, int version) {
1207 if (version <= 9) {
1208 return in.readString();
1209 }
1210 int index = in.readInt();
1211 if (index >= 0) {
1212 return mIndexToCommonString.get(index);
1213 }
1214 index = ~index;
1215 String name = in.readString();
1216 while (mIndexToCommonString.size() <= index) {
1217 mIndexToCommonString.add(null);
1218 }
1219 mIndexToCommonString.set(index, name);
1220 return name;
1221 }
1222
Dianne Hackborn23fb6e82013-08-07 10:08:22 -07001223 @Override
1224 public int describeContents() {
1225 return 0;
1226 }
1227
1228 @Override
1229 public void writeToParcel(Parcel out, int flags) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001230 long now = SystemClock.uptimeMillis();
1231 out.writeInt(MAGIC);
1232 out.writeInt(PARCEL_VERSION);
1233 out.writeInt(STATE_COUNT);
1234 out.writeInt(ADJ_COUNT);
1235 out.writeInt(PSS_COUNT);
1236 out.writeInt(LONGS_SIZE);
1237
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001238 mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size());
1239
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001240 // First commit all running times.
1241 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1242 final int NPROC = procMap.size();
1243 for (int ip=0; ip<NPROC; ip++) {
1244 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1245 final int NUID = uids.size();
1246 for (int iu=0; iu<NUID; iu++) {
1247 uids.valueAt(iu).commitStateTime(now);
1248 }
1249 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001250 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001251 final int NPKG = pkgMap.size();
1252 for (int ip=0; ip<NPKG; ip++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001253 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001254 final int NUID = uids.size();
1255 for (int iu=0; iu<NUID; iu++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001256 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
1257 final int NVERS = vpkgs.size();
1258 for (int iv=0; iv<NVERS; iv++) {
1259 PackageState pkgState = vpkgs.valueAt(iv);
1260 final int NPROCS = pkgState.mProcesses.size();
1261 for (int iproc=0; iproc<NPROCS; iproc++) {
1262 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1263 if (proc.mCommonProcess != proc) {
1264 proc.commitStateTime(now);
1265 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001266 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001267 final int NSRVS = pkgState.mServices.size();
1268 for (int isvc=0; isvc<NSRVS; isvc++) {
1269 pkgState.mServices.valueAt(isvc).commitStateTime(now);
1270 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001271 }
1272 }
1273 }
1274
Dianne Hackbornd2932242013-08-05 18:18:42 -07001275 out.writeLong(mTimePeriodStartClock);
1276 out.writeLong(mTimePeriodStartRealtime);
1277 out.writeLong(mTimePeriodEndRealtime);
1278 out.writeString(mRuntime);
1279 out.writeString(mWebView);
1280 out.writeInt(mFlags);
1281
1282 out.writeInt(mLongs.size());
1283 out.writeInt(mNextLong);
1284 for (int i=0; i<(mLongs.size()-1); i++) {
Dianne Hackborn53459a72013-09-17 17:14:57 -07001285 long[] array = mLongs.get(i);
1286 writeCompactedLongArray(out, array, array.length);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001287 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001288 long[] lastLongs = mLongs.get(mLongs.size() - 1);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001289 writeCompactedLongArray(out, lastLongs, mNextLong);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001290
1291 if (mMemFactor != STATE_NOTHING) {
1292 mMemFactorDurations[mMemFactor] += now - mStartTime;
1293 mStartTime = now;
1294 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001295 writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001296
Dianne Hackbornd2932242013-08-05 18:18:42 -07001297 out.writeInt(NPROC);
1298 for (int ip=0; ip<NPROC; ip++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001299 writeCommonString(out, procMap.keyAt(ip));
Dianne Hackborn8472e612014-01-23 17:57:20 -08001300 final SparseArray<ProcessState> uids = procMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001301 final int NUID = uids.size();
1302 out.writeInt(NUID);
1303 for (int iu=0; iu<NUID; iu++) {
1304 out.writeInt(uids.keyAt(iu));
Dianne Hackborn8472e612014-01-23 17:57:20 -08001305 final ProcessState proc = uids.valueAt(iu);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001306 writeCommonString(out, proc.mPackage);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001307 out.writeInt(proc.mVersion);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001308 proc.writeToParcel(out, now);
1309 }
1310 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001311 out.writeInt(NPKG);
1312 for (int ip=0; ip<NPKG; ip++) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001313 writeCommonString(out, pkgMap.keyAt(ip));
Dianne Hackborn8472e612014-01-23 17:57:20 -08001314 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001315 final int NUID = uids.size();
1316 out.writeInt(NUID);
1317 for (int iu=0; iu<NUID; iu++) {
1318 out.writeInt(uids.keyAt(iu));
Dianne Hackborn8472e612014-01-23 17:57:20 -08001319 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
1320 final int NVERS = vpkgs.size();
1321 out.writeInt(NVERS);
1322 for (int iv=0; iv<NVERS; iv++) {
1323 out.writeInt(vpkgs.keyAt(iv));
1324 final PackageState pkgState = vpkgs.valueAt(iv);
1325 final int NPROCS = pkgState.mProcesses.size();
1326 out.writeInt(NPROCS);
1327 for (int iproc=0; iproc<NPROCS; iproc++) {
1328 writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
1329 final ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1330 if (proc.mCommonProcess == proc) {
1331 // This is the same as the common process we wrote above.
1332 out.writeInt(0);
1333 } else {
1334 // There is separate data for this package's process.
1335 out.writeInt(1);
1336 proc.writeToParcel(out, now);
1337 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001338 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001339 final int NSRVS = pkgState.mServices.size();
1340 out.writeInt(NSRVS);
1341 for (int isvc=0; isvc<NSRVS; isvc++) {
1342 out.writeString(pkgState.mServices.keyAt(isvc));
1343 final ServiceState svc = pkgState.mServices.valueAt(isvc);
1344 writeCommonString(out, svc.mProcessName);
1345 svc.writeToParcel(out, now);
1346 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001347 }
1348 }
1349 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001350
1351 mCommonStringToIndex = null;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001352 }
1353
1354 private boolean readCheckedInt(Parcel in, int val, String what) {
1355 int got;
1356 if ((got=in.readInt()) != val) {
1357 mReadError = "bad " + what + ": " + got;
1358 return false;
1359 }
1360 return true;
1361 }
1362
Dianne Hackborn53459a72013-09-17 17:14:57 -07001363 static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001364 int pos = 0;
Dianne Hackborn53459a72013-09-17 17:14:57 -07001365 final int initialAvail = stream.available();
1366 byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001367 while (true) {
1368 int amt = stream.read(data, pos, data.length-pos);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001369 if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
Dianne Hackborn53459a72013-09-17 17:14:57 -07001370 + " of avail " + data.length);
1371 if (amt < 0) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001372 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
Dianne Hackborn53459a72013-09-17 17:14:57 -07001373 + " len=" + data.length);
1374 outLen[0] = pos;
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001375 return data;
1376 }
1377 pos += amt;
Dianne Hackborn53459a72013-09-17 17:14:57 -07001378 if (pos >= data.length) {
1379 byte[] newData = new byte[pos+16384];
Dianne Hackborn164371f2013-10-01 19:10:13 -07001380 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
Dianne Hackborn53459a72013-09-17 17:14:57 -07001381 + newData.length);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001382 System.arraycopy(data, 0, newData, 0, pos);
1383 data = newData;
1384 }
1385 }
1386 }
1387
1388 public void read(InputStream stream) {
1389 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -07001390 int[] len = new int[1];
1391 byte[] raw = readFully(stream, len);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001392 Parcel in = Parcel.obtain();
Dianne Hackborn53459a72013-09-17 17:14:57 -07001393 in.unmarshall(raw, 0, len[0]);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001394 in.setDataPosition(0);
1395 stream.close();
1396
1397 readFromParcel(in);
1398 } catch (IOException e) {
1399 mReadError = "caught exception: " + e;
1400 }
1401 }
1402
Dianne Hackbornd2932242013-08-05 18:18:42 -07001403 public void readFromParcel(Parcel in) {
1404 final boolean hadData = mPackages.getMap().size() > 0
1405 || mProcesses.getMap().size() > 0;
1406 if (hadData) {
1407 resetSafely();
1408 }
1409
1410 if (!readCheckedInt(in, MAGIC, "magic number")) {
1411 return;
1412 }
1413 int version = in.readInt();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001414 if (version != PARCEL_VERSION) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001415 mReadError = "bad version: " + version;
1416 return;
1417 }
1418 if (!readCheckedInt(in, STATE_COUNT, "state count")) {
1419 return;
1420 }
1421 if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
1422 return;
1423 }
1424 if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
1425 return;
1426 }
1427 if (!readCheckedInt(in, LONGS_SIZE, "longs size")) {
1428 return;
1429 }
1430
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001431 mIndexToCommonString = new ArrayList<String>();
1432
Dianne Hackbornd2932242013-08-05 18:18:42 -07001433 mTimePeriodStartClock = in.readLong();
1434 buildTimePeriodStartClockStr();
1435 mTimePeriodStartRealtime = in.readLong();
1436 mTimePeriodEndRealtime = in.readLong();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001437 mRuntime = in.readString();
1438 mWebView = in.readString();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001439 mFlags = in.readInt();
1440
1441 final int NLONGS = in.readInt();
1442 final int NEXTLONG = in.readInt();
1443 mLongs.clear();
1444 for (int i=0; i<(NLONGS-1); i++) {
1445 while (i >= mLongs.size()) {
1446 mLongs.add(new long[LONGS_SIZE]);
1447 }
Dianne Hackborn53459a72013-09-17 17:14:57 -07001448 readCompactedLongArray(in, version, mLongs.get(i), LONGS_SIZE);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001449 }
1450 long[] longs = new long[LONGS_SIZE];
1451 mNextLong = NEXTLONG;
Dianne Hackborn53459a72013-09-17 17:14:57 -07001452 readCompactedLongArray(in, version, longs, NEXTLONG);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001453 mLongs.add(longs);
1454
Dianne Hackborn53459a72013-09-17 17:14:57 -07001455 readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001456
1457 int NPROC = in.readInt();
1458 if (NPROC < 0) {
1459 mReadError = "bad process count: " + NPROC;
1460 return;
1461 }
1462 while (NPROC > 0) {
1463 NPROC--;
Dianne Hackborn8472e612014-01-23 17:57:20 -08001464 final String procName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001465 if (procName == null) {
1466 mReadError = "bad process name";
1467 return;
1468 }
1469 int NUID = in.readInt();
1470 if (NUID < 0) {
1471 mReadError = "bad uid count: " + NUID;
1472 return;
1473 }
1474 while (NUID > 0) {
1475 NUID--;
Dianne Hackborn8472e612014-01-23 17:57:20 -08001476 final int uid = in.readInt();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001477 if (uid < 0) {
1478 mReadError = "bad uid: " + uid;
1479 return;
1480 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001481 final String pkgName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001482 if (pkgName == null) {
1483 mReadError = "bad process package name";
1484 return;
1485 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001486 final int vers = in.readInt();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001487 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
1488 if (proc != null) {
1489 if (!proc.readFromParcel(in, false)) {
1490 return;
1491 }
1492 } else {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001493 proc = new ProcessState(this, pkgName, uid, vers, procName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001494 if (!proc.readFromParcel(in, true)) {
1495 return;
1496 }
1497 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001498 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
1499 + " " + proc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001500 mProcesses.put(procName, uid, proc);
1501 }
1502 }
1503
Dianne Hackborn164371f2013-10-01 19:10:13 -07001504 if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001505
1506 int NPKG = in.readInt();
1507 if (NPKG < 0) {
1508 mReadError = "bad package count: " + NPKG;
1509 return;
1510 }
1511 while (NPKG > 0) {
1512 NPKG--;
Dianne Hackborn8472e612014-01-23 17:57:20 -08001513 final String pkgName = readCommonString(in, version);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001514 if (pkgName == null) {
1515 mReadError = "bad package name";
1516 return;
1517 }
1518 int NUID = in.readInt();
1519 if (NUID < 0) {
1520 mReadError = "bad uid count: " + NUID;
1521 return;
1522 }
1523 while (NUID > 0) {
1524 NUID--;
Dianne Hackborn8472e612014-01-23 17:57:20 -08001525 final int uid = in.readInt();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001526 if (uid < 0) {
1527 mReadError = "bad uid: " + uid;
1528 return;
1529 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001530 int NVERS = in.readInt();
1531 if (NVERS < 0) {
1532 mReadError = "bad versions count: " + NVERS;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001533 return;
1534 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001535 while (NVERS > 0) {
1536 NVERS--;
1537 final int vers = in.readInt();
1538 PackageState pkgState = new PackageState(pkgName, uid);
1539 SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid);
1540 if (vpkg == null) {
1541 vpkg = new SparseArray<PackageState>();
1542 mPackages.put(pkgName, uid, vpkg);
1543 }
1544 vpkg.put(vers, pkgState);
1545 int NPROCS = in.readInt();
1546 if (NPROCS < 0) {
1547 mReadError = "bad package process count: " + NPROCS;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001548 return;
1549 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001550 while (NPROCS > 0) {
1551 NPROCS--;
1552 String procName = readCommonString(in, version);
1553 if (procName == null) {
1554 mReadError = "bad package process name";
1555 return;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001556 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001557 int hasProc = in.readInt();
1558 if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
1559 + " process " + procName + " hasProc=" + hasProc);
1560 ProcessState commonProc = mProcesses.get(procName, uid);
1561 if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
1562 + ": " + commonProc);
1563 if (commonProc == null) {
1564 mReadError = "no common proc: " + procName;
1565 return;
1566 }
1567 if (hasProc != 0) {
1568 // The process for this package is unique to the package; we
1569 // need to load it. We don't need to do anything about it if
1570 // it is not unique because if someone later looks for it
1571 // they will find and use it from the global procs.
1572 ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
1573 if (proc != null) {
1574 if (!proc.readFromParcel(in, false)) {
1575 return;
1576 }
1577 } else {
1578 proc = new ProcessState(commonProc, pkgName, uid, vers, procName,
1579 0);
1580 if (!proc.readFromParcel(in, true)) {
1581 return;
1582 }
1583 }
1584 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
1585 + procName + " " + uid + " " + proc);
1586 pkgState.mProcesses.put(procName, proc);
1587 } else {
1588 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
1589 + procName + " " + uid + " " + commonProc);
1590 pkgState.mProcesses.put(procName, commonProc);
1591 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001592 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001593 int NSRVS = in.readInt();
1594 if (NSRVS < 0) {
1595 mReadError = "bad package service count: " + NSRVS;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001596 return;
1597 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001598 while (NSRVS > 0) {
1599 NSRVS--;
1600 String serviceName = in.readString();
1601 if (serviceName == null) {
1602 mReadError = "bad package service name";
1603 return;
1604 }
1605 String processName = version > 9 ? readCommonString(in, version) : null;
1606 ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
1607 if (serv == null) {
1608 serv = new ServiceState(this, pkgName, serviceName, processName, null);
1609 }
1610 if (!serv.readFromParcel(in)) {
1611 return;
1612 }
1613 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
1614 + serviceName + " " + uid + " " + serv);
1615 pkgState.mServices.put(serviceName, serv);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001616 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001617 }
1618 }
1619 }
1620
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001621 mIndexToCommonString = null;
1622
Dianne Hackborn164371f2013-10-01 19:10:13 -07001623 if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001624 }
1625
1626 int addLongData(int index, int type, int num) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001627 int off = allocLongData(num);
Adam Lesinski776abc22014-03-07 11:30:59 -05001628 mAddLongTable = GrowingArrayUtils.insert(
1629 mAddLongTable != null ? mAddLongTable : EmptyArray.INT,
1630 mAddLongTableSize, index, type | off);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001631 mAddLongTableSize++;
1632 return off;
1633 }
1634
1635 int allocLongData(int num) {
1636 int whichLongs = mLongs.size()-1;
1637 long[] longs = mLongs.get(whichLongs);
1638 if (mNextLong + num > longs.length) {
1639 longs = new long[LONGS_SIZE];
1640 mLongs.add(longs);
1641 whichLongs++;
1642 mNextLong = 0;
1643 }
1644 int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
1645 mNextLong += num;
1646 return off;
1647 }
1648
1649 boolean validateLongOffset(int off) {
1650 int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK;
1651 if (arr >= mLongs.size()) {
1652 return false;
1653 }
1654 int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
1655 if (idx >= LONGS_SIZE) {
1656 return false;
1657 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07001658 if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off)
Dianne Hackbornd2932242013-08-05 18:18:42 -07001659 + ": " + getLong(off, 0));
1660 return true;
1661 }
1662
1663 static String printLongOffset(int off) {
1664 StringBuilder sb = new StringBuilder(16);
1665 sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1666 sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK);
1667 sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK);
1668 return sb.toString();
1669 }
1670
1671 void setLong(int off, int index, long value) {
1672 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1673 longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
1674 }
1675
1676 long getLong(int off, int index) {
1677 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
1678 return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
1679 }
1680
1681 static int binarySearch(int[] array, int size, int value) {
1682 int lo = 0;
1683 int hi = size - 1;
1684
1685 while (lo <= hi) {
1686 int mid = (lo + hi) >>> 1;
1687 int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
1688
1689 if (midVal < value) {
1690 lo = mid + 1;
1691 } else if (midVal > value) {
1692 hi = mid - 1;
1693 } else {
1694 return mid; // value found
1695 }
1696 }
1697 return ~lo; // value not present
1698 }
1699
Dianne Hackborn8472e612014-01-23 17:57:20 -08001700 public PackageState getPackageStateLocked(String packageName, int uid, int vers) {
1701 SparseArray<PackageState> vpkg = mPackages.get(packageName, uid);
1702 if (vpkg == null) {
1703 vpkg = new SparseArray<PackageState>();
1704 mPackages.put(packageName, uid, vpkg);
1705 }
1706 PackageState as = vpkg.get(vers);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001707 if (as != null) {
1708 return as;
1709 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001710 as = new PackageState(packageName, uid);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001711 vpkg.put(vers, as);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001712 return as;
1713 }
1714
Dianne Hackborn8472e612014-01-23 17:57:20 -08001715 public ProcessState getProcessStateLocked(String packageName, int uid, int vers,
1716 String processName) {
1717 final PackageState pkgState = getPackageStateLocked(packageName, uid, vers);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001718 ProcessState ps = pkgState.mProcesses.get(processName);
1719 if (ps != null) {
1720 return ps;
1721 }
1722 ProcessState commonProc = mProcesses.get(processName, uid);
1723 if (commonProc == null) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001724 commonProc = new ProcessState(this, packageName, uid, vers, processName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001725 mProcesses.put(processName, uid, commonProc);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001726 if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001727 }
1728 if (!commonProc.mMultiPackage) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001729 if (packageName.equals(commonProc.mPackage) && vers == commonProc.mVersion) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001730 // This common process is not in use by multiple packages, and
1731 // is for the calling package, so we can just use it directly.
1732 ps = commonProc;
Dianne Hackborn164371f2013-10-01 19:10:13 -07001733 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001734 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001735 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
Dianne Hackbornd2932242013-08-05 18:18:42 -07001736 // This common process has not been in use by multiple packages,
1737 // but it was created for a different package than the caller.
1738 // We need to convert it to a multi-package process.
1739 commonProc.mMultiPackage = true;
Dianne Hackborncb428552013-09-26 11:07:17 -07001740 // To do this, we need to make two new process states, one a copy
1741 // of the current state for the process under the original package
1742 // name, and the second a free new process state for it as the
1743 // new package name.
Dianne Hackbornd2932242013-08-05 18:18:42 -07001744 long now = SystemClock.uptimeMillis();
Dianne Hackborncb428552013-09-26 11:07:17 -07001745 // First let's make a copy of the current process state and put
1746 // that under the now unique state for its original package name.
Dianne Hackborn8472e612014-01-23 17:57:20 -08001747 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage,
1748 uid, commonProc.mVersion);
Dianne Hackborncb428552013-09-26 11:07:17 -07001749 if (commonPkgState != null) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001750 ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
1751 if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
1752 + ": " + cloned);
1753 commonPkgState.mProcesses.put(commonProc.mName, cloned);
1754 // If this has active services, we need to update their process pointer
1755 // to point to the new package-specific process state.
1756 for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
1757 ServiceState ss = commonPkgState.mServices.valueAt(i);
1758 if (ss.mProc == commonProc) {
1759 if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
1760 + ss);
1761 ss.mProc = cloned;
1762 } else if (DEBUG) {
1763 Slog.d(TAG, "GETPROC leaving proc of " + ss);
1764 }
1765 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001766 } else {
1767 Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
1768 + "/" + uid + " for proc " + commonProc.mName);
1769 }
1770 // And now make a fresh new process state for the new package name.
Dianne Hackborn8472e612014-01-23 17:57:20 -08001771 ps = new ProcessState(commonProc, packageName, uid, vers, processName, now);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001772 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001773 }
1774 } else {
1775 // The common process is for multiple packages, we need to create a
1776 // separate object for the per-package data.
Dianne Hackborn8472e612014-01-23 17:57:20 -08001777 ps = new ProcessState(commonProc, packageName, uid, vers, processName,
Dianne Hackbornd2932242013-08-05 18:18:42 -07001778 SystemClock.uptimeMillis());
Dianne Hackborn164371f2013-10-01 19:10:13 -07001779 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001780 }
1781 pkgState.mProcesses.put(processName, ps);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001782 if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001783 return ps;
1784 }
1785
Dianne Hackborn8472e612014-01-23 17:57:20 -08001786 public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid, int vers,
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001787 String processName, String className) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001788 final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001789 ProcessStats.ServiceState ss = as.mServices.get(className);
1790 if (ss != null) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001791 if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001792 return ss;
1793 }
1794 final ProcessStats.ProcessState ps = processName != null
Dianne Hackborn8472e612014-01-23 17:57:20 -08001795 ? getProcessStateLocked(packageName, uid, vers, processName) : null;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001796 ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001797 as.mServices.put(className, ss);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001798 if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07001799 return ss;
1800 }
1801
Dianne Hackborncb428552013-09-26 11:07:17 -07001802 private void dumpProcessInternalLocked(PrintWriter pw, String prefix, ProcessState proc,
1803 boolean dumpAll) {
1804 if (dumpAll) {
1805 pw.print(prefix); pw.print("myID=");
1806 pw.print(Integer.toHexString(System.identityHashCode(proc)));
1807 pw.print(" mCommonProcess=");
1808 pw.print(Integer.toHexString(System.identityHashCode(proc.mCommonProcess)));
1809 pw.print(" mPackage="); pw.println(proc.mPackage);
1810 if (proc.mMultiPackage) {
1811 pw.print(prefix); pw.print("mMultiPackage="); pw.println(proc.mMultiPackage);
1812 }
1813 if (proc != proc.mCommonProcess) {
1814 pw.print(prefix); pw.print("Common Proc: "); pw.print(proc.mCommonProcess.mName);
1815 pw.print("/"); pw.print(proc.mCommonProcess.mUid);
1816 pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage);
1817 }
1818 }
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001819 if (proc.mActive) {
1820 pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive);
1821 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001822 if (proc.mDead) {
1823 pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead);
1824 }
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001825 if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) {
1826 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices);
1827 pw.print(" mNumStartedServices=");
1828 pw.println(proc.mNumStartedServices);
1829 }
Dianne Hackborncb428552013-09-26 11:07:17 -07001830 }
1831
Dianne Hackborn53459a72013-09-17 17:14:57 -07001832 public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
Dianne Hackborn164371f2013-10-01 19:10:13 -07001833 boolean dumpAll, boolean activeOnly) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001834 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
1835 mStartTime, now);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001836 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001837 boolean printedHeader = false;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001838 boolean sepNeeded = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001839 for (int ip=0; ip<pkgMap.size(); ip++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001840 final String pkgName = pkgMap.keyAt(ip);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001841 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001842 for (int iu=0; iu<uids.size(); iu++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001843 final int uid = uids.keyAt(iu);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001844 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
1845 for (int iv=0; iv<vpkgs.size(); iv++) {
1846 final int vers = vpkgs.keyAt(iv);
1847 final PackageState pkgState = vpkgs.valueAt(iv);
1848 final int NPROCS = pkgState.mProcesses.size();
1849 final int NSRVS = pkgState.mServices.size();
1850 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
1851 if (!pkgMatch) {
1852 boolean procMatch = false;
1853 for (int iproc=0; iproc<NPROCS; iproc++) {
1854 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1855 if (reqPackage.equals(proc.mName)) {
1856 procMatch = true;
1857 break;
1858 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001859 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001860 if (!procMatch) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001861 continue;
1862 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001863 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001864 if (NPROCS > 0 || NSRVS > 0) {
1865 if (!printedHeader) {
1866 pw.println("Per-Package Stats:");
1867 printedHeader = true;
1868 sepNeeded = true;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001869 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001870 pw.print(" * "); pw.print(pkgName); pw.print(" / ");
1871 UserHandle.formatUid(pw, uid); pw.print(" / v");
1872 pw.print(vers); pw.println(":");
1873 }
1874 if (!dumpSummary || dumpAll) {
1875 for (int iproc=0; iproc<NPROCS; iproc++) {
1876 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1877 if (!pkgMatch && !reqPackage.equals(proc.mName)) {
1878 continue;
1879 }
1880 if (activeOnly && !proc.isInUse()) {
1881 pw.print(" (Not active: ");
1882 pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
1883 continue;
1884 }
1885 pw.print(" Process ");
1886 pw.print(pkgState.mProcesses.keyAt(iproc));
1887 if (proc.mCommonProcess.mMultiPackage) {
1888 pw.print(" (multi, ");
1889 } else {
1890 pw.print(" (unique, ");
1891 }
1892 pw.print(proc.mDurationsTableSize);
1893 pw.print(" entries)");
1894 pw.println(":");
1895 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1896 ALL_PROC_STATES, now);
1897 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1898 ALL_PROC_STATES);
1899 dumpProcessInternalLocked(pw, " ", proc, dumpAll);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001900 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001901 } else {
Dianne Hackborn8472e612014-01-23 17:57:20 -08001902 ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
1903 for (int iproc=0; iproc<NPROCS; iproc++) {
1904 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1905 if (!pkgMatch && !reqPackage.equals(proc.mName)) {
1906 continue;
1907 }
1908 if (activeOnly && !proc.isInUse()) {
1909 continue;
1910 }
1911 procs.add(proc);
Dianne Hackborn164371f2013-10-01 19:10:13 -07001912 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08001913 dumpProcessSummaryLocked(pw, " ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1914 NON_CACHED_PROC_STATES, false, now, totalTime);
1915 }
1916 for (int isvc=0; isvc<NSRVS; isvc++) {
1917 ServiceState svc = pkgState.mServices.valueAt(isvc);
1918 if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
1919 continue;
1920 }
1921 if (activeOnly && !svc.isInUse()) {
1922 pw.print(" (Not active: ");
1923 pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
1924 continue;
1925 }
1926 if (dumpAll) {
1927 pw.print(" Service ");
1928 } else {
1929 pw.print(" * ");
1930 }
1931 pw.print(pkgState.mServices.keyAt(isvc));
1932 pw.println(":");
1933 pw.print(" Process: "); pw.println(svc.mProcessName);
1934 dumpServiceStats(pw, " ", " ", " ", "Running", svc,
1935 svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
1936 svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll);
1937 dumpServiceStats(pw, " ", " ", " ", "Started", svc,
1938 svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState,
1939 svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll);
1940 dumpServiceStats(pw, " ", " ", " ", "Bound", svc,
1941 svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState,
1942 svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll);
1943 dumpServiceStats(pw, " ", " ", " ", "Executing", svc,
1944 svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
1945 svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
1946 if (dumpAll) {
1947 if (svc.mOwner != null) {
1948 pw.print(" mOwner="); pw.println(svc.mOwner);
1949 }
1950 if (svc.mStarted || svc.mRestarting) {
1951 pw.print(" mStarted="); pw.print(svc.mStarted);
1952 pw.print(" mRestarting="); pw.println(svc.mRestarting);
1953 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001954 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07001955 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001956 }
1957 }
1958 }
1959
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001960 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1961 printedHeader = false;
1962 int numShownProcs = 0, numTotalProcs = 0;
1963 for (int ip=0; ip<procMap.size(); ip++) {
1964 String procName = procMap.keyAt(ip);
1965 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1966 for (int iu=0; iu<uids.size(); iu++) {
1967 int uid = uids.keyAt(iu);
1968 numTotalProcs++;
1969 ProcessState proc = uids.valueAt(iu);
1970 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
1971 && proc.mPssTableSize == 0) {
1972 continue;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001973 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001974 if (!proc.mMultiPackage) {
1975 continue;
1976 }
1977 if (reqPackage != null && !reqPackage.equals(procName)
1978 && !reqPackage.equals(proc.mPackage)) {
1979 continue;
1980 }
1981 numShownProcs++;
1982 if (sepNeeded) {
1983 pw.println();
1984 }
1985 sepNeeded = true;
1986 if (!printedHeader) {
1987 pw.println("Multi-Package Common Processes:");
1988 printedHeader = true;
1989 }
1990 if (activeOnly && !proc.isInUse()) {
1991 pw.print(" (Not active: "); pw.print(procName); pw.println(")");
1992 continue;
1993 }
1994 pw.print(" * "); pw.print(procName); pw.print(" / ");
1995 UserHandle.formatUid(pw, uid);
1996 pw.print(" ("); pw.print(proc.mDurationsTableSize);
1997 pw.print(" entries)"); pw.println(":");
1998 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1999 ALL_PROC_STATES, now);
2000 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2001 ALL_PROC_STATES);
2002 dumpProcessInternalLocked(pw, " ", proc, dumpAll);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002003 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002004 }
2005 if (dumpAll) {
2006 pw.println();
2007 pw.print(" Total procs: "); pw.print(numShownProcs);
2008 pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
2009 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002010
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002011 if (sepNeeded) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002012 pw.println();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002013 }
2014 if (dumpSummary) {
2015 pw.println("Summary:");
2016 dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002017 } else {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002018 dumpTotalsLocked(pw, now);
2019 }
2020
2021 if (dumpAll) {
2022 pw.println();
2023 pw.println("Internal state:");
2024 pw.print(" Num long arrays: "); pw.println(mLongs.size());
2025 pw.print(" Next long entry: "); pw.println(mNextLong);
2026 pw.print(" mRunning="); pw.println(mRunning);
2027 }
2028 }
2029
Dianne Hackborn69cb00b2013-08-09 16:16:56 -07002030 public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
Dianne Hackbornd2932242013-08-05 18:18:42 -07002031 int serviceType, int curState, long curStartTime, long now) {
2032 long totalTime = 0;
2033 int printedScreen = -1;
2034 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
2035 int printedMem = -1;
2036 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
2037 int state = imem+iscreen;
2038 long time = service.getDuration(serviceType, curState, curStartTime,
2039 state, now);
2040 String running = "";
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002041 if (curState == state && pw != null) {
2042 running = " (running)";
Dianne Hackbornd2932242013-08-05 18:18:42 -07002043 }
2044 if (time != 0) {
2045 if (pw != null) {
2046 pw.print(prefix);
2047 printScreenLabel(pw, printedScreen != iscreen
2048 ? iscreen : STATE_NOTHING);
2049 printedScreen = iscreen;
Dianne Hackborn237cefb2013-10-22 18:45:27 -07002050 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002051 printedMem = imem;
Dianne Hackborn237cefb2013-10-22 18:45:27 -07002052 pw.print(": ");
Dianne Hackbornd2932242013-08-05 18:18:42 -07002053 TimeUtils.formatDuration(time, pw); pw.println(running);
2054 }
2055 totalTime += time;
2056 }
2057 }
2058 }
2059 if (totalTime != 0 && pw != null) {
2060 pw.print(prefix);
Dianne Hackborn237cefb2013-10-22 18:45:27 -07002061 pw.print(" TOTAL: ");
Dianne Hackbornd2932242013-08-05 18:18:42 -07002062 TimeUtils.formatDuration(totalTime, pw);
2063 pw.println();
2064 }
2065 return totalTime;
2066 }
2067
2068 void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner,
2069 String headerPrefix, String header, ServiceState service,
2070 int count, int serviceType, int state, long startTime, long now, long totalTime,
2071 boolean dumpAll) {
2072 if (count != 0) {
2073 if (dumpAll) {
2074 pw.print(prefix); pw.print(header);
2075 pw.print(" op count "); pw.print(count); pw.println(":");
2076 dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime,
2077 now);
2078 } else {
2079 long myTime = dumpSingleServiceTime(null, null, service, serviceType, state,
2080 startTime, now);
2081 pw.print(prefix); pw.print(headerPrefix); pw.print(header);
2082 pw.print(" count "); pw.print(count);
2083 pw.print(" / time ");
2084 printPercent(pw, (double)myTime/(double)totalTime);
2085 pw.println();
2086 }
2087 }
2088 }
2089
Dianne Hackborn164371f2013-10-01 19:10:13 -07002090 public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002091 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
2092 mStartTime, now);
2093 dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002094 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002095 pw.println();
2096 dumpTotalsLocked(pw, now);
2097 }
2098
2099 void dumpTotalsLocked(PrintWriter pw, long now) {
2100 pw.println("Run time Stats:");
2101 dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now);
2102 pw.println();
2103 pw.print(" Start time: ");
2104 pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
2105 pw.println();
2106 pw.print(" Total elapsed time: ");
2107 TimeUtils.formatDuration(
2108 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
2109 - mTimePeriodStartRealtime, pw);
2110 boolean partial = true;
2111 if ((mFlags&FLAG_SHUTDOWN) != 0) {
2112 pw.print(" (shutdown)");
2113 partial = false;
2114 }
2115 if ((mFlags&FLAG_SYSPROPS) != 0) {
2116 pw.print(" (sysprops)");
2117 partial = false;
2118 }
2119 if ((mFlags&FLAG_COMPLETE) != 0) {
2120 pw.print(" (complete)");
2121 partial = false;
2122 }
2123 if (partial) {
2124 pw.print(" (partial)");
2125 }
2126 pw.print(' ');
2127 pw.print(mRuntime);
2128 pw.print(' ');
2129 pw.print(mWebView);
2130 pw.println();
2131 }
2132
2133 void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
Dianne Hackborncb428552013-09-26 11:07:17 -07002134 int[] screenStates, int[] memStates, int[] procStates,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002135 int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002136 ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002137 procStates, sortProcStates, now, reqPackage, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002138 if (procs.size() > 0) {
2139 if (header != null) {
2140 pw.println();
2141 pw.println(header);
2142 }
Dianne Hackborncb428552013-09-26 11:07:17 -07002143 dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
Dianne Hackborn8472e612014-01-23 17:57:20 -08002144 sortProcStates, true, now, totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002145 }
2146 }
2147
2148 public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
Dianne Hackborn164371f2013-10-01 19:10:13 -07002149 int[] procStates, int sortProcStates[], long now, String reqPackage,
2150 boolean activeOnly) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002151 final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
Dianne Hackborn8472e612014-01-23 17:57:20 -08002152 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002153 for (int ip=0; ip<pkgMap.size(); ip++) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002154 final String pkgName = pkgMap.keyAt(ip);
Dianne Hackborn8472e612014-01-23 17:57:20 -08002155 final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002156 for (int iu=0; iu<procs.size(); iu++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08002157 final SparseArray<PackageState> vpkgs = procs.valueAt(iu);
2158 final int NVERS = vpkgs.size();
2159 for (int iv=0; iv<NVERS; iv++) {
2160 final PackageState state = vpkgs.valueAt(iv);
2161 final int NPROCS = state.mProcesses.size();
2162 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
2163 for (int iproc=0; iproc<NPROCS; iproc++) {
2164 final ProcessState proc = state.mProcesses.valueAt(iproc);
2165 if (!pkgMatch && !reqPackage.equals(proc.mName)) {
2166 continue;
2167 }
2168 if (activeOnly && !proc.isInUse()) {
2169 continue;
2170 }
2171 foundProcs.add(proc.mCommonProcess);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002172 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002173 }
2174 }
2175 }
2176 ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
2177 for (int i=0; i<foundProcs.size(); i++) {
2178 ProcessState proc = foundProcs.valueAt(i);
Dianne Hackborn164371f2013-10-01 19:10:13 -07002179 if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002180 outProcs.add(proc);
Dianne Hackborncb428552013-09-26 11:07:17 -07002181 if (procStates != sortProcStates) {
2182 computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
2183 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002184 }
2185 }
2186 Collections.sort(outProcs, new Comparator<ProcessState>() {
2187 @Override
2188 public int compare(ProcessState lhs, ProcessState rhs) {
2189 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
2190 return -1;
2191 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
2192 return 1;
2193 }
2194 return 0;
2195 }
2196 });
2197 return outProcs;
2198 }
2199
2200 String collapseString(String pkgName, String itemName) {
2201 if (itemName.startsWith(pkgName)) {
2202 final int ITEMLEN = itemName.length();
2203 final int PKGLEN = pkgName.length();
2204 if (ITEMLEN == PKGLEN) {
2205 return "";
2206 } else if (ITEMLEN >= PKGLEN) {
2207 if (itemName.charAt(PKGLEN) == '.') {
2208 return itemName.substring(PKGLEN);
2209 }
2210 }
2211 }
2212 return itemName;
2213 }
2214
2215 public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
2216 final long now = SystemClock.uptimeMillis();
Dianne Hackborn8472e612014-01-23 17:57:20 -08002217 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
2218 pw.println("vers,4");
Dianne Hackbornd2932242013-08-05 18:18:42 -07002219 pw.print("period,"); pw.print(mTimePeriodStartClockStr);
2220 pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
2221 pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
2222 boolean partial = true;
2223 if ((mFlags&FLAG_SHUTDOWN) != 0) {
2224 pw.print(",shutdown");
2225 partial = false;
2226 }
2227 if ((mFlags&FLAG_SYSPROPS) != 0) {
2228 pw.print(",sysprops");
2229 partial = false;
2230 }
2231 if ((mFlags&FLAG_COMPLETE) != 0) {
2232 pw.print(",complete");
2233 partial = false;
2234 }
2235 if (partial) {
2236 pw.print(",partial");
2237 }
2238 pw.println();
2239 pw.print("config,"); pw.print(mRuntime); pw.print(','); pw.println(mWebView);
2240 for (int ip=0; ip<pkgMap.size(); ip++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08002241 final String pkgName = pkgMap.keyAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002242 if (reqPackage != null && !reqPackage.equals(pkgName)) {
2243 continue;
2244 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08002245 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002246 for (int iu=0; iu<uids.size(); iu++) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08002247 final int uid = uids.keyAt(iu);
2248 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
2249 for (int iv=0; iv<vpkgs.size(); iv++) {
2250 final int vers = vpkgs.keyAt(iv);
2251 final PackageState pkgState = vpkgs.valueAt(iv);
2252 final int NPROCS = pkgState.mProcesses.size();
2253 final int NSRVS = pkgState.mServices.size();
2254 for (int iproc=0; iproc<NPROCS; iproc++) {
2255 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2256 pw.print("pkgproc,");
Dianne Hackbornd2932242013-08-05 18:18:42 -07002257 pw.print(pkgName);
2258 pw.print(",");
2259 pw.print(uid);
2260 pw.print(",");
Dianne Hackborn8472e612014-01-23 17:57:20 -08002261 pw.print(vers);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002262 pw.print(",");
2263 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
Dianne Hackborn8472e612014-01-23 17:57:20 -08002264 dumpAllProcessStateCheckin(pw, proc, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002265 pw.println();
Dianne Hackborn8472e612014-01-23 17:57:20 -08002266 if (proc.mPssTableSize > 0) {
2267 pw.print("pkgpss,");
2268 pw.print(pkgName);
2269 pw.print(",");
2270 pw.print(uid);
2271 pw.print(",");
2272 pw.print(vers);
2273 pw.print(",");
2274 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2275 dumpAllProcessPssCheckin(pw, proc);
2276 pw.println();
2277 }
2278 if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0
2279 || proc.mNumCachedKill > 0) {
2280 pw.print("pkgkills,");
2281 pw.print(pkgName);
2282 pw.print(",");
2283 pw.print(uid);
2284 pw.print(",");
2285 pw.print(vers);
2286 pw.print(",");
2287 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2288 pw.print(",");
2289 pw.print(proc.mNumExcessiveWake);
2290 pw.print(",");
2291 pw.print(proc.mNumExcessiveCpu);
2292 pw.print(",");
2293 pw.print(proc.mNumCachedKill);
2294 pw.print(",");
2295 pw.print(proc.mMinCachedKillPss);
2296 pw.print(":");
2297 pw.print(proc.mAvgCachedKillPss);
2298 pw.print(":");
2299 pw.print(proc.mMaxCachedKillPss);
2300 pw.println();
2301 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002302 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08002303 for (int isvc=0; isvc<NSRVS; isvc++) {
2304 String serviceName = collapseString(pkgName,
2305 pkgState.mServices.keyAt(isvc));
2306 ServiceState svc = pkgState.mServices.valueAt(isvc);
2307 dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, vers, serviceName,
2308 svc, ServiceState.SERVICE_RUN, svc.mRunCount,
2309 svc.mRunState, svc.mRunStartTime, now);
2310 dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName,
2311 svc, ServiceState.SERVICE_STARTED, svc.mStartedCount,
2312 svc.mStartedState, svc.mStartedStartTime, now);
2313 dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName,
2314 svc, ServiceState.SERVICE_BOUND, svc.mBoundCount,
2315 svc.mBoundState, svc.mBoundStartTime, now);
2316 dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName,
2317 svc, ServiceState.SERVICE_EXEC, svc.mExecCount,
2318 svc.mExecState, svc.mExecStartTime, now);
2319 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002320 }
2321 }
2322 }
2323
2324 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2325 for (int ip=0; ip<procMap.size(); ip++) {
2326 String procName = procMap.keyAt(ip);
2327 SparseArray<ProcessState> uids = procMap.valueAt(ip);
2328 for (int iu=0; iu<uids.size(); iu++) {
2329 int uid = uids.keyAt(iu);
2330 ProcessState procState = uids.valueAt(iu);
2331 if (procState.mDurationsTableSize > 0) {
2332 pw.print("proc,");
2333 pw.print(procName);
2334 pw.print(",");
2335 pw.print(uid);
2336 dumpAllProcessStateCheckin(pw, procState, now);
2337 pw.println();
2338 }
2339 if (procState.mPssTableSize > 0) {
2340 pw.print("pss,");
2341 pw.print(procName);
2342 pw.print(",");
2343 pw.print(uid);
2344 dumpAllProcessPssCheckin(pw, procState);
2345 pw.println();
2346 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002347 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0
2348 || procState.mNumCachedKill > 0) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002349 pw.print("kills,");
2350 pw.print(procName);
2351 pw.print(",");
2352 pw.print(uid);
2353 pw.print(",");
2354 pw.print(procState.mNumExcessiveWake);
2355 pw.print(",");
2356 pw.print(procState.mNumExcessiveCpu);
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002357 pw.print(",");
2358 pw.print(procState.mNumCachedKill);
2359 pw.print(",");
2360 pw.print(procState.mMinCachedKillPss);
2361 pw.print(":");
2362 pw.print(procState.mAvgCachedKillPss);
2363 pw.print(":");
2364 pw.print(procState.mMaxCachedKillPss);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002365 pw.println();
2366 }
2367 }
2368 }
2369 pw.print("total");
2370 dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor,
2371 mStartTime, now);
2372 pw.println();
2373 }
2374
Dianne Hackborncb428552013-09-26 11:07:17 -07002375 public static class DurationsTable {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002376 public final ProcessStats mStats;
Dianne Hackborncb428552013-09-26 11:07:17 -07002377 public final String mName;
2378 public int[] mDurationsTable;
2379 public int mDurationsTableSize;
2380
2381 public DurationsTable(ProcessStats stats, String name) {
2382 mStats = stats;
2383 mName = name;
2384 }
2385
2386 void copyDurationsTo(DurationsTable other) {
2387 if (mDurationsTable != null) {
2388 mStats.mAddLongTable = new int[mDurationsTable.length];
2389 mStats.mAddLongTableSize = 0;
2390 for (int i=0; i<mDurationsTableSize; i++) {
2391 int origEnt = mDurationsTable[i];
2392 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2393 int newOff = mStats.addLongData(i, type, 1);
2394 mStats.mAddLongTable[i] = newOff | type;
2395 mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0));
2396 }
2397 other.mDurationsTable = mStats.mAddLongTable;
2398 other.mDurationsTableSize = mStats.mAddLongTableSize;
2399 } else {
2400 other.mDurationsTable = null;
2401 other.mDurationsTableSize = 0;
2402 }
2403 }
2404
2405 void addDurations(DurationsTable other) {
2406 for (int i=0; i<other.mDurationsTableSize; i++) {
2407 int ent = other.mDurationsTable[i];
2408 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2409 if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
2410 + other.mStats.getLong(ent, 0));
2411 addDuration(state, other.mStats.getLong(ent, 0));
2412 }
2413 }
2414
2415 void resetDurationsSafely() {
2416 mDurationsTable = null;
2417 mDurationsTableSize = 0;
2418 }
2419
2420 void writeDurationsToParcel(Parcel out) {
2421 out.writeInt(mDurationsTableSize);
2422 for (int i=0; i<mDurationsTableSize; i++) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002423 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
Dianne Hackborncb428552013-09-26 11:07:17 -07002424 + printLongOffset(mDurationsTable[i]));
2425 out.writeInt(mDurationsTable[i]);
2426 }
2427 }
2428
2429 boolean readDurationsFromParcel(Parcel in) {
2430 mDurationsTable = mStats.readTableFromParcel(in, mName, "durations");
2431 if (mDurationsTable == BAD_TABLE) {
2432 return false;
2433 }
2434 mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
2435 return true;
2436 }
2437
2438 void addDuration(int state, long dur) {
2439 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
2440 int off;
2441 if (idx >= 0) {
2442 off = mDurationsTable[idx];
2443 } else {
2444 mStats.mAddLongTable = mDurationsTable;
2445 mStats.mAddLongTableSize = mDurationsTableSize;
2446 off = mStats.addLongData(~idx, state, 1);
2447 mDurationsTable = mStats.mAddLongTable;
2448 mDurationsTableSize = mStats.mAddLongTableSize;
2449 }
2450 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
2451 if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
2452 + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
2453 longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
2454 }
2455
2456 long getDuration(int state, long now) {
2457 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
2458 return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
2459 }
2460 }
2461
2462 public static final class ProcessState extends DurationsTable {
Dianne Hackborn8472e612014-01-23 17:57:20 -08002463 public ProcessState mCommonProcess;
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002464 public final String mPackage;
2465 public final int mUid;
Dianne Hackborn8472e612014-01-23 17:57:20 -08002466 public final int mVersion;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002467
2468 //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
2469 int mCurState = STATE_NOTHING;
2470 long mStartTime;
2471
2472 int mLastPssState = STATE_NOTHING;
2473 long mLastPssTime;
2474 int[] mPssTable;
2475 int mPssTableSize;
2476
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002477 boolean mActive;
2478 int mNumActiveServices;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002479 int mNumStartedServices;
2480
2481 int mNumExcessiveWake;
2482 int mNumExcessiveCpu;
2483
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002484 int mNumCachedKill;
2485 long mMinCachedKillPss;
2486 long mAvgCachedKillPss;
2487 long mMaxCachedKillPss;
2488
Dianne Hackbornd2932242013-08-05 18:18:42 -07002489 boolean mMultiPackage;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002490 boolean mDead;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002491
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002492 public long mTmpTotalTime;
Dianne Hackborn8472e612014-01-23 17:57:20 -08002493 int mTmpNumInUse;
2494 ProcessState mTmpFoundSubProc;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002495
2496 /**
2497 * Create a new top-level process state, for the initial case where there is only
2498 * a single package running in a process. The initial state is not running.
2499 */
Dianne Hackborn8472e612014-01-23 17:57:20 -08002500 public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002501 super(processStats, name);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002502 mCommonProcess = this;
2503 mPackage = pkg;
2504 mUid = uid;
Dianne Hackborn8472e612014-01-23 17:57:20 -08002505 mVersion = vers;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002506 }
2507
2508 /**
2509 * Create a new per-package process state for an existing top-level process
2510 * state. The current running state of the top-level process is also copied,
2511 * marked as started running at 'now'.
2512 */
Dianne Hackborn8472e612014-01-23 17:57:20 -08002513 public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name,
Dianne Hackbornd2932242013-08-05 18:18:42 -07002514 long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002515 super(commonProcess.mStats, name);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002516 mCommonProcess = commonProcess;
2517 mPackage = pkg;
2518 mUid = uid;
Dianne Hackborn8472e612014-01-23 17:57:20 -08002519 mVersion = vers;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002520 mCurState = commonProcess.mCurState;
2521 mStartTime = now;
2522 }
2523
2524 ProcessState clone(String pkg, long now) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08002525 ProcessState pnew = new ProcessState(this, pkg, mUid, mVersion, mName, now);
Dianne Hackborncb428552013-09-26 11:07:17 -07002526 copyDurationsTo(pnew);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002527 if (mPssTable != null) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002528 mStats.mAddLongTable = new int[mPssTable.length];
2529 mStats.mAddLongTableSize = 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002530 for (int i=0; i<mPssTableSize; i++) {
2531 int origEnt = mPssTable[i];
2532 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002533 int newOff = mStats.addLongData(i, type, PSS_COUNT);
2534 mStats.mAddLongTable[i] = newOff | type;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002535 for (int j=0; j<PSS_COUNT; j++) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002536 mStats.setLong(newOff, j, mStats.getLong(origEnt, j));
Dianne Hackbornd2932242013-08-05 18:18:42 -07002537 }
2538 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002539 pnew.mPssTable = mStats.mAddLongTable;
2540 pnew.mPssTableSize = mStats.mAddLongTableSize;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002541 }
2542 pnew.mNumExcessiveWake = mNumExcessiveWake;
2543 pnew.mNumExcessiveCpu = mNumExcessiveCpu;
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002544 pnew.mNumCachedKill = mNumCachedKill;
2545 pnew.mMinCachedKillPss = mMinCachedKillPss;
2546 pnew.mAvgCachedKillPss = mAvgCachedKillPss;
2547 pnew.mMaxCachedKillPss = mMaxCachedKillPss;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002548 pnew.mActive = mActive;
Dianne Hackborn164371f2013-10-01 19:10:13 -07002549 pnew.mNumActiveServices = mNumActiveServices;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002550 pnew.mNumStartedServices = mNumStartedServices;
2551 return pnew;
2552 }
2553
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002554 void add(ProcessState other) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002555 addDurations(other);
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002556 for (int i=0; i<other.mPssTableSize; i++) {
2557 int ent = other.mPssTable[i];
2558 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2559 addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
2560 other.mStats.getLong(ent, PSS_MINIMUM),
2561 other.mStats.getLong(ent, PSS_AVERAGE),
2562 other.mStats.getLong(ent, PSS_MAXIMUM),
2563 other.mStats.getLong(ent, PSS_USS_MINIMUM),
2564 other.mStats.getLong(ent, PSS_USS_AVERAGE),
2565 other.mStats.getLong(ent, PSS_USS_MAXIMUM));
2566 }
2567 mNumExcessiveWake += other.mNumExcessiveWake;
2568 mNumExcessiveCpu += other.mNumExcessiveCpu;
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002569 if (other.mNumCachedKill > 0) {
2570 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
2571 other.mAvgCachedKillPss, other.mMaxCachedKillPss);
2572 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002573 }
2574
Dianne Hackbornd2932242013-08-05 18:18:42 -07002575 void resetSafely(long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002576 resetDurationsSafely();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002577 mStartTime = now;
2578 mLastPssState = STATE_NOTHING;
2579 mLastPssTime = 0;
2580 mPssTable = null;
2581 mPssTableSize = 0;
2582 mNumExcessiveWake = 0;
2583 mNumExcessiveCpu = 0;
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002584 mNumCachedKill = 0;
2585 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002586 }
2587
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002588 void makeDead() {
2589 mDead = true;
2590 }
2591
2592 private void ensureNotDead() {
2593 if (!mDead) {
2594 return;
2595 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002596 Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002597 + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
2598 }
2599
Dianne Hackbornd2932242013-08-05 18:18:42 -07002600 void writeToParcel(Parcel out, long now) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002601 out.writeInt(mMultiPackage ? 1 : 0);
Dianne Hackborncb428552013-09-26 11:07:17 -07002602 writeDurationsToParcel(out);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002603 out.writeInt(mPssTableSize);
2604 for (int i=0; i<mPssTableSize; i++) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002605 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
Dianne Hackbornd2932242013-08-05 18:18:42 -07002606 + printLongOffset(mPssTable[i]));
2607 out.writeInt(mPssTable[i]);
2608 }
2609 out.writeInt(mNumExcessiveWake);
2610 out.writeInt(mNumExcessiveCpu);
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002611 out.writeInt(mNumCachedKill);
2612 if (mNumCachedKill > 0) {
2613 out.writeLong(mMinCachedKillPss);
2614 out.writeLong(mAvgCachedKillPss);
2615 out.writeLong(mMaxCachedKillPss);
2616 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002617 }
2618
2619 boolean readFromParcel(Parcel in, boolean fully) {
2620 boolean multiPackage = in.readInt() != 0;
2621 if (fully) {
2622 mMultiPackage = multiPackage;
2623 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002624 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
Dianne Hackborncb428552013-09-26 11:07:17 -07002625 if (!readDurationsFromParcel(in)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002626 return false;
2627 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07002628 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002629 mPssTable = mStats.readTableFromParcel(in, mName, "pss");
Dianne Hackbornd2932242013-08-05 18:18:42 -07002630 if (mPssTable == BAD_TABLE) {
2631 return false;
2632 }
2633 mPssTableSize = mPssTable != null ? mPssTable.length : 0;
2634 mNumExcessiveWake = in.readInt();
2635 mNumExcessiveCpu = in.readInt();
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002636 mNumCachedKill = in.readInt();
2637 if (mNumCachedKill > 0) {
2638 mMinCachedKillPss = in.readLong();
2639 mAvgCachedKillPss = in.readLong();
2640 mMaxCachedKillPss = in.readLong();
2641 } else {
2642 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
2643 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002644 return true;
2645 }
2646
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002647 public void makeActive() {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002648 ensureNotDead();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002649 mActive = true;
2650 }
2651
2652 public void makeInactive() {
2653 mActive = false;
2654 }
2655
2656 public boolean isInUse() {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002657 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
2658 || mCurState != STATE_NOTHING;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002659 }
2660
Dianne Hackbornd2932242013-08-05 18:18:42 -07002661 /**
2662 * Update the current state of the given list of processes.
2663 *
2664 * @param state Current ActivityManager.PROCESS_STATE_*
2665 * @param memFactor Current mem factor constant.
2666 * @param now Current time.
2667 * @param pkgList Processes to update.
2668 */
2669 public void setState(int state, int memFactor, long now,
2670 ArrayMap<String, ProcessState> pkgList) {
2671 if (state < 0) {
2672 state = mNumStartedServices > 0
2673 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
2674 } else {
2675 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
2676 }
2677
2678 // First update the common process.
2679 mCommonProcess.setState(state, now);
2680
2681 // If the common process is not multi-package, there is nothing else to do.
2682 if (!mCommonProcess.mMultiPackage) {
2683 return;
2684 }
2685
2686 if (pkgList != null) {
2687 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2688 pullFixedProc(pkgList, ip).setState(state, now);
2689 }
2690 }
2691 }
2692
2693 void setState(int state, long now) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002694 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002695 if (mCurState != state) {
2696 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
2697 commitStateTime(now);
2698 mCurState = state;
2699 }
2700 }
2701
2702 void commitStateTime(long now) {
2703 if (mCurState != STATE_NOTHING) {
2704 long dur = now - mStartTime;
2705 if (dur > 0) {
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002706 addDuration(mCurState, dur);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002707 }
2708 }
2709 mStartTime = now;
2710 }
2711
Dianne Hackborn164371f2013-10-01 19:10:13 -07002712 void incActiveServices(String serviceName) {
2713 if (DEBUG && "".equals(mName)) {
2714 RuntimeException here = new RuntimeException("here");
2715 here.fillInStackTrace();
2716 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
2717 + " to " + (mNumActiveServices+1), here);
2718 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002719 if (mCommonProcess != this) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002720 mCommonProcess.incActiveServices(serviceName);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002721 }
2722 mNumActiveServices++;
2723 }
2724
Dianne Hackborn164371f2013-10-01 19:10:13 -07002725 void decActiveServices(String serviceName) {
2726 if (DEBUG && "".equals(mName)) {
2727 RuntimeException here = new RuntimeException("here");
2728 here.fillInStackTrace();
2729 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
2730 + " to " + (mNumActiveServices-1), here);
2731 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002732 if (mCommonProcess != this) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002733 mCommonProcess.decActiveServices(serviceName);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002734 }
2735 mNumActiveServices--;
2736 if (mNumActiveServices < 0) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002737 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
2738 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
2739 mNumActiveServices = 0;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07002740 }
2741 }
2742
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002743 void incStartedServices(int memFactor, long now, String serviceName) {
2744 if (false) {
2745 RuntimeException here = new RuntimeException("here");
2746 here.fillInStackTrace();
2747 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
2748 + " to " + (mNumStartedServices+1), here);
2749 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002750 if (mCommonProcess != this) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002751 mCommonProcess.incStartedServices(memFactor, now, serviceName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002752 }
2753 mNumStartedServices++;
2754 if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002755 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002756 }
2757 }
2758
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002759 void decStartedServices(int memFactor, long now, String serviceName) {
2760 if (false) {
2761 RuntimeException here = new RuntimeException("here");
2762 here.fillInStackTrace();
2763 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
2764 + " to " + (mNumStartedServices-1), here);
2765 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002766 if (mCommonProcess != this) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002767 mCommonProcess.decStartedServices(memFactor, now, serviceName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002768 }
2769 mNumStartedServices--;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08002770 if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
2771 setState(STATE_NOTHING, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002772 } else if (mNumStartedServices < 0) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002773 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
Dianne Hackbornd2932242013-08-05 18:18:42 -07002774 + mPackage + " uid=" + mUid + " name=" + mName);
Dianne Hackborn164371f2013-10-01 19:10:13 -07002775 mNumStartedServices = 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002776 }
2777 }
2778
Dianne Hackborncb428552013-09-26 11:07:17 -07002779 public void addPss(long pss, long uss, boolean always,
2780 ArrayMap<String, ProcessState> pkgList) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002781 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002782 if (!always) {
2783 if (mLastPssState == mCurState && SystemClock.uptimeMillis()
2784 < (mLastPssTime+(30*1000))) {
2785 return;
2786 }
2787 }
2788 mLastPssState = mCurState;
2789 mLastPssTime = SystemClock.uptimeMillis();
2790 if (mCurState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002791 // First update the common process.
2792 mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
2793
2794 // If the common process is not multi-package, there is nothing else to do.
2795 if (!mCommonProcess.mMultiPackage) {
2796 return;
2797 }
2798
2799 if (pkgList != null) {
2800 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2801 pullFixedProc(pkgList, ip).addPss(mCurState, 1,
2802 pss, pss, pss, uss, uss, uss);
2803 }
2804 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002805 }
2806 }
2807
2808 void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
2809 long avgUss, long maxUss) {
2810 int idx = binarySearch(mPssTable, mPssTableSize, state);
2811 int off;
2812 if (idx >= 0) {
2813 off = mPssTable[idx];
2814 } else {
2815 mStats.mAddLongTable = mPssTable;
2816 mStats.mAddLongTableSize = mPssTableSize;
2817 off = mStats.addLongData(~idx, state, PSS_COUNT);
2818 mPssTable = mStats.mAddLongTable;
2819 mPssTableSize = mStats.mAddLongTableSize;
2820 }
2821 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
2822 idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
2823 long count = longs[idx+PSS_SAMPLE_COUNT];
2824 if (count == 0) {
2825 longs[idx+PSS_SAMPLE_COUNT] = inCount;
2826 longs[idx+PSS_MINIMUM] = minPss;
2827 longs[idx+PSS_AVERAGE] = avgPss;
2828 longs[idx+PSS_MAXIMUM] = maxPss;
2829 longs[idx+PSS_USS_MINIMUM] = minUss;
2830 longs[idx+PSS_USS_AVERAGE] = avgUss;
2831 longs[idx+PSS_USS_MAXIMUM] = maxUss;
2832 } else {
2833 longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
2834 if (longs[idx+PSS_MINIMUM] > minPss) {
2835 longs[idx+PSS_MINIMUM] = minPss;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002836 }
Dianne Hackborn60444fd2013-08-08 21:57:14 -07002837 longs[idx+PSS_AVERAGE] = (long)(
2838 ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
2839 / (count+inCount) );
2840 if (longs[idx+PSS_MAXIMUM] < maxPss) {
2841 longs[idx+PSS_MAXIMUM] = maxPss;
2842 }
2843 if (longs[idx+PSS_USS_MINIMUM] > minUss) {
2844 longs[idx+PSS_USS_MINIMUM] = minUss;
2845 }
2846 longs[idx+PSS_USS_AVERAGE] = (long)(
2847 ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
2848 / (count+inCount) );
2849 if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
2850 longs[idx+PSS_USS_MAXIMUM] = maxUss;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002851 }
2852 }
2853 }
2854
2855 public void reportExcessiveWake(ArrayMap<String, ProcessState> pkgList) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002856 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002857 mCommonProcess.mNumExcessiveWake++;
2858 if (!mCommonProcess.mMultiPackage) {
2859 return;
2860 }
2861
2862 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2863 pullFixedProc(pkgList, ip).mNumExcessiveWake++;
2864 }
2865 }
2866
2867 public void reportExcessiveCpu(ArrayMap<String, ProcessState> pkgList) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002868 ensureNotDead();
Dianne Hackbornd2932242013-08-05 18:18:42 -07002869 mCommonProcess.mNumExcessiveCpu++;
2870 if (!mCommonProcess.mMultiPackage) {
2871 return;
2872 }
2873
2874 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2875 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
2876 }
2877 }
2878
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07002879 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
2880 if (mNumCachedKill <= 0) {
2881 mNumCachedKill = num;
2882 mMinCachedKillPss = minPss;
2883 mAvgCachedKillPss = avgPss;
2884 mMaxCachedKillPss = maxPss;
2885 } else {
2886 if (minPss < mMinCachedKillPss) {
2887 mMinCachedKillPss = minPss;
2888 }
2889 if (maxPss > mMaxCachedKillPss) {
2890 mMaxCachedKillPss = maxPss;
2891 }
2892 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
2893 / (mNumCachedKill+num) );
2894 mNumCachedKill += num;
2895 }
2896 }
2897
2898 public void reportCachedKill(ArrayMap<String, ProcessState> pkgList, long pss) {
2899 ensureNotDead();
2900 mCommonProcess.addCachedKill(1, pss, pss, pss);
2901 if (!mCommonProcess.mMultiPackage) {
2902 return;
2903 }
2904
2905 for (int ip=pkgList.size()-1; ip>=0; ip--) {
2906 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
2907 }
2908 }
2909
Dianne Hackbornd2932242013-08-05 18:18:42 -07002910 ProcessState pullFixedProc(String pkgName) {
2911 if (mMultiPackage) {
2912 // The array map is still pointing to a common process state
2913 // that is now shared across packages. Update it to point to
2914 // the new per-package state.
Dianne Hackborn8472e612014-01-23 17:57:20 -08002915 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid);
2916 if (vpkg == null) {
2917 throw new IllegalStateException("Didn't find package " + pkgName
2918 + " / " + mUid);
2919 }
2920 PackageState pkg = vpkg.get(mVersion);
2921 if (pkg == null) {
2922 throw new IllegalStateException("Didn't find package " + pkgName
2923 + " / " + mUid + " vers " + mVersion);
2924 }
2925 ProcessState proc = pkg.mProcesses.get(mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002926 if (proc == null) {
Dianne Hackborn8472e612014-01-23 17:57:20 -08002927 throw new IllegalStateException("Didn't create per-package process "
2928 + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002929 }
2930 return proc;
2931 }
2932 return this;
2933 }
2934
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002935 private ProcessState pullFixedProc(ArrayMap<String, ProcessState> pkgList, int index) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07002936 ProcessState proc = pkgList.valueAt(index);
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002937 if (mDead && proc.mCommonProcess != proc) {
Dianne Hackborn53459a72013-09-17 17:14:57 -07002938 // Somehow we are contining to use a process state that is dead, because
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002939 // it was not being told it was active during the last commit. We can recover
2940 // from this by generating a fresh new state, but this is bad because we
2941 // are losing whatever data we had in the old process state.
2942 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
2943 + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
Dianne Hackborn8472e612014-01-23 17:57:20 -08002944 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion,
2945 proc.mName);
Dianne Hackborn50ef0b62013-09-16 17:40:27 -07002946 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07002947 if (proc.mMultiPackage) {
2948 // The array map is still pointing to a common process state
2949 // that is now shared across packages. Update it to point to
2950 // the new per-package state.
Dianne Hackborn8472e612014-01-23 17:57:20 -08002951 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index),
2952 proc.mUid);
2953 if (vpkg == null) {
Dianne Hackborna0332372013-09-13 18:34:13 -07002954 throw new IllegalStateException("No existing package "
Dianne Hackborn164371f2013-10-01 19:10:13 -07002955 + pkgList.keyAt(index) + "/" + proc.mUid
2956 + " for multi-proc " + proc.mName);
Dianne Hackborna0332372013-09-13 18:34:13 -07002957 }
Dianne Hackborn8472e612014-01-23 17:57:20 -08002958 PackageState pkg = vpkg.get(proc.mVersion);
2959 if (pkg == null) {
2960 throw new IllegalStateException("No existing package "
2961 + pkgList.keyAt(index) + "/" + proc.mUid
2962 + " for multi-proc " + proc.mName + " version " + proc.mVersion);
2963 }
Dianne Hackborna0332372013-09-13 18:34:13 -07002964 proc = pkg.mProcesses.get(proc.mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002965 if (proc == null) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07002966 throw new IllegalStateException("Didn't create per-package process "
2967 + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002968 }
2969 pkgList.setValueAt(index, proc);
2970 }
2971 return proc;
2972 }
2973
2974 long getDuration(int state, long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07002975 long time = super.getDuration(state, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07002976 if (mCurState == state) {
2977 time += now - mStartTime;
2978 }
2979 return time;
2980 }
2981
2982 long getPssSampleCount(int state) {
2983 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002984 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002985 }
2986
2987 long getPssMinimum(int state) {
2988 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002989 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002990 }
2991
2992 long getPssAverage(int state) {
2993 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002994 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07002995 }
2996
2997 long getPssMaximum(int state) {
2998 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07002999 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003000 }
3001
3002 long getPssUssMinimum(int state) {
3003 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003004 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003005 }
3006
3007 long getPssUssAverage(int state) {
3008 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003009 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003010 }
3011
3012 long getPssUssMaximum(int state) {
3013 int idx = binarySearch(mPssTable, mPssTableSize, state);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003014 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003015 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003016
3017 public String toString() {
3018 StringBuilder sb = new StringBuilder(128);
3019 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
3020 .append(" ").append(mName).append("/").append(mUid)
3021 .append(" pkg=").append(mPackage);
3022 if (mMultiPackage) sb.append(" (multi)");
3023 if (mCommonProcess != this) sb.append(" (sub)");
3024 sb.append("}");
3025 return sb.toString();
3026 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003027 }
3028
Dianne Hackborncb428552013-09-26 11:07:17 -07003029 public static final class ServiceState extends DurationsTable {
Dianne Hackborn69cb00b2013-08-09 16:16:56 -07003030 public final String mPackage;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003031 public final String mProcessName;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003032 ProcessState mProc;
3033
Dianne Hackborn164371f2013-10-01 19:10:13 -07003034 Object mOwner;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003035
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003036 public static final int SERVICE_RUN = 0;
3037 public static final int SERVICE_STARTED = 1;
3038 public static final int SERVICE_BOUND = 2;
3039 public static final int SERVICE_EXEC = 3;
3040 static final int SERVICE_COUNT = 4;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003041
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003042 int mRunCount;
3043 public int mRunState = STATE_NOTHING;
3044 long mRunStartTime;
3045
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003046 boolean mStarted;
3047 boolean mRestarting;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003048 int mStartedCount;
3049 public int mStartedState = STATE_NOTHING;
3050 long mStartedStartTime;
3051
3052 int mBoundCount;
3053 public int mBoundState = STATE_NOTHING;
3054 long mBoundStartTime;
3055
3056 int mExecCount;
3057 public int mExecState = STATE_NOTHING;
3058 long mExecStartTime;
3059
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003060 public ServiceState(ProcessStats processStats, String pkg, String name,
3061 String processName, ProcessState proc) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003062 super(processStats, name);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003063 mPackage = pkg;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003064 mProcessName = processName;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003065 mProc = proc;
3066 }
3067
Dianne Hackborn164371f2013-10-01 19:10:13 -07003068 public void applyNewOwner(Object newOwner) {
3069 if (mOwner != newOwner) {
3070 if (mOwner == null) {
3071 mOwner = newOwner;
3072 mProc.incActiveServices(mName);
3073 } else {
3074 // There was already an old owner, reset this object for its
3075 // new owner.
3076 mOwner = newOwner;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003077 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003078 long now = SystemClock.uptimeMillis();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003079 if (mStarted) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003080 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
3081 + " from " + mOwner + " while started: pkg="
3082 + mPackage + " service=" + mName + " proc=" + mProc);
3083 setStarted(false, 0, now);
3084 }
3085 if (mBoundState != STATE_NOTHING) {
3086 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
3087 + " from " + mOwner + " while bound: pkg="
3088 + mPackage + " service=" + mName + " proc=" + mProc);
3089 setBound(false, 0, now);
3090 }
3091 if (mExecState != STATE_NOTHING) {
3092 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
3093 + " from " + mOwner + " while executing: pkg="
3094 + mPackage + " service=" + mName + " proc=" + mProc);
3095 setExecuting(false, 0, now);
3096 }
3097 }
3098 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003099 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003100 }
3101
Dianne Hackborn878deb32013-10-14 16:55:09 -07003102 public void clearCurrentOwner(Object owner, boolean silently) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003103 if (mOwner == owner) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003104 mProc.decActiveServices(mName);
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003105 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003106 long now = SystemClock.uptimeMillis();
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003107 if (mStarted) {
Dianne Hackborn878deb32013-10-14 16:55:09 -07003108 if (!silently) {
3109 Slog.wtfStack(TAG, "Service owner " + owner
3110 + " cleared while started: pkg=" + mPackage + " service="
3111 + mName + " proc=" + mProc);
3112 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003113 setStarted(false, 0, now);
3114 }
3115 if (mBoundState != STATE_NOTHING) {
Dianne Hackborn878deb32013-10-14 16:55:09 -07003116 if (!silently) {
3117 Slog.wtfStack(TAG, "Service owner " + owner
3118 + " cleared while bound: pkg=" + mPackage + " service="
3119 + mName + " proc=" + mProc);
3120 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003121 setBound(false, 0, now);
3122 }
3123 if (mExecState != STATE_NOTHING) {
Dianne Hackborn878deb32013-10-14 16:55:09 -07003124 if (!silently) {
3125 Slog.wtfStack(TAG, "Service owner " + owner
3126 + " cleared while exec: pkg=" + mPackage + " service="
3127 + mName + " proc=" + mProc);
3128 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003129 setExecuting(false, 0, now);
3130 }
3131 }
Dianne Hackborn878deb32013-10-14 16:55:09 -07003132 mOwner = null;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003133 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003134 }
3135
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003136 public boolean isInUse() {
Dianne Hackborndfc60ec2014-02-18 17:42:55 -08003137 return mOwner != null || mRestarting;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003138 }
3139
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003140 void add(ServiceState other) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003141 addDurations(other);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003142 mRunCount += other.mRunCount;
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003143 mStartedCount += other.mStartedCount;
3144 mBoundCount += other.mBoundCount;
3145 mExecCount += other.mExecCount;
3146 }
3147
Dianne Hackbornd2932242013-08-05 18:18:42 -07003148 void resetSafely(long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003149 resetDurationsSafely();
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003150 mRunCount = mRunState != STATE_NOTHING ? 1 : 0;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003151 mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
3152 mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
3153 mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
Dianne Hackborncb428552013-09-26 11:07:17 -07003154 mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003155 }
3156
3157 void writeToParcel(Parcel out, long now) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003158 writeDurationsToParcel(out);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003159 out.writeInt(mRunCount);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003160 out.writeInt(mStartedCount);
3161 out.writeInt(mBoundCount);
3162 out.writeInt(mExecCount);
3163 }
3164
3165 boolean readFromParcel(Parcel in) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003166 if (!readDurationsFromParcel(in)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003167 return false;
3168 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003169 mRunCount = in.readInt();
Dianne Hackbornd2932242013-08-05 18:18:42 -07003170 mStartedCount = in.readInt();
3171 mBoundCount = in.readInt();
3172 mExecCount = in.readInt();
3173 return true;
3174 }
3175
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003176 void commitStateTime(long now) {
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003177 if (mRunState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003178 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime);
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003179 mRunStartTime = now;
3180 }
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003181 if (mStartedState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003182 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003183 now - mStartedStartTime);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003184 mStartedStartTime = now;
3185 }
3186 if (mBoundState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003187 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003188 mBoundStartTime = now;
3189 }
3190 if (mExecState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003191 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003192 mExecStartTime = now;
3193 }
3194 }
3195
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003196 private void updateRunning(int memFactor, long now) {
3197 final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
3198 || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
3199 if (mRunState != state) {
3200 if (mRunState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003201 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT),
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003202 now - mRunStartTime);
3203 } else if (state != STATE_NOTHING) {
3204 mRunCount++;
3205 }
3206 mRunState = state;
3207 mRunStartTime = now;
3208 }
3209 }
3210
Dianne Hackbornd2932242013-08-05 18:18:42 -07003211 public void setStarted(boolean started, int memFactor, long now) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003212 if (mOwner == null) {
3213 Slog.wtf(TAG, "Starting service " + this + " without owner");
Dianne Hackbornd2932242013-08-05 18:18:42 -07003214 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003215 mStarted = started;
3216 updateStartedState(memFactor, now);
3217 }
3218
3219 public void setRestarting(boolean restarting, int memFactor, long now) {
3220 mRestarting = restarting;
3221 updateStartedState(memFactor, now);
3222 }
3223
3224 void updateStartedState(int memFactor, long now) {
Dianne Hackbornae36b232013-09-03 18:12:53 -07003225 final boolean wasStarted = mStartedState != STATE_NOTHING;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003226 final boolean started = mStarted || mRestarting;
Dianne Hackbornae36b232013-09-03 18:12:53 -07003227 final int state = started ? memFactor : STATE_NOTHING;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003228 if (mStartedState != state) {
3229 if (mStartedState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003230 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003231 now - mStartedStartTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003232 } else if (started) {
3233 mStartedCount++;
3234 }
3235 mStartedState = state;
3236 mStartedStartTime = now;
Dianne Hackbornae36b232013-09-03 18:12:53 -07003237 mProc = mProc.pullFixedProc(mPackage);
3238 if (wasStarted != started) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003239 if (started) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003240 mProc.incStartedServices(memFactor, now, mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003241 } else {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08003242 mProc.decStartedServices(memFactor, now, mName);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003243 }
3244 }
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003245 updateRunning(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003246 }
3247 }
3248
3249 public void setBound(boolean bound, int memFactor, long now) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003250 if (mOwner == null) {
3251 Slog.wtf(TAG, "Binding service " + this + " without owner");
Dianne Hackbornd2932242013-08-05 18:18:42 -07003252 }
Dianne Hackbornae36b232013-09-03 18:12:53 -07003253 final int state = bound ? memFactor : STATE_NOTHING;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003254 if (mBoundState != state) {
3255 if (mBoundState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003256 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
Dianne Hackborn60444fd2013-08-08 21:57:14 -07003257 now - mBoundStartTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003258 } else if (bound) {
3259 mBoundCount++;
3260 }
3261 mBoundState = state;
3262 mBoundStartTime = now;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003263 updateRunning(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003264 }
3265 }
3266
3267 public void setExecuting(boolean executing, int memFactor, long now) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07003268 if (mOwner == null) {
3269 Slog.wtf(TAG, "Executing service " + this + " without owner");
Dianne Hackbornd2932242013-08-05 18:18:42 -07003270 }
Dianne Hackbornae36b232013-09-03 18:12:53 -07003271 final int state = executing ? memFactor : STATE_NOTHING;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003272 if (mExecState != state) {
3273 if (mExecState != STATE_NOTHING) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003274 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003275 } else if (executing) {
3276 mExecCount++;
3277 }
3278 mExecState = state;
3279 mExecStartTime = now;
Dianne Hackbornbe4c1d72013-09-09 09:44:05 -07003280 updateRunning(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003281 }
3282 }
3283
Dianne Hackbornd2932242013-08-05 18:18:42 -07003284 private long getDuration(int opType, int curState, long startTime, int memFactor,
3285 long now) {
3286 int state = opType + (memFactor*SERVICE_COUNT);
Dianne Hackborncb428552013-09-26 11:07:17 -07003287 long time = getDuration(state, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -07003288 if (curState == memFactor) {
3289 time += now - startTime;
3290 }
3291 return time;
3292 }
Dianne Hackborn164371f2013-10-01 19:10:13 -07003293
3294 public String toString() {
3295 return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
3296 + " " + mName + " pkg=" + mPackage + " proc="
3297 + Integer.toHexString(System.identityHashCode(this)) + "}";
3298 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003299 }
3300
3301 public static final class PackageState {
3302 public final ArrayMap<String, ProcessState> mProcesses
3303 = new ArrayMap<String, ProcessState>();
3304 public final ArrayMap<String, ServiceState> mServices
3305 = new ArrayMap<String, ServiceState>();
Dianne Hackborncb428552013-09-26 11:07:17 -07003306 public final String mPackageName;
3307 public final int mUid;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003308
Dianne Hackborncb428552013-09-26 11:07:17 -07003309 public PackageState(String packageName, int uid) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003310 mUid = uid;
Dianne Hackborncb428552013-09-26 11:07:17 -07003311 mPackageName = packageName;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003312 }
3313 }
3314
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003315 public static final class ProcessDataCollection {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003316 final int[] screenStates;
3317 final int[] memStates;
3318 final int[] procStates;
3319
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003320 public long totalTime;
3321 public long numPss;
3322 public long minPss;
3323 public long avgPss;
3324 public long maxPss;
3325 public long minUss;
3326 public long avgUss;
3327 public long maxUss;
Dianne Hackbornd2932242013-08-05 18:18:42 -07003328
Dianne Hackborn8a0de582013-08-07 15:22:07 -07003329 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07003330 screenStates = _screenStates;
3331 memStates = _memStates;
3332 procStates = _procStates;
3333 }
3334
3335 void print(PrintWriter pw, long overallTime, boolean full) {
Dianne Hackborncb428552013-09-26 11:07:17 -07003336 if (totalTime > overallTime) {
3337 pw.print("*");
3338 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07003339 printPercent(pw, (double) totalTime / (double) overallTime);
3340 if (numPss > 0) {
3341 pw.print(" (");
3342 printSizeValue(pw, minPss * 1024);
3343 pw.print("-");
3344 printSizeValue(pw, avgPss * 1024);
3345 pw.print("-");
3346 printSizeValue(pw, maxPss * 1024);
3347 pw.print("/");
3348 printSizeValue(pw, minUss * 1024);
3349 pw.print("-");
3350 printSizeValue(pw, avgUss * 1024);
3351 pw.print("-");
3352 printSizeValue(pw, maxUss * 1024);
3353 if (full) {
3354 pw.print(" over ");
3355 pw.print(numPss);
3356 }
3357 pw.print(")");
3358 }
3359 }
3360 }
3361}