blob: efc9c02f1da939870bbe5bee0639855349454dd9 [file] [log] [blame]
Joe Onorato4eb64fd2016-03-21 15:30:09 -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.procstats;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.os.SystemClock;
22import android.os.SystemProperties;
23import android.os.UserHandle;
Yi Jin9680cfa2017-09-15 15:14:43 -070024import android.service.pm.PackageProto;
25import android.service.procstats.ProcessStatsProto;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070026import android.text.format.DateFormat;
27import android.util.ArrayMap;
28import android.util.ArraySet;
29import android.util.DebugUtils;
30import android.util.Log;
Dianne Hackborn3accca02013-09-20 09:32:11 -070031import android.util.LongSparseArray;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070032import android.util.Slog;
33import android.util.SparseArray;
34import android.util.TimeUtils;
Yi Jin9680cfa2017-09-15 15:14:43 -070035import android.util.proto.ProtoOutputStream;
36import android.util.proto.ProtoUtils;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070037
38import com.android.internal.app.procstats.ProcessStats;
39import com.android.internal.app.procstats.ProcessStats.PackageState;
40import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
41import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
42import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
43import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM;
44import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE;
45import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM;
46import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM;
47import static com.android.internal.app.procstats.ProcessStats.PSS_USS_AVERAGE;
48import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
49import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT;
50import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
51import static com.android.internal.app.procstats.ProcessStats.STATE_PERSISTENT;
52import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
53import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_FOREGROUND;
54import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
55import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP;
56import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
57import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE;
58import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE_RESTARTING;
59import static com.android.internal.app.procstats.ProcessStats.STATE_RECEIVER;
60import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
61import static com.android.internal.app.procstats.ProcessStats.STATE_LAST_ACTIVITY;
62import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY;
63import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY_CLIENT;
64import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY;
65import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
66
67import dalvik.system.VMRuntime;
68import libcore.util.EmptyArray;
69
70import java.io.IOException;
71import java.io.InputStream;
72import java.io.PrintWriter;
73import java.util.ArrayList;
74import java.util.Arrays;
75import java.util.Collections;
76import java.util.Comparator;
Yi Jin9680cfa2017-09-15 15:14:43 -070077import java.util.HashMap;
78import java.util.List;
79import java.util.Map;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070080import java.util.Objects;
81
82public final class ProcessState {
83 private static final String TAG = "ProcessStats";
84 private static final boolean DEBUG = false;
85 private static final boolean DEBUG_PARCEL = false;
86
87 // Map from process states to the states we track.
88 private static final int[] PROCESS_STATE_TO_STATE = new int[] {
89 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
90 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
91 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
92 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
93 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
Joe Onorato4eb64fd2016-03-21 15:30:09 -070094 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
95 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
Dianne Hackborn83b40f62017-04-26 13:59:47 -070096 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
Joe Onorato4eb64fd2016-03-21 15:30:09 -070097 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP
Joe Onorato4eb64fd2016-03-21 15:30:09 -070098 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE
99 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER
Dianne Hackbornbad8d912017-12-18 16:45:52 -0800100 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
Dianne Hackbornf097d422017-12-15 16:32:19 -0800101 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700102 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME
103 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
104 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
105 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
Dianne Hackborn68a06332017-11-15 17:54:18 -0800106 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_RECENT
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700107 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
108 };
109
110 public static final Comparator<ProcessState> COMPARATOR = new Comparator<ProcessState>() {
111 @Override
112 public int compare(ProcessState lhs, ProcessState rhs) {
113 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
114 return -1;
115 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
116 return 1;
117 }
118 return 0;
119 }
120 };
121
122 static class PssAggr {
123 long pss = 0;
124 long samples = 0;
125
126 void add(long newPss, long newSamples) {
127 pss = (long)( (pss*(double)samples) + (newPss*(double)newSamples) )
128 / (samples+newSamples);
129 samples += newSamples;
130 }
131 }
132
133 // Used by reset to count rather than storing extra maps. Be careful.
134 public int tmpNumInUse;
135 public ProcessState tmpFoundSubProc;
136
137 private final ProcessStats mStats;
138 private final String mName;
139 private final String mPackage;
140 private final int mUid;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700141 private final long mVersion;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700142 private final DurationsTable mDurations;
143 private final PssTable mPssTable;
144
145 private ProcessState mCommonProcess;
146 private int mCurState = STATE_NOTHING;
147 private long mStartTime;
148
149 private int mLastPssState = STATE_NOTHING;
150 private long mLastPssTime;
151
152 private boolean mActive;
153 private int mNumActiveServices;
154 private int mNumStartedServices;
155
156 private int mNumExcessiveWake;
157 private int mNumExcessiveCpu;
158
159 private int mNumCachedKill;
160 private long mMinCachedKillPss;
161 private long mAvgCachedKillPss;
162 private long mMaxCachedKillPss;
163
164 private boolean mMultiPackage;
165 private boolean mDead;
166
167 // Set in computeProcessTimeLocked and used by COMPARATOR to sort. Be careful.
168 private long mTmpTotalTime;
169
170 /**
171 * Create a new top-level process state, for the initial case where there is only
172 * a single package running in a process. The initial state is not running.
173 */
Dianne Hackborn3accca02013-09-20 09:32:11 -0700174 public ProcessState(ProcessStats processStats, String pkg, int uid, long vers, String name) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700175 mStats = processStats;
176 mName = name;
177 mCommonProcess = this;
178 mPackage = pkg;
179 mUid = uid;
180 mVersion = vers;
181 mDurations = new DurationsTable(processStats.mTableData);
182 mPssTable = new PssTable(processStats.mTableData);
183 }
184
185 /**
186 * Create a new per-package process state for an existing top-level process
187 * state. The current running state of the top-level process is also copied,
188 * marked as started running at 'now'.
189 */
Dianne Hackborn3accca02013-09-20 09:32:11 -0700190 public ProcessState(ProcessState commonProcess, String pkg, int uid, long vers, String name,
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700191 long now) {
192 mStats = commonProcess.mStats;
193 mName = name;
194 mCommonProcess = commonProcess;
195 mPackage = pkg;
196 mUid = uid;
197 mVersion = vers;
198 mCurState = commonProcess.mCurState;
199 mStartTime = now;
200 mDurations = new DurationsTable(commonProcess.mStats.mTableData);
201 mPssTable = new PssTable(commonProcess.mStats.mTableData);
202 }
203
204 public ProcessState clone(long now) {
205 ProcessState pnew = new ProcessState(this, mPackage, mUid, mVersion, mName, now);
206 pnew.mDurations.addDurations(mDurations);
207 pnew.mPssTable.copyFrom(mPssTable, PSS_COUNT);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700208 pnew.mNumExcessiveCpu = mNumExcessiveCpu;
209 pnew.mNumCachedKill = mNumCachedKill;
210 pnew.mMinCachedKillPss = mMinCachedKillPss;
211 pnew.mAvgCachedKillPss = mAvgCachedKillPss;
212 pnew.mMaxCachedKillPss = mMaxCachedKillPss;
213 pnew.mActive = mActive;
214 pnew.mNumActiveServices = mNumActiveServices;
215 pnew.mNumStartedServices = mNumStartedServices;
216 return pnew;
217 }
218
219 public String getName() {
220 return mName;
221 }
222
223 public ProcessState getCommonProcess() {
224 return mCommonProcess;
225 }
226
227 /**
228 * Say that we are not part of a shared process, so mCommonProcess = this.
229 */
230 public void makeStandalone() {
231 mCommonProcess = this;
232 }
233
234 public String getPackage() {
235 return mPackage;
236 }
237
238 public int getUid() {
239 return mUid;
240 }
241
Dianne Hackborn3accca02013-09-20 09:32:11 -0700242 public long getVersion() {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700243 return mVersion;
244 }
245
246 public boolean isMultiPackage() {
247 return mMultiPackage;
248 }
249
250 public void setMultiPackage(boolean val) {
251 mMultiPackage = val;
252 }
253
254 public int getDurationsBucketCount() {
255 return mDurations.getKeyCount();
256 }
257
258 public void add(ProcessState other) {
259 mDurations.addDurations(other.mDurations);
260 mPssTable.mergeStats(other.mPssTable);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700261 mNumExcessiveCpu += other.mNumExcessiveCpu;
262 if (other.mNumCachedKill > 0) {
263 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
264 other.mAvgCachedKillPss, other.mMaxCachedKillPss);
265 }
266 }
267
268 public void resetSafely(long now) {
269 mDurations.resetTable();
270 mPssTable.resetTable();
271 mStartTime = now;
272 mLastPssState = STATE_NOTHING;
273 mLastPssTime = 0;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700274 mNumExcessiveCpu = 0;
275 mNumCachedKill = 0;
276 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
277 }
278
279 public void makeDead() {
280 mDead = true;
281 }
282
283 private void ensureNotDead() {
284 if (!mDead) {
285 return;
286 }
Joe Onorato1cc1d132016-05-17 15:31:38 -0700287 Slog.w(TAG, "ProcessState dead: name=" + mName
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700288 + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
289 }
290
291 public void writeToParcel(Parcel out, long now) {
292 out.writeInt(mMultiPackage ? 1 : 0);
293 mDurations.writeToParcel(out);
294 mPssTable.writeToParcel(out);
Dianne Hackbornffca58b2017-05-24 16:15:45 -0700295 out.writeInt(0); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700296 out.writeInt(mNumExcessiveCpu);
297 out.writeInt(mNumCachedKill);
298 if (mNumCachedKill > 0) {
299 out.writeLong(mMinCachedKillPss);
300 out.writeLong(mAvgCachedKillPss);
301 out.writeLong(mMaxCachedKillPss);
302 }
303 }
304
305 public boolean readFromParcel(Parcel in, boolean fully) {
306 boolean multiPackage = in.readInt() != 0;
307 if (fully) {
308 mMultiPackage = multiPackage;
309 }
310 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
311 if (!mDurations.readFromParcel(in)) {
312 return false;
313 }
314 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
315 if (!mPssTable.readFromParcel(in)) {
316 return false;
317 }
Dianne Hackbornffca58b2017-05-24 16:15:45 -0700318 in.readInt(); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700319 mNumExcessiveCpu = in.readInt();
320 mNumCachedKill = in.readInt();
321 if (mNumCachedKill > 0) {
322 mMinCachedKillPss = in.readLong();
323 mAvgCachedKillPss = in.readLong();
324 mMaxCachedKillPss = in.readLong();
325 } else {
326 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
327 }
328 return true;
329 }
330
331 public void makeActive() {
332 ensureNotDead();
333 mActive = true;
334 }
335
336 public void makeInactive() {
337 mActive = false;
338 }
339
340 public boolean isInUse() {
341 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
342 || mCurState != STATE_NOTHING;
343 }
344
345 public boolean isActive() {
346 return mActive;
347 }
348
349 public boolean hasAnyData() {
350 return !(mDurations.getKeyCount() == 0
351 && mCurState == STATE_NOTHING
352 && mPssTable.getKeyCount() == 0);
353 }
354
355 /**
356 * Update the current state of the given list of processes.
357 *
358 * @param state Current ActivityManager.PROCESS_STATE_*
359 * @param memFactor Current mem factor constant.
360 * @param now Current time.
361 * @param pkgList Processes to update.
362 */
363 public void setState(int state, int memFactor, long now,
364 ArrayMap<String, ProcessStateHolder> pkgList) {
365 if (state < 0) {
366 state = mNumStartedServices > 0
367 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
368 } else {
369 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
370 }
371
372 // First update the common process.
373 mCommonProcess.setState(state, now);
374
375 // If the common process is not multi-package, there is nothing else to do.
376 if (!mCommonProcess.mMultiPackage) {
377 return;
378 }
379
380 if (pkgList != null) {
381 for (int ip=pkgList.size()-1; ip>=0; ip--) {
382 pullFixedProc(pkgList, ip).setState(state, now);
383 }
384 }
385 }
386
387 public void setState(int state, long now) {
388 ensureNotDead();
pengzhicai5c6740a2016-09-27 16:57:56 +0800389 if (!mDead && (mCurState != state)) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700390 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
391 commitStateTime(now);
392 mCurState = state;
393 }
394 }
395
396 public void commitStateTime(long now) {
397 if (mCurState != STATE_NOTHING) {
398 long dur = now - mStartTime;
399 if (dur > 0) {
400 mDurations.addDuration(mCurState, dur);
401 }
402 }
403 mStartTime = now;
404 }
405
406 public void incActiveServices(String serviceName) {
407 if (DEBUG && "".equals(mName)) {
408 RuntimeException here = new RuntimeException("here");
409 here.fillInStackTrace();
410 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
411 + " to " + (mNumActiveServices+1), here);
412 }
413 if (mCommonProcess != this) {
414 mCommonProcess.incActiveServices(serviceName);
415 }
416 mNumActiveServices++;
417 }
418
419 public void decActiveServices(String serviceName) {
420 if (DEBUG && "".equals(mName)) {
421 RuntimeException here = new RuntimeException("here");
422 here.fillInStackTrace();
423 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
424 + " to " + (mNumActiveServices-1), here);
425 }
426 if (mCommonProcess != this) {
427 mCommonProcess.decActiveServices(serviceName);
428 }
429 mNumActiveServices--;
430 if (mNumActiveServices < 0) {
431 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
432 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
433 mNumActiveServices = 0;
434 }
435 }
436
437 public void incStartedServices(int memFactor, long now, String serviceName) {
438 if (false) {
439 RuntimeException here = new RuntimeException("here");
440 here.fillInStackTrace();
441 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
442 + " to " + (mNumStartedServices+1), here);
443 }
444 if (mCommonProcess != this) {
445 mCommonProcess.incStartedServices(memFactor, now, serviceName);
446 }
447 mNumStartedServices++;
448 if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
449 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
450 }
451 }
452
453 public void decStartedServices(int memFactor, long now, String serviceName) {
454 if (false) {
455 RuntimeException here = new RuntimeException("here");
456 here.fillInStackTrace();
457 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
458 + " to " + (mNumStartedServices-1), here);
459 }
460 if (mCommonProcess != this) {
461 mCommonProcess.decStartedServices(memFactor, now, serviceName);
462 }
463 mNumStartedServices--;
464 if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
465 setState(STATE_NOTHING, now);
466 } else if (mNumStartedServices < 0) {
467 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
468 + mPackage + " uid=" + mUid + " name=" + mName);
469 mNumStartedServices = 0;
470 }
471 }
472
473 public void addPss(long pss, long uss, boolean always,
474 ArrayMap<String, ProcessStateHolder> pkgList) {
475 ensureNotDead();
476 if (!always) {
477 if (mLastPssState == mCurState && SystemClock.uptimeMillis()
478 < (mLastPssTime+(30*1000))) {
479 return;
480 }
481 }
482 mLastPssState = mCurState;
483 mLastPssTime = SystemClock.uptimeMillis();
484 if (mCurState != STATE_NOTHING) {
485 // First update the common process.
486 mCommonProcess.mPssTable.mergeStats(mCurState, 1, pss, pss, pss, uss, uss, uss);
487
488 // If the common process is not multi-package, there is nothing else to do.
489 if (!mCommonProcess.mMultiPackage) {
490 return;
491 }
492
493 if (pkgList != null) {
494 for (int ip=pkgList.size()-1; ip>=0; ip--) {
495 pullFixedProc(pkgList, ip).mPssTable.mergeStats(mCurState, 1,
496 pss, pss, pss, uss, uss, uss);
497 }
498 }
499 }
500 }
501
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700502 public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) {
503 ensureNotDead();
504 mCommonProcess.mNumExcessiveCpu++;
505 if (!mCommonProcess.mMultiPackage) {
506 return;
507 }
508
509 for (int ip=pkgList.size()-1; ip>=0; ip--) {
510 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
511 }
512 }
513
514 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
515 if (mNumCachedKill <= 0) {
516 mNumCachedKill = num;
517 mMinCachedKillPss = minPss;
518 mAvgCachedKillPss = avgPss;
519 mMaxCachedKillPss = maxPss;
520 } else {
521 if (minPss < mMinCachedKillPss) {
522 mMinCachedKillPss = minPss;
523 }
524 if (maxPss > mMaxCachedKillPss) {
525 mMaxCachedKillPss = maxPss;
526 }
527 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
528 / (mNumCachedKill+num) );
529 mNumCachedKill += num;
530 }
531 }
532
533 public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) {
534 ensureNotDead();
535 mCommonProcess.addCachedKill(1, pss, pss, pss);
536 if (!mCommonProcess.mMultiPackage) {
537 return;
538 }
539
540 for (int ip=pkgList.size()-1; ip>=0; ip--) {
541 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
542 }
543 }
544
545 public ProcessState pullFixedProc(String pkgName) {
546 if (mMultiPackage) {
547 // The array map is still pointing to a common process state
548 // that is now shared across packages. Update it to point to
549 // the new per-package state.
Dianne Hackborn3accca02013-09-20 09:32:11 -0700550 LongSparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700551 if (vpkg == null) {
552 throw new IllegalStateException("Didn't find package " + pkgName
553 + " / " + mUid);
554 }
555 PackageState pkg = vpkg.get(mVersion);
556 if (pkg == null) {
557 throw new IllegalStateException("Didn't find package " + pkgName
558 + " / " + mUid + " vers " + mVersion);
559 }
560 ProcessState proc = pkg.mProcesses.get(mName);
561 if (proc == null) {
562 throw new IllegalStateException("Didn't create per-package process "
563 + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion);
564 }
565 return proc;
566 }
567 return this;
568 }
569
570 private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList,
571 int index) {
572 ProcessStateHolder holder = pkgList.valueAt(index);
573 ProcessState proc = holder.state;
574 if (mDead && proc.mCommonProcess != proc) {
575 // Somehow we are contining to use a process state that is dead, because
576 // it was not being told it was active during the last commit. We can recover
577 // from this by generating a fresh new state, but this is bad because we
578 // are losing whatever data we had in the old process state.
579 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
580 + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
581 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion,
582 proc.mName);
583 }
584 if (proc.mMultiPackage) {
585 // The array map is still pointing to a common process state
586 // that is now shared across packages. Update it to point to
587 // the new per-package state.
Dianne Hackborn3accca02013-09-20 09:32:11 -0700588 LongSparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index),
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700589 proc.mUid);
590 if (vpkg == null) {
591 throw new IllegalStateException("No existing package "
592 + pkgList.keyAt(index) + "/" + proc.mUid
593 + " for multi-proc " + proc.mName);
594 }
595 PackageState pkg = vpkg.get(proc.mVersion);
596 if (pkg == null) {
597 throw new IllegalStateException("No existing package "
598 + pkgList.keyAt(index) + "/" + proc.mUid
599 + " for multi-proc " + proc.mName + " version " + proc.mVersion);
600 }
601 String savedName = proc.mName;
602 proc = pkg.mProcesses.get(proc.mName);
603 if (proc == null) {
604 throw new IllegalStateException("Didn't create per-package process "
605 + savedName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
606 }
607 holder.state = proc;
608 }
609 return proc;
610 }
611
612 public long getDuration(int state, long now) {
613 long time = mDurations.getValueForId((byte)state);
614 if (mCurState == state) {
615 time += now - mStartTime;
616 }
617 return time;
618 }
619
620 public long getPssSampleCount(int state) {
621 return mPssTable.getValueForId((byte)state, PSS_SAMPLE_COUNT);
622 }
623
624 public long getPssMinimum(int state) {
625 return mPssTable.getValueForId((byte)state, PSS_MINIMUM);
626 }
627
628 public long getPssAverage(int state) {
629 return mPssTable.getValueForId((byte)state, PSS_AVERAGE);
630 }
631
632 public long getPssMaximum(int state) {
633 return mPssTable.getValueForId((byte)state, PSS_MAXIMUM);
634 }
635
636 public long getPssUssMinimum(int state) {
637 return mPssTable.getValueForId((byte)state, PSS_USS_MINIMUM);
638 }
639
640 public long getPssUssAverage(int state) {
641 return mPssTable.getValueForId((byte)state, PSS_USS_AVERAGE);
642 }
643
644 public long getPssUssMaximum(int state) {
645 return mPssTable.getValueForId((byte)state, PSS_USS_MAXIMUM);
646 }
647
648 /**
649 * Sums up the PSS data and adds it to 'data'.
650 *
651 * @param data The aggregate data is added here.
652 * @param now SystemClock.uptimeMillis()
653 */
654 public void aggregatePss(TotalMemoryUseCollection data, long now) {
655 final PssAggr fgPss = new PssAggr();
656 final PssAggr bgPss = new PssAggr();
657 final PssAggr cachedPss = new PssAggr();
658 boolean havePss = false;
659 for (int i=0; i<mDurations.getKeyCount(); i++) {
660 final int key = mDurations.getKeyAt(i);
661 int type = SparseMappingTable.getIdFromKey(key);
662 int procState = type % STATE_COUNT;
663 long samples = getPssSampleCount(type);
664 if (samples > 0) {
665 long avg = getPssAverage(type);
666 havePss = true;
667 if (procState <= STATE_IMPORTANT_FOREGROUND) {
668 fgPss.add(avg, samples);
669 } else if (procState <= STATE_RECEIVER) {
670 bgPss.add(avg, samples);
671 } else {
672 cachedPss.add(avg, samples);
673 }
674 }
675 }
676 if (!havePss) {
677 return;
678 }
679 boolean fgHasBg = false;
680 boolean fgHasCached = false;
681 boolean bgHasCached = false;
682 if (fgPss.samples < 3 && bgPss.samples > 0) {
683 fgHasBg = true;
684 fgPss.add(bgPss.pss, bgPss.samples);
685 }
686 if (fgPss.samples < 3 && cachedPss.samples > 0) {
687 fgHasCached = true;
688 fgPss.add(cachedPss.pss, cachedPss.samples);
689 }
690 if (bgPss.samples < 3 && cachedPss.samples > 0) {
691 bgHasCached = true;
692 bgPss.add(cachedPss.pss, cachedPss.samples);
693 }
694 if (bgPss.samples < 3 && !fgHasBg && fgPss.samples > 0) {
695 bgPss.add(fgPss.pss, fgPss.samples);
696 }
697 if (cachedPss.samples < 3 && !bgHasCached && bgPss.samples > 0) {
698 cachedPss.add(bgPss.pss, bgPss.samples);
699 }
700 if (cachedPss.samples < 3 && !fgHasCached && fgPss.samples > 0) {
701 cachedPss.add(fgPss.pss, fgPss.samples);
702 }
703 for (int i=0; i<mDurations.getKeyCount(); i++) {
704 final int key = mDurations.getKeyAt(i);
705 final int type = SparseMappingTable.getIdFromKey(key);
706 long time = mDurations.getValue(key);
707 if (mCurState == type) {
708 time += now - mStartTime;
709 }
710 final int procState = type % STATE_COUNT;
711 data.processStateTime[procState] += time;
712 long samples = getPssSampleCount(type);
713 long avg;
714 if (samples > 0) {
715 avg = getPssAverage(type);
716 } else if (procState <= STATE_IMPORTANT_FOREGROUND) {
717 samples = fgPss.samples;
718 avg = fgPss.pss;
719 } else if (procState <= STATE_RECEIVER) {
720 samples = bgPss.samples;
721 avg = bgPss.pss;
722 } else {
723 samples = cachedPss.samples;
724 avg = cachedPss.pss;
725 }
726 double newAvg = ( (data.processStatePss[procState]
727 * (double)data.processStateSamples[procState])
728 + (avg*(double)samples)
729 ) / (data.processStateSamples[procState]+samples);
730 data.processStatePss[procState] = (long)newAvg;
731 data.processStateSamples[procState] += samples;
732 data.processStateWeight[procState] += avg * (double)time;
733 }
734 }
735
736 public long computeProcessTimeLocked(int[] screenStates, int[] memStates,
737 int[] procStates, long now) {
738 long totalTime = 0;
739 for (int is=0; is<screenStates.length; is++) {
740 for (int im=0; im<memStates.length; im++) {
741 for (int ip=0; ip<procStates.length; ip++) {
742 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
743 + procStates[ip];
744 totalTime += getDuration(bucket, now);
745 }
746 }
747 }
748 mTmpTotalTime = totalTime;
749 return totalTime;
750 }
751
752 public void dumpSummary(PrintWriter pw, String prefix,
753 int[] screenStates, int[] memStates, int[] procStates,
754 long now, long totalTime) {
755 pw.print(prefix);
756 pw.print("* ");
757 pw.print(mName);
758 pw.print(" / ");
759 UserHandle.formatUid(pw, mUid);
760 pw.print(" / v");
761 pw.print(mVersion);
762 pw.println(":");
763 dumpProcessSummaryDetails(pw, prefix, " TOTAL: ", screenStates, memStates,
764 procStates, now, totalTime, true);
765 dumpProcessSummaryDetails(pw, prefix, " Persistent: ", screenStates, memStates,
766 new int[] { STATE_PERSISTENT }, now, totalTime, true);
767 dumpProcessSummaryDetails(pw, prefix, " Top: ", screenStates, memStates,
768 new int[] {STATE_TOP}, now, totalTime, true);
769 dumpProcessSummaryDetails(pw, prefix, " Imp Fg: ", screenStates, memStates,
770 new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true);
771 dumpProcessSummaryDetails(pw, prefix, " Imp Bg: ", screenStates, memStates,
772 new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true);
773 dumpProcessSummaryDetails(pw, prefix, " Backup: ", screenStates, memStates,
774 new int[] {STATE_BACKUP}, now, totalTime, true);
775 dumpProcessSummaryDetails(pw, prefix, " Heavy Wgt: ", screenStates, memStates,
776 new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
777 dumpProcessSummaryDetails(pw, prefix, " Service: ", screenStates, memStates,
778 new int[] {STATE_SERVICE}, now, totalTime, true);
779 dumpProcessSummaryDetails(pw, prefix, " Service Rs: ", screenStates, memStates,
780 new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
781 dumpProcessSummaryDetails(pw, prefix, " Receiver: ", screenStates, memStates,
782 new int[] {STATE_RECEIVER}, now, totalTime, true);
783 dumpProcessSummaryDetails(pw, prefix, " (Home): ", screenStates, memStates,
784 new int[] {STATE_HOME}, now, totalTime, true);
785 dumpProcessSummaryDetails(pw, prefix, " (Last Act): ", screenStates, memStates,
786 new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
787 dumpProcessSummaryDetails(pw, prefix, " (Cached): ", screenStates, memStates,
788 new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT,
789 STATE_CACHED_EMPTY}, now, totalTime, true);
790 }
791
792 public void dumpProcessState(PrintWriter pw, String prefix,
793 int[] screenStates, int[] memStates, int[] procStates, long now) {
794 long totalTime = 0;
795 int printedScreen = -1;
796 for (int is=0; is<screenStates.length; is++) {
797 int printedMem = -1;
798 for (int im=0; im<memStates.length; im++) {
799 for (int ip=0; ip<procStates.length; ip++) {
800 final int iscreen = screenStates[is];
801 final int imem = memStates[im];
802 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
803 long time = mDurations.getValueForId((byte)bucket);
804 String running = "";
805 if (mCurState == bucket) {
806 running = " (running)";
807 }
808 if (time != 0) {
809 pw.print(prefix);
810 if (screenStates.length > 1) {
811 DumpUtils.printScreenLabel(pw, printedScreen != iscreen
812 ? iscreen : STATE_NOTHING);
813 printedScreen = iscreen;
814 }
815 if (memStates.length > 1) {
816 DumpUtils.printMemLabel(pw,
817 printedMem != imem ? imem : STATE_NOTHING, '/');
818 printedMem = imem;
819 }
820 pw.print(DumpUtils.STATE_NAMES[procStates[ip]]); pw.print(": ");
821 TimeUtils.formatDuration(time, pw); pw.println(running);
822 totalTime += time;
823 }
824 }
825 }
826 }
827 if (totalTime != 0) {
828 pw.print(prefix);
829 if (screenStates.length > 1) {
830 DumpUtils.printScreenLabel(pw, STATE_NOTHING);
831 }
832 if (memStates.length > 1) {
833 DumpUtils.printMemLabel(pw, STATE_NOTHING, '/');
834 }
835 pw.print("TOTAL : ");
836 TimeUtils.formatDuration(totalTime, pw);
837 pw.println();
838 }
839 }
840
841 public void dumpPss(PrintWriter pw, String prefix,
842 int[] screenStates, int[] memStates, int[] procStates) {
843 boolean printedHeader = false;
844 int printedScreen = -1;
845 for (int is=0; is<screenStates.length; is++) {
846 int printedMem = -1;
847 for (int im=0; im<memStates.length; im++) {
848 for (int ip=0; ip<procStates.length; ip++) {
849 final int iscreen = screenStates[is];
850 final int imem = memStates[im];
851 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
852 long count = getPssSampleCount(bucket);
853 if (count > 0) {
854 if (!printedHeader) {
855 pw.print(prefix);
856 pw.print("PSS/USS (");
857 pw.print(mPssTable.getKeyCount());
858 pw.println(" entries):");
859 printedHeader = true;
860 }
861 pw.print(prefix);
862 pw.print(" ");
863 if (screenStates.length > 1) {
864 DumpUtils.printScreenLabel(pw,
865 printedScreen != iscreen ? iscreen : STATE_NOTHING);
866 printedScreen = iscreen;
867 }
868 if (memStates.length > 1) {
869 DumpUtils.printMemLabel(pw,
870 printedMem != imem ? imem : STATE_NOTHING, '/');
871 printedMem = imem;
872 }
873 pw.print(DumpUtils.STATE_NAMES[procStates[ip]]); pw.print(": ");
874 pw.print(count);
875 pw.print(" samples ");
876 DebugUtils.printSizeValue(pw, getPssMinimum(bucket) * 1024);
877 pw.print(" ");
878 DebugUtils.printSizeValue(pw, getPssAverage(bucket) * 1024);
879 pw.print(" ");
880 DebugUtils.printSizeValue(pw, getPssMaximum(bucket) * 1024);
881 pw.print(" / ");
882 DebugUtils.printSizeValue(pw, getPssUssMinimum(bucket) * 1024);
883 pw.print(" ");
884 DebugUtils.printSizeValue(pw, getPssUssAverage(bucket) * 1024);
885 pw.print(" ");
886 DebugUtils.printSizeValue(pw, getPssUssMaximum(bucket) * 1024);
887 pw.println();
888 }
889 }
890 }
891 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700892 if (mNumExcessiveCpu != 0) {
893 pw.print(prefix); pw.print("Killed for excessive CPU use: ");
894 pw.print(mNumExcessiveCpu); pw.println(" times");
895 }
896 if (mNumCachedKill != 0) {
897 pw.print(prefix); pw.print("Killed from cached state: ");
898 pw.print(mNumCachedKill); pw.print(" times from pss ");
899 DebugUtils.printSizeValue(pw, mMinCachedKillPss * 1024); pw.print("-");
900 DebugUtils.printSizeValue(pw, mAvgCachedKillPss * 1024); pw.print("-");
901 DebugUtils.printSizeValue(pw, mMaxCachedKillPss * 1024); pw.println();
902 }
903 }
904
905 private void dumpProcessSummaryDetails(PrintWriter pw, String prefix,
906 String label, int[] screenStates, int[] memStates, int[] procStates,
907 long now, long totalTime, boolean full) {
908 ProcessStats.ProcessDataCollection totals = new ProcessStats.ProcessDataCollection(
909 screenStates, memStates, procStates);
910 computeProcessData(totals, now);
911 final double percentage = (double) totals.totalTime / (double) totalTime * 100;
912 // We don't print percentages < .01, so just drop those.
913 if (percentage >= 0.005 || totals.numPss != 0) {
914 if (prefix != null) {
915 pw.print(prefix);
916 }
917 if (label != null) {
918 pw.print(label);
919 }
920 totals.print(pw, totalTime, full);
921 if (prefix != null) {
922 pw.println();
923 }
924 }
925 }
926
927 public void dumpInternalLocked(PrintWriter pw, String prefix, boolean dumpAll) {
928 if (dumpAll) {
929 pw.print(prefix); pw.print("myID=");
930 pw.print(Integer.toHexString(System.identityHashCode(this)));
931 pw.print(" mCommonProcess=");
932 pw.print(Integer.toHexString(System.identityHashCode(mCommonProcess)));
933 pw.print(" mPackage="); pw.println(mPackage);
934 if (mMultiPackage) {
935 pw.print(prefix); pw.print("mMultiPackage="); pw.println(mMultiPackage);
936 }
937 if (this != mCommonProcess) {
938 pw.print(prefix); pw.print("Common Proc: "); pw.print(mCommonProcess.mName);
939 pw.print("/"); pw.print(mCommonProcess.mUid);
940 pw.print(" pkg="); pw.println(mCommonProcess.mPackage);
941 }
942 }
943 if (mActive) {
944 pw.print(prefix); pw.print("mActive="); pw.println(mActive);
945 }
946 if (mDead) {
947 pw.print(prefix); pw.print("mDead="); pw.println(mDead);
948 }
949 if (mNumActiveServices != 0 || mNumStartedServices != 0) {
950 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(mNumActiveServices);
951 pw.print(" mNumStartedServices=");
952 pw.println(mNumStartedServices);
953 }
954 }
955
956 public void computeProcessData(ProcessStats.ProcessDataCollection data, long now) {
957 data.totalTime = 0;
958 data.numPss = data.minPss = data.avgPss = data.maxPss =
959 data.minUss = data.avgUss = data.maxUss = 0;
960 for (int is=0; is<data.screenStates.length; is++) {
961 for (int im=0; im<data.memStates.length; im++) {
962 for (int ip=0; ip<data.procStates.length; ip++) {
963 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
964 + data.procStates[ip];
965 data.totalTime += getDuration(bucket, now);
966 long samples = getPssSampleCount(bucket);
967 if (samples > 0) {
968 long minPss = getPssMinimum(bucket);
969 long avgPss = getPssAverage(bucket);
970 long maxPss = getPssMaximum(bucket);
971 long minUss = getPssUssMinimum(bucket);
972 long avgUss = getPssUssAverage(bucket);
973 long maxUss = getPssUssMaximum(bucket);
974 if (data.numPss == 0) {
975 data.minPss = minPss;
976 data.avgPss = avgPss;
977 data.maxPss = maxPss;
978 data.minUss = minUss;
979 data.avgUss = avgUss;
980 data.maxUss = maxUss;
981 } else {
982 if (minPss < data.minPss) {
983 data.minPss = minPss;
984 }
985 data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
986 + (avgPss*(double)samples)) / (data.numPss+samples) );
987 if (maxPss > data.maxPss) {
988 data.maxPss = maxPss;
989 }
990 if (minUss < data.minUss) {
991 data.minUss = minUss;
992 }
993 data.avgUss = (long)( ((data.avgUss*(double)data.numPss)
994 + (avgUss*(double)samples)) / (data.numPss+samples) );
995 if (maxUss > data.maxUss) {
996 data.maxUss = maxUss;
997 }
998 }
999 data.numPss += samples;
1000 }
1001 }
1002 }
1003 }
1004 }
1005
1006 public void dumpCsv(PrintWriter pw,
1007 boolean sepScreenStates, int[] screenStates, boolean sepMemStates,
1008 int[] memStates, boolean sepProcStates, int[] procStates, long now) {
1009 final int NSS = sepScreenStates ? screenStates.length : 1;
1010 final int NMS = sepMemStates ? memStates.length : 1;
1011 final int NPS = sepProcStates ? procStates.length : 1;
1012 for (int iss=0; iss<NSS; iss++) {
1013 for (int ims=0; ims<NMS; ims++) {
1014 for (int ips=0; ips<NPS; ips++) {
1015 final int vsscreen = sepScreenStates ? screenStates[iss] : 0;
1016 final int vsmem = sepMemStates ? memStates[ims] : 0;
1017 final int vsproc = sepProcStates ? procStates[ips] : 0;
1018 final int NSA = sepScreenStates ? 1 : screenStates.length;
1019 final int NMA = sepMemStates ? 1 : memStates.length;
1020 final int NPA = sepProcStates ? 1 : procStates.length;
1021 long totalTime = 0;
1022 for (int isa=0; isa<NSA; isa++) {
1023 for (int ima=0; ima<NMA; ima++) {
1024 for (int ipa=0; ipa<NPA; ipa++) {
1025 final int vascreen = sepScreenStates ? 0 : screenStates[isa];
1026 final int vamem = sepMemStates ? 0 : memStates[ima];
1027 final int vaproc = sepProcStates ? 0 : procStates[ipa];
1028 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
1029 * STATE_COUNT) + vsproc + vaproc;
1030 totalTime += getDuration(bucket, now);
1031 }
1032 }
1033 }
1034 pw.print(DumpUtils.CSV_SEP);
1035 pw.print(totalTime);
1036 }
1037 }
1038 }
1039 }
1040
Dianne Hackborn3accca02013-09-20 09:32:11 -07001041 public void dumpPackageProcCheckin(PrintWriter pw, String pkgName, int uid, long vers,
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001042 String itemName, long now) {
1043 pw.print("pkgproc,");
1044 pw.print(pkgName);
1045 pw.print(",");
1046 pw.print(uid);
1047 pw.print(",");
1048 pw.print(vers);
1049 pw.print(",");
1050 pw.print(DumpUtils.collapseString(pkgName, itemName));
1051 dumpAllStateCheckin(pw, now);
1052 pw.println();
1053 if (mPssTable.getKeyCount() > 0) {
1054 pw.print("pkgpss,");
1055 pw.print(pkgName);
1056 pw.print(",");
1057 pw.print(uid);
1058 pw.print(",");
1059 pw.print(vers);
1060 pw.print(",");
1061 pw.print(DumpUtils.collapseString(pkgName, itemName));
1062 dumpAllPssCheckin(pw);
1063 pw.println();
1064 }
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001065 if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001066 pw.print("pkgkills,");
1067 pw.print(pkgName);
1068 pw.print(",");
1069 pw.print(uid);
1070 pw.print(",");
1071 pw.print(vers);
1072 pw.print(",");
1073 pw.print(DumpUtils.collapseString(pkgName, itemName));
1074 pw.print(",");
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001075 pw.print("0"); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001076 pw.print(",");
1077 pw.print(mNumExcessiveCpu);
1078 pw.print(",");
1079 pw.print(mNumCachedKill);
1080 pw.print(",");
1081 pw.print(mMinCachedKillPss);
1082 pw.print(":");
1083 pw.print(mAvgCachedKillPss);
1084 pw.print(":");
1085 pw.print(mMaxCachedKillPss);
1086 pw.println();
1087 }
1088 }
1089
1090 public void dumpProcCheckin(PrintWriter pw, String procName, int uid, long now) {
1091 if (mDurations.getKeyCount() > 0) {
1092 pw.print("proc,");
1093 pw.print(procName);
1094 pw.print(",");
1095 pw.print(uid);
1096 dumpAllStateCheckin(pw, now);
1097 pw.println();
1098 }
1099 if (mPssTable.getKeyCount() > 0) {
1100 pw.print("pss,");
1101 pw.print(procName);
1102 pw.print(",");
1103 pw.print(uid);
1104 dumpAllPssCheckin(pw);
1105 pw.println();
1106 }
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001107 if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001108 pw.print("kills,");
1109 pw.print(procName);
1110 pw.print(",");
1111 pw.print(uid);
1112 pw.print(",");
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001113 pw.print("0"); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001114 pw.print(",");
1115 pw.print(mNumExcessiveCpu);
1116 pw.print(",");
1117 pw.print(mNumCachedKill);
1118 pw.print(",");
1119 pw.print(mMinCachedKillPss);
1120 pw.print(":");
1121 pw.print(mAvgCachedKillPss);
1122 pw.print(":");
1123 pw.print(mMaxCachedKillPss);
1124 pw.println();
1125 }
1126 }
1127
1128 public void dumpAllStateCheckin(PrintWriter pw, long now) {
1129 boolean didCurState = false;
1130 for (int i=0; i<mDurations.getKeyCount(); i++) {
1131 final int key = mDurations.getKeyAt(i);
1132 final int type = SparseMappingTable.getIdFromKey(key);
1133 long time = mDurations.getValue(key);
1134 if (mCurState == type) {
1135 didCurState = true;
1136 time += now - mStartTime;
1137 }
1138 DumpUtils.printProcStateTagAndValue(pw, type, time);
1139 }
1140 if (!didCurState && mCurState != STATE_NOTHING) {
1141 DumpUtils.printProcStateTagAndValue(pw, mCurState, now - mStartTime);
1142 }
1143 }
1144
1145 public void dumpAllPssCheckin(PrintWriter pw) {
1146 final int N = mPssTable.getKeyCount();
1147 for (int i=0; i<N; i++) {
1148 final int key = mPssTable.getKeyAt(i);
1149 final int type = SparseMappingTable.getIdFromKey(key);
1150 pw.print(',');
1151 DumpUtils.printProcStateTag(pw, type);
1152 pw.print(':');
1153 pw.print(mPssTable.getValue(key, PSS_SAMPLE_COUNT));
1154 pw.print(':');
1155 pw.print(mPssTable.getValue(key, PSS_MINIMUM));
1156 pw.print(':');
1157 pw.print(mPssTable.getValue(key, PSS_AVERAGE));
1158 pw.print(':');
1159 pw.print(mPssTable.getValue(key, PSS_MAXIMUM));
1160 pw.print(':');
1161 pw.print(mPssTable.getValue(key, PSS_USS_MINIMUM));
1162 pw.print(':');
1163 pw.print(mPssTable.getValue(key, PSS_USS_AVERAGE));
1164 pw.print(':');
1165 pw.print(mPssTable.getValue(key, PSS_USS_MAXIMUM));
1166 }
1167 }
1168
Yi Jin9680cfa2017-09-15 15:14:43 -07001169 @Override
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001170 public String toString() {
1171 StringBuilder sb = new StringBuilder(128);
1172 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
1173 .append(" ").append(mName).append("/").append(mUid)
1174 .append(" pkg=").append(mPackage);
1175 if (mMultiPackage) sb.append(" (multi)");
1176 if (mCommonProcess != this) sb.append(" (sub)");
1177 sb.append("}");
1178 return sb.toString();
1179 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001180
1181 public void toProto(ProtoOutputStream proto, String procName, int uid, long now) {
1182 proto.write(ProcessStatsProto.PROCESS, procName);
1183 proto.write(ProcessStatsProto.UID, uid);
1184 if (mNumExcessiveCpu > 0 || mNumCachedKill > 0 ) {
1185 final long killToken = proto.start(ProcessStatsProto.KILL);
Yi Jin9680cfa2017-09-15 15:14:43 -07001186 proto.write(ProcessStatsProto.Kill.CPU, mNumExcessiveCpu);
1187 proto.write(ProcessStatsProto.Kill.CACHED, mNumCachedKill);
1188 ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.Kill.CACHED_PSS,
1189 mMinCachedKillPss, mAvgCachedKillPss, mMaxCachedKillPss);
1190 proto.end(killToken);
1191 }
1192
1193 // Group proc stats by type (screen state + mem state + process state)
1194 Map<Integer, Long> durationByState = new HashMap<>();
1195 boolean didCurState = false;
1196 for (int i=0; i<mDurations.getKeyCount(); i++) {
1197 final int key = mDurations.getKeyAt(i);
1198 final int type = SparseMappingTable.getIdFromKey(key);
1199 long time = mDurations.getValue(key);
1200 if (mCurState == type) {
1201 didCurState = true;
1202 time += now - mStartTime;
1203 }
1204 durationByState.put(type, time);
1205 }
1206 if (!didCurState && mCurState != STATE_NOTHING) {
1207 durationByState.put(mCurState, now - mStartTime);
1208 }
1209
1210 for (int i=0; i<mPssTable.getKeyCount(); i++) {
1211 final int key = mPssTable.getKeyAt(i);
1212 final int type = SparseMappingTable.getIdFromKey(key);
1213 if (!durationByState.containsKey(type)) {
1214 // state without duration should not have stats!
1215 continue;
1216 }
1217 final long stateToken = proto.start(ProcessStatsProto.STATES);
1218 DumpUtils.printProcStateTagProto(proto,
1219 ProcessStatsProto.State.SCREEN_STATE,
1220 ProcessStatsProto.State.MEMORY_STATE,
1221 ProcessStatsProto.State.PROCESS_STATE,
1222 type);
1223
1224 long duration = durationByState.get(type);
1225 durationByState.remove(type); // remove the key since it is already being dumped.
1226 proto.write(ProcessStatsProto.State.DURATION_MS, duration);
1227
1228 proto.write(ProcessStatsProto.State.SAMPLE_SIZE, mPssTable.getValue(key, PSS_SAMPLE_COUNT));
1229 ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.PSS,
1230 mPssTable.getValue(key, PSS_MINIMUM),
1231 mPssTable.getValue(key, PSS_AVERAGE),
1232 mPssTable.getValue(key, PSS_MAXIMUM));
1233 ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.USS,
1234 mPssTable.getValue(key, PSS_USS_MINIMUM),
1235 mPssTable.getValue(key, PSS_USS_AVERAGE),
1236 mPssTable.getValue(key, PSS_USS_MAXIMUM));
1237
1238 proto.end(stateToken);
1239 }
1240
1241 for (Map.Entry<Integer, Long> entry : durationByState.entrySet()) {
1242 final long stateToken = proto.start(ProcessStatsProto.STATES);
1243 DumpUtils.printProcStateTagProto(proto,
1244 ProcessStatsProto.State.SCREEN_STATE,
1245 ProcessStatsProto.State.MEMORY_STATE,
1246 ProcessStatsProto.State.PROCESS_STATE,
1247 entry.getKey());
1248 proto.write(ProcessStatsProto.State.DURATION_MS, entry.getValue());
1249 proto.end(stateToken);
1250 }
1251 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001252}