blob: 79ff5948f32b567b0e8cb3f2ae994bc22c64d441 [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
Joe Onorato4eb64fd2016-03-21 15:30:09 -070019import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE;
Yangster-macbac82322018-08-23 14:45:10 -070020import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070021import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM;
Yangster-macbac82322018-08-23 14:45:10 -070022import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM;
Dianne Hackborne17b4452018-01-10 13:15:40 -080023import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_AVERAGE;
24import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MAXIMUM;
Yangster-macbac82322018-08-23 14:45:10 -070025import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM;
26import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070027import static com.android.internal.app.procstats.ProcessStats.PSS_USS_AVERAGE;
28import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
Yangster-macbac82322018-08-23 14:45:10 -070029import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070030import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070031import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY;
32import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY_CLIENT;
33import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY;
34import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
Yangster-macbac82322018-08-23 14:45:10 -070035import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
36import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
37import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
38import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_FOREGROUND;
39import static com.android.internal.app.procstats.ProcessStats.STATE_LAST_ACTIVITY;
40import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
41import static com.android.internal.app.procstats.ProcessStats.STATE_PERSISTENT;
42import static com.android.internal.app.procstats.ProcessStats.STATE_RECEIVER;
43import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE;
44import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE_RESTARTING;
45import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
46
Richard Gaywood57dc86a2020-03-12 17:57:10 +000047import android.os.Parcel;
48import android.os.SystemClock;
49import android.os.UserHandle;
50import android.service.procstats.ProcessStatsProto;
51import android.service.procstats.ProcessStatsStateProto;
52import android.util.ArrayMap;
53import android.util.DebugUtils;
54import android.util.Log;
55import android.util.LongSparseArray;
56import android.util.Slog;
57import android.util.SparseLongArray;
58import android.util.TimeUtils;
59import android.util.proto.ProtoOutputStream;
60import android.util.proto.ProtoUtils;
61
Yangster-macbac82322018-08-23 14:45:10 -070062import com.android.internal.app.procstats.ProcessStats.PackageState;
63import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
64import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070065
Joe Onorato4eb64fd2016-03-21 15:30:09 -070066import java.io.PrintWriter;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070067import java.util.Comparator;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070068
69public final class ProcessState {
70 private static final String TAG = "ProcessStats";
71 private static final boolean DEBUG = false;
72 private static final boolean DEBUG_PARCEL = false;
73
74 // Map from process states to the states we track.
Dianne Hackborn95031ef2018-07-09 09:09:05 -070075 static final int[] PROCESS_STATE_TO_STATE = new int[] {
Joe Onorato4eb64fd2016-03-21 15:30:09 -070076 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
77 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
78 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
Amith Yamasanif235d0b2019-03-20 22:49:43 -070079 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP
Amith Yamasanic45a9902019-04-05 16:29:30 -070080 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
Dianne Hackborn10fc4fd2017-12-19 17:23:13 -080081 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
Joe Onorato4eb64fd2016-03-21 15:30:09 -070082 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
83 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
Dianne Hackborn83b40f62017-04-26 13:59:47 -070084 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
Joe Onorato4eb64fd2016-03-21 15:30:09 -070085 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP
Joe Onorato4eb64fd2016-03-21 15:30:09 -070086 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE
87 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER
Dianne Hackbornbad8d912017-12-18 16:45:52 -080088 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
Dianne Hackbornf097d422017-12-15 16:32:19 -080089 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
Joe Onorato4eb64fd2016-03-21 15:30:09 -070090 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME
91 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
92 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
93 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
Dianne Hackborn68a06332017-11-15 17:54:18 -080094 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_RECENT
Joe Onorato4eb64fd2016-03-21 15:30:09 -070095 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
96 };
97
98 public static final Comparator<ProcessState> COMPARATOR = new Comparator<ProcessState>() {
99 @Override
100 public int compare(ProcessState lhs, ProcessState rhs) {
101 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
102 return -1;
103 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
104 return 1;
105 }
106 return 0;
107 }
108 };
109
110 static class PssAggr {
111 long pss = 0;
112 long samples = 0;
113
114 void add(long newPss, long newSamples) {
115 pss = (long)( (pss*(double)samples) + (newPss*(double)newSamples) )
116 / (samples+newSamples);
117 samples += newSamples;
118 }
119 }
120
121 // Used by reset to count rather than storing extra maps. Be careful.
122 public int tmpNumInUse;
123 public ProcessState tmpFoundSubProc;
124
125 private final ProcessStats mStats;
126 private final String mName;
127 private final String mPackage;
128 private final int mUid;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700129 private final long mVersion;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700130 private final DurationsTable mDurations;
131 private final PssTable mPssTable;
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700132 private final long[] mTotalRunningPss = new long[ProcessStats.PSS_COUNT];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700133
134 private ProcessState mCommonProcess;
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700135 private int mCurCombinedState = STATE_NOTHING;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700136 private long mStartTime;
137
138 private int mLastPssState = STATE_NOTHING;
139 private long mLastPssTime;
140
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700141 private long mTotalRunningStartTime;
142 private long mTotalRunningDuration;
143
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700144 private boolean mActive;
145 private int mNumActiveServices;
146 private int mNumStartedServices;
147
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700148 private int mNumExcessiveCpu;
149
150 private int mNumCachedKill;
151 private long mMinCachedKillPss;
152 private long mAvgCachedKillPss;
153 private long mMaxCachedKillPss;
154
155 private boolean mMultiPackage;
156 private boolean mDead;
157
158 // Set in computeProcessTimeLocked and used by COMPARATOR to sort. Be careful.
159 private long mTmpTotalTime;
160
161 /**
162 * Create a new top-level process state, for the initial case where there is only
163 * a single package running in a process. The initial state is not running.
164 */
Dianne Hackborn3accca02013-09-20 09:32:11 -0700165 public ProcessState(ProcessStats processStats, String pkg, int uid, long vers, String name) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700166 mStats = processStats;
167 mName = name;
168 mCommonProcess = this;
169 mPackage = pkg;
170 mUid = uid;
171 mVersion = vers;
172 mDurations = new DurationsTable(processStats.mTableData);
173 mPssTable = new PssTable(processStats.mTableData);
174 }
175
176 /**
177 * Create a new per-package process state for an existing top-level process
178 * state. The current running state of the top-level process is also copied,
179 * marked as started running at 'now'.
180 */
Dianne Hackborn3accca02013-09-20 09:32:11 -0700181 public ProcessState(ProcessState commonProcess, String pkg, int uid, long vers, String name,
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700182 long now) {
183 mStats = commonProcess.mStats;
184 mName = name;
185 mCommonProcess = commonProcess;
186 mPackage = pkg;
187 mUid = uid;
188 mVersion = vers;
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700189 mCurCombinedState = commonProcess.mCurCombinedState;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700190 mStartTime = now;
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700191 if (mCurCombinedState != STATE_NOTHING) {
192 mTotalRunningStartTime = now;
193 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700194 mDurations = new DurationsTable(commonProcess.mStats.mTableData);
195 mPssTable = new PssTable(commonProcess.mStats.mTableData);
196 }
197
198 public ProcessState clone(long now) {
199 ProcessState pnew = new ProcessState(this, mPackage, mUid, mVersion, mName, now);
200 pnew.mDurations.addDurations(mDurations);
201 pnew.mPssTable.copyFrom(mPssTable, PSS_COUNT);
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700202 System.arraycopy(mTotalRunningPss, 0, pnew.mTotalRunningPss, 0, ProcessStats.PSS_COUNT);
203 pnew.mTotalRunningDuration = getTotalRunningDuration(now);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700204 pnew.mNumExcessiveCpu = mNumExcessiveCpu;
205 pnew.mNumCachedKill = mNumCachedKill;
206 pnew.mMinCachedKillPss = mMinCachedKillPss;
207 pnew.mAvgCachedKillPss = mAvgCachedKillPss;
208 pnew.mMaxCachedKillPss = mMaxCachedKillPss;
209 pnew.mActive = mActive;
210 pnew.mNumActiveServices = mNumActiveServices;
211 pnew.mNumStartedServices = mNumStartedServices;
212 return pnew;
213 }
214
215 public String getName() {
216 return mName;
217 }
218
219 public ProcessState getCommonProcess() {
220 return mCommonProcess;
221 }
222
223 /**
224 * Say that we are not part of a shared process, so mCommonProcess = this.
225 */
226 public void makeStandalone() {
227 mCommonProcess = this;
228 }
229
230 public String getPackage() {
231 return mPackage;
232 }
233
234 public int getUid() {
235 return mUid;
236 }
237
Dianne Hackborn3accca02013-09-20 09:32:11 -0700238 public long getVersion() {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700239 return mVersion;
240 }
241
242 public boolean isMultiPackage() {
243 return mMultiPackage;
244 }
245
246 public void setMultiPackage(boolean val) {
247 mMultiPackage = val;
248 }
Kweku Adamsef0c08f2018-08-01 11:55:07 -0700249
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700250 public int getDurationsBucketCount() {
251 return mDurations.getKeyCount();
252 }
253
254 public void add(ProcessState other) {
255 mDurations.addDurations(other.mDurations);
256 mPssTable.mergeStats(other.mPssTable);
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700257 // Note that we don't touch mTotalRunningPss, because in current use
258 // 'other' is older stats that are being added in to these newer ones.
259 // So the newer ones keep track of the total running time, which is always
260 // the right thing over whatever was in older stats.
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 Hackborn99aeba82018-07-31 13:29:33 -0700295 for (int i = 0; i < ProcessStats.PSS_COUNT; i++) {
296 out.writeLong(mTotalRunningPss[i]);
297 }
298 out.writeLong(getTotalRunningDuration(now));
Dianne Hackbornffca58b2017-05-24 16:15:45 -0700299 out.writeInt(0); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700300 out.writeInt(mNumExcessiveCpu);
301 out.writeInt(mNumCachedKill);
302 if (mNumCachedKill > 0) {
303 out.writeLong(mMinCachedKillPss);
304 out.writeLong(mAvgCachedKillPss);
305 out.writeLong(mMaxCachedKillPss);
306 }
307 }
308
309 public boolean readFromParcel(Parcel in, boolean fully) {
310 boolean multiPackage = in.readInt() != 0;
311 if (fully) {
312 mMultiPackage = multiPackage;
313 }
314 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
315 if (!mDurations.readFromParcel(in)) {
316 return false;
317 }
318 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
319 if (!mPssTable.readFromParcel(in)) {
320 return false;
321 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700322 for (int i = 0; i < ProcessStats.PSS_COUNT; i++) {
323 mTotalRunningPss[i] = in.readLong();
324 }
325 mTotalRunningDuration = in.readLong();
Dianne Hackbornffca58b2017-05-24 16:15:45 -0700326 in.readInt(); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700327 mNumExcessiveCpu = in.readInt();
328 mNumCachedKill = in.readInt();
329 if (mNumCachedKill > 0) {
330 mMinCachedKillPss = in.readLong();
331 mAvgCachedKillPss = in.readLong();
332 mMaxCachedKillPss = in.readLong();
333 } else {
334 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
335 }
336 return true;
337 }
338
339 public void makeActive() {
340 ensureNotDead();
341 mActive = true;
342 }
343
344 public void makeInactive() {
345 mActive = false;
346 }
347
348 public boolean isInUse() {
349 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700350 || mCurCombinedState != STATE_NOTHING;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700351 }
352
353 public boolean isActive() {
354 return mActive;
355 }
356
357 public boolean hasAnyData() {
358 return !(mDurations.getKeyCount() == 0
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700359 && mCurCombinedState == STATE_NOTHING
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700360 && mPssTable.getKeyCount() == 0
361 && mTotalRunningPss[PSS_SAMPLE_COUNT] == 0);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700362 }
363
364 /**
365 * Update the current state of the given list of processes.
366 *
367 * @param state Current ActivityManager.PROCESS_STATE_*
368 * @param memFactor Current mem factor constant.
369 * @param now Current time.
370 * @param pkgList Processes to update.
371 */
372 public void setState(int state, int memFactor, long now,
373 ArrayMap<String, ProcessStateHolder> pkgList) {
374 if (state < 0) {
375 state = mNumStartedServices > 0
376 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
377 } else {
378 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
379 }
380
381 // First update the common process.
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700382 mCommonProcess.setCombinedState(state, now);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700383
384 // If the common process is not multi-package, there is nothing else to do.
385 if (!mCommonProcess.mMultiPackage) {
386 return;
387 }
388
389 if (pkgList != null) {
390 for (int ip=pkgList.size()-1; ip>=0; ip--) {
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700391 pullFixedProc(pkgList, ip).setCombinedState(state, now);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700392 }
393 }
394 }
395
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700396 public void setCombinedState(int state, long now) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700397 ensureNotDead();
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700398 if (!mDead && (mCurCombinedState != state)) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700399 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
400 commitStateTime(now);
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700401 if (state == STATE_NOTHING) {
402 // We are transitioning to a no longer running state... stop counting run time.
403 mTotalRunningDuration += now - mTotalRunningStartTime;
404 mTotalRunningStartTime = 0;
405 } else if (mCurCombinedState == STATE_NOTHING) {
406 // We previously weren't running... now starting again, clear out total
407 // running info.
408 mTotalRunningDuration = 0;
409 mTotalRunningStartTime = now;
410 for (int i = ProcessStats.PSS_COUNT - 1; i >= 0; i--) {
411 mTotalRunningPss[i] = 0;
412 }
413 }
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700414 mCurCombinedState = state;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700415 }
416 }
417
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700418 public int getCombinedState() {
419 return mCurCombinedState;
Dianne Hackborn95031ef2018-07-09 09:09:05 -0700420 }
421
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700422 public void commitStateTime(long now) {
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700423 if (mCurCombinedState != STATE_NOTHING) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700424 long dur = now - mStartTime;
425 if (dur > 0) {
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700426 mDurations.addDuration(mCurCombinedState, dur);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700427 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700428 mTotalRunningDuration += now - mTotalRunningStartTime;
429 mTotalRunningStartTime = now;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700430 }
431 mStartTime = now;
432 }
433
434 public void incActiveServices(String serviceName) {
435 if (DEBUG && "".equals(mName)) {
436 RuntimeException here = new RuntimeException("here");
437 here.fillInStackTrace();
438 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
439 + " to " + (mNumActiveServices+1), here);
440 }
441 if (mCommonProcess != this) {
442 mCommonProcess.incActiveServices(serviceName);
443 }
444 mNumActiveServices++;
445 }
446
447 public void decActiveServices(String serviceName) {
448 if (DEBUG && "".equals(mName)) {
449 RuntimeException here = new RuntimeException("here");
450 here.fillInStackTrace();
451 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
452 + " to " + (mNumActiveServices-1), here);
453 }
454 if (mCommonProcess != this) {
455 mCommonProcess.decActiveServices(serviceName);
456 }
457 mNumActiveServices--;
458 if (mNumActiveServices < 0) {
459 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
460 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
461 mNumActiveServices = 0;
462 }
463 }
464
465 public void incStartedServices(int memFactor, long now, String serviceName) {
466 if (false) {
467 RuntimeException here = new RuntimeException("here");
468 here.fillInStackTrace();
469 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
470 + " to " + (mNumStartedServices+1), here);
471 }
472 if (mCommonProcess != this) {
473 mCommonProcess.incStartedServices(memFactor, now, serviceName);
474 }
475 mNumStartedServices++;
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700476 if (mNumStartedServices == 1 && mCurCombinedState == STATE_NOTHING) {
477 setCombinedState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700478 }
479 }
480
481 public void decStartedServices(int memFactor, long now, String serviceName) {
482 if (false) {
483 RuntimeException here = new RuntimeException("here");
484 here.fillInStackTrace();
485 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
486 + " to " + (mNumStartedServices-1), here);
487 }
488 if (mCommonProcess != this) {
489 mCommonProcess.decStartedServices(memFactor, now, serviceName);
490 }
491 mNumStartedServices--;
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700492 if (mNumStartedServices == 0 && (mCurCombinedState %STATE_COUNT) == STATE_SERVICE_RESTARTING) {
493 setCombinedState(STATE_NOTHING, now);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700494 } else if (mNumStartedServices < 0) {
495 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
496 + mPackage + " uid=" + mUid + " name=" + mName);
497 mNumStartedServices = 0;
498 }
499 }
500
Dianne Hackborne17b4452018-01-10 13:15:40 -0800501 public void addPss(long pss, long uss, long rss, boolean always, int type, long duration,
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700502 ArrayMap<String, ProcessStateHolder> pkgList) {
503 ensureNotDead();
Dianne Hackborn052e3142017-12-19 16:08:30 -0800504 switch (type) {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800505 case ProcessStats.ADD_PSS_INTERNAL_SINGLE:
506 mStats.mInternalSinglePssCount++;
507 mStats.mInternalSinglePssTime += duration;
508 break;
509 case ProcessStats.ADD_PSS_INTERNAL_ALL_MEM:
510 mStats.mInternalAllMemPssCount++;
511 mStats.mInternalAllMemPssTime += duration;
512 break;
513 case ProcessStats.ADD_PSS_INTERNAL_ALL_POLL:
514 mStats.mInternalAllPollPssCount++;
515 mStats.mInternalAllPollPssTime += duration;
Dianne Hackborn052e3142017-12-19 16:08:30 -0800516 break;
517 case ProcessStats.ADD_PSS_EXTERNAL:
518 mStats.mExternalPssCount++;
519 mStats.mExternalPssTime += duration;
520 break;
521 case ProcessStats.ADD_PSS_EXTERNAL_SLOW:
522 mStats.mExternalSlowPssCount++;
523 mStats.mExternalSlowPssTime += duration;
524 break;
525 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700526 if (!always) {
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700527 if (mLastPssState == mCurCombinedState && SystemClock.uptimeMillis()
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700528 < (mLastPssTime+(30*1000))) {
529 return;
530 }
531 }
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700532 mLastPssState = mCurCombinedState;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700533 mLastPssTime = SystemClock.uptimeMillis();
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700534 if (mCurCombinedState != STATE_NOTHING) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700535 // First update the common process.
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700536 mCommonProcess.mPssTable.mergeStats(mCurCombinedState, 1, pss, pss, pss, uss, uss, uss,
Dianne Hackborne17b4452018-01-10 13:15:40 -0800537 rss, rss, rss);
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700538 PssTable.mergeStats(mCommonProcess.mTotalRunningPss, 0, 1, pss, pss, pss, uss, uss, uss,
539 rss, rss, rss);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700540
541 // If the common process is not multi-package, there is nothing else to do.
542 if (!mCommonProcess.mMultiPackage) {
543 return;
544 }
545
546 if (pkgList != null) {
547 for (int ip=pkgList.size()-1; ip>=0; ip--) {
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700548 ProcessState fixedProc = pullFixedProc(pkgList, ip);
549 fixedProc.mPssTable.mergeStats(mCurCombinedState, 1,
550 pss, pss, pss, uss, uss, uss, rss, rss, rss);
551 PssTable.mergeStats(fixedProc.mTotalRunningPss, 0, 1,
Dianne Hackborne17b4452018-01-10 13:15:40 -0800552 pss, pss, pss, uss, uss, uss, rss, rss, rss);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700553 }
554 }
555 }
556 }
557
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700558 public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) {
559 ensureNotDead();
560 mCommonProcess.mNumExcessiveCpu++;
561 if (!mCommonProcess.mMultiPackage) {
562 return;
563 }
564
565 for (int ip=pkgList.size()-1; ip>=0; ip--) {
566 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
567 }
568 }
569
570 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
571 if (mNumCachedKill <= 0) {
572 mNumCachedKill = num;
573 mMinCachedKillPss = minPss;
574 mAvgCachedKillPss = avgPss;
575 mMaxCachedKillPss = maxPss;
576 } else {
577 if (minPss < mMinCachedKillPss) {
578 mMinCachedKillPss = minPss;
579 }
580 if (maxPss > mMaxCachedKillPss) {
581 mMaxCachedKillPss = maxPss;
582 }
583 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
584 / (mNumCachedKill+num) );
585 mNumCachedKill += num;
586 }
587 }
588
589 public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) {
590 ensureNotDead();
591 mCommonProcess.addCachedKill(1, pss, pss, pss);
592 if (!mCommonProcess.mMultiPackage) {
593 return;
594 }
595
596 for (int ip=pkgList.size()-1; ip>=0; ip--) {
597 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
598 }
599 }
600
601 public ProcessState pullFixedProc(String pkgName) {
602 if (mMultiPackage) {
603 // The array map is still pointing to a common process state
604 // that is now shared across packages. Update it to point to
605 // the new per-package state.
Dianne Hackborn3accca02013-09-20 09:32:11 -0700606 LongSparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700607 if (vpkg == null) {
608 throw new IllegalStateException("Didn't find package " + pkgName
609 + " / " + mUid);
610 }
611 PackageState pkg = vpkg.get(mVersion);
612 if (pkg == null) {
613 throw new IllegalStateException("Didn't find package " + pkgName
614 + " / " + mUid + " vers " + mVersion);
615 }
616 ProcessState proc = pkg.mProcesses.get(mName);
617 if (proc == null) {
618 throw new IllegalStateException("Didn't create per-package process "
619 + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion);
620 }
621 return proc;
622 }
623 return this;
624 }
625
626 private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList,
627 int index) {
628 ProcessStateHolder holder = pkgList.valueAt(index);
629 ProcessState proc = holder.state;
630 if (mDead && proc.mCommonProcess != proc) {
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700631 // Somehow we are continuing to use a process state that is dead, because
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700632 // it was not being told it was active during the last commit. We can recover
633 // from this by generating a fresh new state, but this is bad because we
634 // are losing whatever data we had in the old process state.
635 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
636 + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
637 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion,
638 proc.mName);
639 }
640 if (proc.mMultiPackage) {
641 // The array map is still pointing to a common process state
642 // that is now shared across packages. Update it to point to
643 // the new per-package state.
Dianne Hackborn3accca02013-09-20 09:32:11 -0700644 LongSparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index),
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700645 proc.mUid);
646 if (vpkg == null) {
647 throw new IllegalStateException("No existing package "
648 + pkgList.keyAt(index) + "/" + proc.mUid
649 + " for multi-proc " + proc.mName);
650 }
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700651 PackageState expkg = vpkg.get(proc.mVersion);
652 if (expkg == null) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700653 throw new IllegalStateException("No existing package "
654 + pkgList.keyAt(index) + "/" + proc.mUid
655 + " for multi-proc " + proc.mName + " version " + proc.mVersion);
656 }
657 String savedName = proc.mName;
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700658 proc = expkg.mProcesses.get(proc.mName);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700659 if (proc == null) {
660 throw new IllegalStateException("Didn't create per-package process "
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700661 + savedName + " in pkg " + expkg.mPackageName + "/" + expkg.mUid);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700662 }
663 holder.state = proc;
664 }
665 return proc;
666 }
667
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700668 public long getTotalRunningDuration(long now) {
669 return mTotalRunningDuration +
670 (mTotalRunningStartTime != 0 ? (now - mTotalRunningStartTime) : 0);
671 }
672
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700673 public long getDuration(int state, long now) {
674 long time = mDurations.getValueForId((byte)state);
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700675 if (mCurCombinedState == state) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700676 time += now - mStartTime;
677 }
678 return time;
679 }
680
681 public long getPssSampleCount(int state) {
682 return mPssTable.getValueForId((byte)state, PSS_SAMPLE_COUNT);
683 }
684
685 public long getPssMinimum(int state) {
686 return mPssTable.getValueForId((byte)state, PSS_MINIMUM);
687 }
688
689 public long getPssAverage(int state) {
690 return mPssTable.getValueForId((byte)state, PSS_AVERAGE);
691 }
692
693 public long getPssMaximum(int state) {
694 return mPssTable.getValueForId((byte)state, PSS_MAXIMUM);
695 }
696
697 public long getPssUssMinimum(int state) {
698 return mPssTable.getValueForId((byte)state, PSS_USS_MINIMUM);
699 }
700
701 public long getPssUssAverage(int state) {
702 return mPssTable.getValueForId((byte)state, PSS_USS_AVERAGE);
703 }
704
705 public long getPssUssMaximum(int state) {
706 return mPssTable.getValueForId((byte)state, PSS_USS_MAXIMUM);
707 }
708
Dianne Hackborne17b4452018-01-10 13:15:40 -0800709 public long getPssRssMinimum(int state) {
710 return mPssTable.getValueForId((byte)state, PSS_RSS_MINIMUM);
711 }
712
713 public long getPssRssAverage(int state) {
714 return mPssTable.getValueForId((byte)state, PSS_RSS_AVERAGE);
715 }
716
717 public long getPssRssMaximum(int state) {
718 return mPssTable.getValueForId((byte)state, PSS_RSS_MAXIMUM);
719 }
720
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700721 /**
722 * Sums up the PSS data and adds it to 'data'.
Kweku Adamsef0c08f2018-08-01 11:55:07 -0700723 *
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700724 * @param data The aggregate data is added here.
725 * @param now SystemClock.uptimeMillis()
726 */
727 public void aggregatePss(TotalMemoryUseCollection data, long now) {
728 final PssAggr fgPss = new PssAggr();
729 final PssAggr bgPss = new PssAggr();
730 final PssAggr cachedPss = new PssAggr();
731 boolean havePss = false;
732 for (int i=0; i<mDurations.getKeyCount(); i++) {
733 final int key = mDurations.getKeyAt(i);
734 int type = SparseMappingTable.getIdFromKey(key);
735 int procState = type % STATE_COUNT;
736 long samples = getPssSampleCount(type);
737 if (samples > 0) {
738 long avg = getPssAverage(type);
739 havePss = true;
740 if (procState <= STATE_IMPORTANT_FOREGROUND) {
741 fgPss.add(avg, samples);
742 } else if (procState <= STATE_RECEIVER) {
743 bgPss.add(avg, samples);
744 } else {
745 cachedPss.add(avg, samples);
746 }
747 }
748 }
749 if (!havePss) {
750 return;
751 }
752 boolean fgHasBg = false;
753 boolean fgHasCached = false;
754 boolean bgHasCached = false;
755 if (fgPss.samples < 3 && bgPss.samples > 0) {
756 fgHasBg = true;
757 fgPss.add(bgPss.pss, bgPss.samples);
758 }
759 if (fgPss.samples < 3 && cachedPss.samples > 0) {
760 fgHasCached = true;
761 fgPss.add(cachedPss.pss, cachedPss.samples);
762 }
763 if (bgPss.samples < 3 && cachedPss.samples > 0) {
764 bgHasCached = true;
765 bgPss.add(cachedPss.pss, cachedPss.samples);
766 }
767 if (bgPss.samples < 3 && !fgHasBg && fgPss.samples > 0) {
768 bgPss.add(fgPss.pss, fgPss.samples);
769 }
770 if (cachedPss.samples < 3 && !bgHasCached && bgPss.samples > 0) {
771 cachedPss.add(bgPss.pss, bgPss.samples);
772 }
773 if (cachedPss.samples < 3 && !fgHasCached && fgPss.samples > 0) {
774 cachedPss.add(fgPss.pss, fgPss.samples);
775 }
776 for (int i=0; i<mDurations.getKeyCount(); i++) {
777 final int key = mDurations.getKeyAt(i);
778 final int type = SparseMappingTable.getIdFromKey(key);
779 long time = mDurations.getValue(key);
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700780 if (mCurCombinedState == type) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700781 time += now - mStartTime;
782 }
783 final int procState = type % STATE_COUNT;
784 data.processStateTime[procState] += time;
785 long samples = getPssSampleCount(type);
786 long avg;
787 if (samples > 0) {
788 avg = getPssAverage(type);
789 } else if (procState <= STATE_IMPORTANT_FOREGROUND) {
790 samples = fgPss.samples;
791 avg = fgPss.pss;
792 } else if (procState <= STATE_RECEIVER) {
793 samples = bgPss.samples;
794 avg = bgPss.pss;
795 } else {
796 samples = cachedPss.samples;
797 avg = cachedPss.pss;
798 }
799 double newAvg = ( (data.processStatePss[procState]
800 * (double)data.processStateSamples[procState])
801 + (avg*(double)samples)
802 ) / (data.processStateSamples[procState]+samples);
803 data.processStatePss[procState] = (long)newAvg;
804 data.processStateSamples[procState] += samples;
805 data.processStateWeight[procState] += avg * (double)time;
806 }
807 }
808
809 public long computeProcessTimeLocked(int[] screenStates, int[] memStates,
810 int[] procStates, long now) {
811 long totalTime = 0;
812 for (int is=0; is<screenStates.length; is++) {
813 for (int im=0; im<memStates.length; im++) {
814 for (int ip=0; ip<procStates.length; ip++) {
815 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
816 + procStates[ip];
817 totalTime += getDuration(bucket, now);
818 }
819 }
820 }
821 mTmpTotalTime = totalTime;
822 return totalTime;
823 }
824
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700825 public void dumpSummary(PrintWriter pw, String prefix, String header,
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700826 int[] screenStates, int[] memStates, int[] procStates,
827 long now, long totalTime) {
828 pw.print(prefix);
829 pw.print("* ");
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700830 if (header != null) {
831 pw.print(header);
832 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700833 pw.print(mName);
834 pw.print(" / ");
835 UserHandle.formatUid(pw, mUid);
836 pw.print(" / v");
837 pw.print(mVersion);
838 pw.println(":");
Dianne Hackborn7aea7a42018-07-25 08:58:47 -0700839 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABEL_TOTAL,
840 screenStates, memStates, procStates, now, totalTime, true);
841 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_PERSISTENT],
842 screenStates, memStates, new int[] { STATE_PERSISTENT }, now, totalTime, true);
843 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_TOP],
844 screenStates, memStates, new int[] {STATE_TOP}, now, totalTime, true);
845 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_IMPORTANT_FOREGROUND],
846 screenStates, memStates, new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime,
847 true);
848 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_IMPORTANT_BACKGROUND],
849 screenStates, memStates, new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime,
850 true);
851 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_BACKUP],
852 screenStates, memStates, new int[] {STATE_BACKUP}, now, totalTime, true);
853 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_SERVICE],
854 screenStates, memStates, new int[] {STATE_SERVICE}, now, totalTime, true);
855 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_SERVICE_RESTARTING],
856 screenStates, memStates, new int[] {STATE_SERVICE_RESTARTING}, now, totalTime,
857 true);
858 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_RECEIVER],
859 screenStates, memStates, new int[] {STATE_RECEIVER}, now, totalTime, true);
860 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_HEAVY_WEIGHT],
861 screenStates, memStates, new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
862 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_HOME],
863 screenStates, memStates, new int[] {STATE_HOME}, now, totalTime, true);
864 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_LAST_ACTIVITY],
865 screenStates, memStates, new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
866 dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABEL_CACHED,
867 screenStates, memStates, new int[] {STATE_CACHED_ACTIVITY,
868 STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY}, now, totalTime, true);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700869 }
870
871 public void dumpProcessState(PrintWriter pw, String prefix,
872 int[] screenStates, int[] memStates, int[] procStates, long now) {
873 long totalTime = 0;
874 int printedScreen = -1;
875 for (int is=0; is<screenStates.length; is++) {
876 int printedMem = -1;
877 for (int im=0; im<memStates.length; im++) {
878 for (int ip=0; ip<procStates.length; ip++) {
879 final int iscreen = screenStates[is];
880 final int imem = memStates[im];
881 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
882 long time = mDurations.getValueForId((byte)bucket);
883 String running = "";
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -0700884 if (mCurCombinedState == bucket) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700885 running = " (running)";
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700886 time += now - mStartTime;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700887 }
888 if (time != 0) {
889 pw.print(prefix);
890 if (screenStates.length > 1) {
891 DumpUtils.printScreenLabel(pw, printedScreen != iscreen
892 ? iscreen : STATE_NOTHING);
893 printedScreen = iscreen;
894 }
895 if (memStates.length > 1) {
896 DumpUtils.printMemLabel(pw,
897 printedMem != imem ? imem : STATE_NOTHING, '/');
898 printedMem = imem;
899 }
Dianne Hackborn7aea7a42018-07-25 08:58:47 -0700900 pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700901 TimeUtils.formatDuration(time, pw); pw.println(running);
902 totalTime += time;
903 }
904 }
905 }
906 }
907 if (totalTime != 0) {
908 pw.print(prefix);
909 if (screenStates.length > 1) {
910 DumpUtils.printScreenLabel(pw, STATE_NOTHING);
911 }
912 if (memStates.length > 1) {
913 DumpUtils.printMemLabel(pw, STATE_NOTHING, '/');
914 }
Dianne Hackborn7aea7a42018-07-25 08:58:47 -0700915 pw.print(DumpUtils.STATE_LABEL_TOTAL);
916 pw.print(": ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700917 TimeUtils.formatDuration(totalTime, pw);
918 pw.println();
919 }
920 }
921
922 public void dumpPss(PrintWriter pw, String prefix,
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700923 int[] screenStates, int[] memStates, int[] procStates, long now) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700924 boolean printedHeader = false;
925 int printedScreen = -1;
926 for (int is=0; is<screenStates.length; is++) {
927 int printedMem = -1;
928 for (int im=0; im<memStates.length; im++) {
929 for (int ip=0; ip<procStates.length; ip++) {
930 final int iscreen = screenStates[is];
931 final int imem = memStates[im];
932 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700933 final int key = mPssTable.getKey((byte)bucket);
934 if (key == SparseMappingTable.INVALID_KEY) {
935 continue;
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700936 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700937 final long[] table = mPssTable.getArrayForKey(key);
938 final int tableOffset = SparseMappingTable.getIndexFromKey(key);
939 if (!printedHeader) {
940 pw.print(prefix);
941 pw.print("PSS/USS (");
942 pw.print(mPssTable.getKeyCount());
943 pw.println(" entries):");
944 printedHeader = true;
945 }
946 pw.print(prefix);
947 pw.print(" ");
948 if (screenStates.length > 1) {
949 DumpUtils.printScreenLabel(pw,
950 printedScreen != iscreen ? iscreen : STATE_NOTHING);
951 printedScreen = iscreen;
952 }
953 if (memStates.length > 1) {
954 DumpUtils.printMemLabel(pw,
955 printedMem != imem ? imem : STATE_NOTHING, '/');
956 printedMem = imem;
957 }
958 pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
959 dumpPssSamples(pw, table, tableOffset);
960 pw.println();
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700961 }
962 }
963 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700964 final long totalRunningDuration = getTotalRunningDuration(now);
965 if (totalRunningDuration != 0) {
966 pw.print(prefix);
967 pw.print("Cur time ");
968 TimeUtils.formatDuration(totalRunningDuration, pw);
969 if (mTotalRunningStartTime != 0) {
970 pw.print(" (running)");
971 }
972 if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
973 pw.print(": ");
974 dumpPssSamples(pw, mTotalRunningPss, 0);
975 }
976 pw.println();
977 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700978 if (mNumExcessiveCpu != 0) {
979 pw.print(prefix); pw.print("Killed for excessive CPU use: ");
980 pw.print(mNumExcessiveCpu); pw.println(" times");
981 }
982 if (mNumCachedKill != 0) {
983 pw.print(prefix); pw.print("Killed from cached state: ");
984 pw.print(mNumCachedKill); pw.print(" times from pss ");
985 DebugUtils.printSizeValue(pw, mMinCachedKillPss * 1024); pw.print("-");
986 DebugUtils.printSizeValue(pw, mAvgCachedKillPss * 1024); pw.print("-");
987 DebugUtils.printSizeValue(pw, mMaxCachedKillPss * 1024); pw.println();
988 }
989 }
990
Dianne Hackborn99aeba82018-07-31 13:29:33 -0700991 public static void dumpPssSamples(PrintWriter pw, long[] table, int offset) {
992 DebugUtils.printSizeValue(pw, table[offset + PSS_MINIMUM] * 1024);
993 pw.print("-");
994 DebugUtils.printSizeValue(pw, table[offset + PSS_AVERAGE] * 1024);
995 pw.print("-");
996 DebugUtils.printSizeValue(pw, table[offset + PSS_MAXIMUM] * 1024);
997 pw.print("/");
998 DebugUtils.printSizeValue(pw, table[offset + PSS_USS_MINIMUM] * 1024);
999 pw.print("-");
1000 DebugUtils.printSizeValue(pw, table[offset + PSS_USS_AVERAGE] * 1024);
1001 pw.print("-");
1002 DebugUtils.printSizeValue(pw, table[offset + PSS_USS_MAXIMUM] * 1024);
1003 pw.print("/");
1004 DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_MINIMUM] * 1024);
1005 pw.print("-");
1006 DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_AVERAGE] * 1024);
1007 pw.print("-");
1008 DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_MAXIMUM] * 1024);
1009 pw.print(" over ");
1010 pw.print(table[offset + PSS_SAMPLE_COUNT]);
1011 }
1012
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001013 private void dumpProcessSummaryDetails(PrintWriter pw, String prefix,
1014 String label, int[] screenStates, int[] memStates, int[] procStates,
1015 long now, long totalTime, boolean full) {
1016 ProcessStats.ProcessDataCollection totals = new ProcessStats.ProcessDataCollection(
1017 screenStates, memStates, procStates);
1018 computeProcessData(totals, now);
1019 final double percentage = (double) totals.totalTime / (double) totalTime * 100;
1020 // We don't print percentages < .01, so just drop those.
1021 if (percentage >= 0.005 || totals.numPss != 0) {
1022 if (prefix != null) {
1023 pw.print(prefix);
1024 }
1025 if (label != null) {
Dianne Hackborn7aea7a42018-07-25 08:58:47 -07001026 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001027 pw.print(label);
Dianne Hackborn7aea7a42018-07-25 08:58:47 -07001028 pw.print(": ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001029 }
1030 totals.print(pw, totalTime, full);
1031 if (prefix != null) {
1032 pw.println();
1033 }
1034 }
1035 }
1036
1037 public void dumpInternalLocked(PrintWriter pw, String prefix, boolean dumpAll) {
1038 if (dumpAll) {
1039 pw.print(prefix); pw.print("myID=");
1040 pw.print(Integer.toHexString(System.identityHashCode(this)));
1041 pw.print(" mCommonProcess=");
1042 pw.print(Integer.toHexString(System.identityHashCode(mCommonProcess)));
1043 pw.print(" mPackage="); pw.println(mPackage);
1044 if (mMultiPackage) {
1045 pw.print(prefix); pw.print("mMultiPackage="); pw.println(mMultiPackage);
1046 }
1047 if (this != mCommonProcess) {
1048 pw.print(prefix); pw.print("Common Proc: "); pw.print(mCommonProcess.mName);
1049 pw.print("/"); pw.print(mCommonProcess.mUid);
1050 pw.print(" pkg="); pw.println(mCommonProcess.mPackage);
1051 }
1052 }
1053 if (mActive) {
1054 pw.print(prefix); pw.print("mActive="); pw.println(mActive);
1055 }
1056 if (mDead) {
1057 pw.print(prefix); pw.print("mDead="); pw.println(mDead);
1058 }
1059 if (mNumActiveServices != 0 || mNumStartedServices != 0) {
1060 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(mNumActiveServices);
1061 pw.print(" mNumStartedServices=");
1062 pw.println(mNumStartedServices);
1063 }
1064 }
1065
1066 public void computeProcessData(ProcessStats.ProcessDataCollection data, long now) {
1067 data.totalTime = 0;
1068 data.numPss = data.minPss = data.avgPss = data.maxPss =
Dianne Hackborne17b4452018-01-10 13:15:40 -08001069 data.minUss = data.avgUss = data.maxUss =
1070 data.minRss = data.avgRss = data.maxRss = 0;
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001071 for (int is=0; is<data.screenStates.length; is++) {
1072 for (int im=0; im<data.memStates.length; im++) {
1073 for (int ip=0; ip<data.procStates.length; ip++) {
1074 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
1075 + data.procStates[ip];
1076 data.totalTime += getDuration(bucket, now);
1077 long samples = getPssSampleCount(bucket);
1078 if (samples > 0) {
1079 long minPss = getPssMinimum(bucket);
1080 long avgPss = getPssAverage(bucket);
1081 long maxPss = getPssMaximum(bucket);
1082 long minUss = getPssUssMinimum(bucket);
1083 long avgUss = getPssUssAverage(bucket);
1084 long maxUss = getPssUssMaximum(bucket);
Dianne Hackborne17b4452018-01-10 13:15:40 -08001085 long minRss = getPssRssMinimum(bucket);
1086 long avgRss = getPssRssAverage(bucket);
1087 long maxRss = getPssRssMaximum(bucket);
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001088 if (data.numPss == 0) {
1089 data.minPss = minPss;
1090 data.avgPss = avgPss;
1091 data.maxPss = maxPss;
1092 data.minUss = minUss;
1093 data.avgUss = avgUss;
1094 data.maxUss = maxUss;
Dianne Hackborne17b4452018-01-10 13:15:40 -08001095 data.minRss = minRss;
1096 data.avgRss = avgRss;
1097 data.maxRss = maxRss;
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001098 } else {
1099 if (minPss < data.minPss) {
1100 data.minPss = minPss;
1101 }
1102 data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
1103 + (avgPss*(double)samples)) / (data.numPss+samples) );
1104 if (maxPss > data.maxPss) {
1105 data.maxPss = maxPss;
1106 }
1107 if (minUss < data.minUss) {
1108 data.minUss = minUss;
1109 }
1110 data.avgUss = (long)( ((data.avgUss*(double)data.numPss)
1111 + (avgUss*(double)samples)) / (data.numPss+samples) );
1112 if (maxUss > data.maxUss) {
1113 data.maxUss = maxUss;
1114 }
Dianne Hackborne17b4452018-01-10 13:15:40 -08001115 if (minRss < data.minRss) {
1116 data.minRss = minRss;
1117 }
1118 data.avgRss = (long)( ((data.avgRss*(double)data.numPss)
1119 + (avgRss*(double)samples)) / (data.numPss+samples) );
1120 if (maxRss > data.maxRss) {
1121 data.maxRss = maxRss;
1122 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001123 }
1124 data.numPss += samples;
1125 }
1126 }
1127 }
1128 }
1129 }
1130
1131 public void dumpCsv(PrintWriter pw,
1132 boolean sepScreenStates, int[] screenStates, boolean sepMemStates,
1133 int[] memStates, boolean sepProcStates, int[] procStates, long now) {
1134 final int NSS = sepScreenStates ? screenStates.length : 1;
1135 final int NMS = sepMemStates ? memStates.length : 1;
1136 final int NPS = sepProcStates ? procStates.length : 1;
1137 for (int iss=0; iss<NSS; iss++) {
1138 for (int ims=0; ims<NMS; ims++) {
1139 for (int ips=0; ips<NPS; ips++) {
1140 final int vsscreen = sepScreenStates ? screenStates[iss] : 0;
1141 final int vsmem = sepMemStates ? memStates[ims] : 0;
1142 final int vsproc = sepProcStates ? procStates[ips] : 0;
1143 final int NSA = sepScreenStates ? 1 : screenStates.length;
1144 final int NMA = sepMemStates ? 1 : memStates.length;
1145 final int NPA = sepProcStates ? 1 : procStates.length;
1146 long totalTime = 0;
1147 for (int isa=0; isa<NSA; isa++) {
1148 for (int ima=0; ima<NMA; ima++) {
1149 for (int ipa=0; ipa<NPA; ipa++) {
1150 final int vascreen = sepScreenStates ? 0 : screenStates[isa];
1151 final int vamem = sepMemStates ? 0 : memStates[ima];
1152 final int vaproc = sepProcStates ? 0 : procStates[ipa];
1153 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
1154 * STATE_COUNT) + vsproc + vaproc;
1155 totalTime += getDuration(bucket, now);
1156 }
1157 }
1158 }
1159 pw.print(DumpUtils.CSV_SEP);
1160 pw.print(totalTime);
1161 }
1162 }
1163 }
1164 }
1165
Dianne Hackborn3accca02013-09-20 09:32:11 -07001166 public void dumpPackageProcCheckin(PrintWriter pw, String pkgName, int uid, long vers,
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001167 String itemName, long now) {
1168 pw.print("pkgproc,");
1169 pw.print(pkgName);
1170 pw.print(",");
1171 pw.print(uid);
1172 pw.print(",");
1173 pw.print(vers);
1174 pw.print(",");
1175 pw.print(DumpUtils.collapseString(pkgName, itemName));
1176 dumpAllStateCheckin(pw, now);
1177 pw.println();
1178 if (mPssTable.getKeyCount() > 0) {
1179 pw.print("pkgpss,");
1180 pw.print(pkgName);
1181 pw.print(",");
1182 pw.print(uid);
1183 pw.print(",");
1184 pw.print(vers);
1185 pw.print(",");
1186 pw.print(DumpUtils.collapseString(pkgName, itemName));
1187 dumpAllPssCheckin(pw);
1188 pw.println();
1189 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001190 if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
1191 pw.print("pkgrun,");
1192 pw.print(pkgName);
1193 pw.print(",");
1194 pw.print(uid);
1195 pw.print(",");
1196 pw.print(vers);
1197 pw.print(",");
1198 pw.print(DumpUtils.collapseString(pkgName, itemName));
1199 pw.print(",");
1200 pw.print(getTotalRunningDuration(now));
1201 pw.print(",");
1202 dumpPssSamplesCheckin(pw, mTotalRunningPss, 0);
1203 pw.println();
1204 }
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001205 if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001206 pw.print("pkgkills,");
1207 pw.print(pkgName);
1208 pw.print(",");
1209 pw.print(uid);
1210 pw.print(",");
1211 pw.print(vers);
1212 pw.print(",");
1213 pw.print(DumpUtils.collapseString(pkgName, itemName));
1214 pw.print(",");
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001215 pw.print("0"); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001216 pw.print(",");
1217 pw.print(mNumExcessiveCpu);
1218 pw.print(",");
1219 pw.print(mNumCachedKill);
1220 pw.print(",");
1221 pw.print(mMinCachedKillPss);
1222 pw.print(":");
1223 pw.print(mAvgCachedKillPss);
1224 pw.print(":");
1225 pw.print(mMaxCachedKillPss);
1226 pw.println();
1227 }
1228 }
1229
1230 public void dumpProcCheckin(PrintWriter pw, String procName, int uid, long now) {
1231 if (mDurations.getKeyCount() > 0) {
1232 pw.print("proc,");
1233 pw.print(procName);
1234 pw.print(",");
1235 pw.print(uid);
1236 dumpAllStateCheckin(pw, now);
1237 pw.println();
1238 }
1239 if (mPssTable.getKeyCount() > 0) {
1240 pw.print("pss,");
1241 pw.print(procName);
1242 pw.print(",");
1243 pw.print(uid);
1244 dumpAllPssCheckin(pw);
1245 pw.println();
1246 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001247 if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
1248 pw.print("procrun,");
1249 pw.print(procName);
1250 pw.print(",");
1251 pw.print(uid);
1252 pw.print(",");
1253 pw.print(getTotalRunningDuration(now));
1254 pw.print(",");
1255 dumpPssSamplesCheckin(pw, mTotalRunningPss, 0);
1256 pw.println();
1257 }
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001258 if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001259 pw.print("kills,");
1260 pw.print(procName);
1261 pw.print(",");
1262 pw.print(uid);
1263 pw.print(",");
Dianne Hackbornffca58b2017-05-24 16:15:45 -07001264 pw.print("0"); // was mNumExcessiveWake
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001265 pw.print(",");
1266 pw.print(mNumExcessiveCpu);
1267 pw.print(",");
1268 pw.print(mNumCachedKill);
1269 pw.print(",");
1270 pw.print(mMinCachedKillPss);
1271 pw.print(":");
1272 pw.print(mAvgCachedKillPss);
1273 pw.print(":");
1274 pw.print(mMaxCachedKillPss);
1275 pw.println();
1276 }
1277 }
1278
1279 public void dumpAllStateCheckin(PrintWriter pw, long now) {
1280 boolean didCurState = false;
1281 for (int i=0; i<mDurations.getKeyCount(); i++) {
1282 final int key = mDurations.getKeyAt(i);
1283 final int type = SparseMappingTable.getIdFromKey(key);
1284 long time = mDurations.getValue(key);
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -07001285 if (mCurCombinedState == type) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001286 didCurState = true;
1287 time += now - mStartTime;
1288 }
1289 DumpUtils.printProcStateTagAndValue(pw, type, time);
1290 }
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -07001291 if (!didCurState && mCurCombinedState != STATE_NOTHING) {
1292 DumpUtils.printProcStateTagAndValue(pw, mCurCombinedState, now - mStartTime);
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001293 }
1294 }
1295
1296 public void dumpAllPssCheckin(PrintWriter pw) {
1297 final int N = mPssTable.getKeyCount();
1298 for (int i=0; i<N; i++) {
1299 final int key = mPssTable.getKeyAt(i);
1300 final int type = SparseMappingTable.getIdFromKey(key);
1301 pw.print(',');
1302 DumpUtils.printProcStateTag(pw, type);
1303 pw.print(':');
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001304 dumpPssSamplesCheckin(pw, mPssTable.getArrayForKey(key),
1305 SparseMappingTable.getIndexFromKey(key));
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001306 }
1307 }
1308
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001309 public static void dumpPssSamplesCheckin(PrintWriter pw, long[] table, int offset) {
1310 pw.print(table[offset + PSS_SAMPLE_COUNT]);
1311 pw.print(':');
1312 pw.print(table[offset + PSS_MINIMUM]);
1313 pw.print(':');
1314 pw.print(table[offset + PSS_AVERAGE]);
1315 pw.print(':');
1316 pw.print(table[offset + PSS_MAXIMUM]);
1317 pw.print(':');
1318 pw.print(table[offset + PSS_USS_MINIMUM]);
1319 pw.print(':');
1320 pw.print(table[offset + PSS_USS_AVERAGE]);
1321 pw.print(':');
1322 pw.print(table[offset + PSS_USS_MAXIMUM]);
1323 pw.print(':');
1324 pw.print(table[offset + PSS_RSS_MINIMUM]);
1325 pw.print(':');
1326 pw.print(table[offset + PSS_RSS_AVERAGE]);
1327 pw.print(':');
1328 pw.print(table[offset + PSS_RSS_MAXIMUM]);
1329 }
1330
Yi Jin9680cfa2017-09-15 15:14:43 -07001331 @Override
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001332 public String toString() {
1333 StringBuilder sb = new StringBuilder(128);
1334 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
1335 .append(" ").append(mName).append("/").append(mUid)
1336 .append(" pkg=").append(mPackage);
1337 if (mMultiPackage) sb.append(" (multi)");
1338 if (mCommonProcess != this) sb.append(" (sub)");
1339 sb.append("}");
1340 return sb.toString();
1341 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001342
Jeffrey Huangcb782852019-12-05 11:28:11 -08001343 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Yi Jin676d1ac2018-01-25 15:40:28 -08001344 String procName, int uid, long now) {
1345 final long token = proto.start(fieldId);
Yi Jin9680cfa2017-09-15 15:14:43 -07001346 proto.write(ProcessStatsProto.PROCESS, procName);
1347 proto.write(ProcessStatsProto.UID, uid);
1348 if (mNumExcessiveCpu > 0 || mNumCachedKill > 0 ) {
1349 final long killToken = proto.start(ProcessStatsProto.KILL);
Yi Jin9680cfa2017-09-15 15:14:43 -07001350 proto.write(ProcessStatsProto.Kill.CPU, mNumExcessiveCpu);
1351 proto.write(ProcessStatsProto.Kill.CACHED, mNumCachedKill);
1352 ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.Kill.CACHED_PSS,
1353 mMinCachedKillPss, mAvgCachedKillPss, mMaxCachedKillPss);
1354 proto.end(killToken);
1355 }
1356
1357 // Group proc stats by type (screen state + mem state + process state)
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001358 SparseLongArray durationByState = new SparseLongArray();
Yi Jin9680cfa2017-09-15 15:14:43 -07001359 boolean didCurState = false;
1360 for (int i=0; i<mDurations.getKeyCount(); i++) {
1361 final int key = mDurations.getKeyAt(i);
1362 final int type = SparseMappingTable.getIdFromKey(key);
1363 long time = mDurations.getValue(key);
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -07001364 if (mCurCombinedState == type) {
Yi Jin9680cfa2017-09-15 15:14:43 -07001365 didCurState = true;
1366 time += now - mStartTime;
1367 }
1368 durationByState.put(type, time);
1369 }
Dianne Hackborn2fd8ce42018-07-12 14:51:54 -07001370 if (!didCurState && mCurCombinedState != STATE_NOTHING) {
1371 durationByState.put(mCurCombinedState, now - mStartTime);
Yi Jin9680cfa2017-09-15 15:14:43 -07001372 }
1373
1374 for (int i=0; i<mPssTable.getKeyCount(); i++) {
1375 final int key = mPssTable.getKeyAt(i);
1376 final int type = SparseMappingTable.getIdFromKey(key);
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001377 if (durationByState.indexOfKey(type) < 0) {
Yi Jin9680cfa2017-09-15 15:14:43 -07001378 // state without duration should not have stats!
1379 continue;
1380 }
1381 final long stateToken = proto.start(ProcessStatsProto.STATES);
1382 DumpUtils.printProcStateTagProto(proto,
Dianne Hackborneaed0ba2018-08-08 17:10:17 -07001383 ProcessStatsStateProto.SCREEN_STATE,
1384 ProcessStatsStateProto.MEMORY_STATE,
1385 ProcessStatsStateProto.PROCESS_STATE,
Yi Jin9680cfa2017-09-15 15:14:43 -07001386 type);
1387
1388 long duration = durationByState.get(type);
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001389 durationByState.delete(type); // remove the key since it is already being dumped.
Dianne Hackborneaed0ba2018-08-08 17:10:17 -07001390 proto.write(ProcessStatsStateProto.DURATION_MS, duration);
Yi Jin9680cfa2017-09-15 15:14:43 -07001391
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001392 mPssTable.writeStatsToProtoForKey(proto, key);
Yi Jin9680cfa2017-09-15 15:14:43 -07001393
1394 proto.end(stateToken);
1395 }
1396
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001397 for (int i = 0; i < durationByState.size(); i++) {
Yi Jin9680cfa2017-09-15 15:14:43 -07001398 final long stateToken = proto.start(ProcessStatsProto.STATES);
1399 DumpUtils.printProcStateTagProto(proto,
Dianne Hackborneaed0ba2018-08-08 17:10:17 -07001400 ProcessStatsStateProto.SCREEN_STATE,
1401 ProcessStatsStateProto.MEMORY_STATE,
1402 ProcessStatsStateProto.PROCESS_STATE,
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001403 durationByState.keyAt(i));
Dianne Hackborneaed0ba2018-08-08 17:10:17 -07001404 proto.write(ProcessStatsStateProto.DURATION_MS, durationByState.valueAt(i));
Yi Jin9680cfa2017-09-15 15:14:43 -07001405 proto.end(stateToken);
1406 }
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001407
1408 final long totalRunningDuration = getTotalRunningDuration(now);
1409 if (totalRunningDuration > 0) {
1410 final long stateToken = proto.start(ProcessStatsProto.TOTAL_RUNNING_STATE);
Dianne Hackborneaed0ba2018-08-08 17:10:17 -07001411 proto.write(ProcessStatsStateProto.DURATION_MS, totalRunningDuration);
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001412 if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
1413 PssTable.writeStatsToProto(proto, mTotalRunningPss, 0);
1414 }
1415 proto.end(stateToken);
Dianne Hackborn99aeba82018-07-31 13:29:33 -07001416 }
1417
Yi Jin676d1ac2018-01-25 15:40:28 -08001418 proto.end(token);
Yi Jin9680cfa2017-09-15 15:14:43 -07001419 }
Richard Gaywood57dc86a2020-03-12 17:57:10 +00001420
1421 /** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
1422 public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
1423 String procName, int uid, long now) {
1424 // Group proc stats by aggregated type (only screen state + process state)
1425 SparseLongArray durationByState = new SparseLongArray();
1426 boolean didCurState = false;
1427 for (int i = 0; i < mDurations.getKeyCount(); i++) {
1428 final int key = mDurations.getKeyAt(i);
1429 final int type = SparseMappingTable.getIdFromKey(key);
1430 final int aggregatedType = DumpUtils.aggregateCurrentProcessState(type);
1431
1432 long time = mDurations.getValue(key);
1433 if (mCurCombinedState == type) {
1434 didCurState = true;
1435 time += now - mStartTime;
1436 }
1437 int index = durationByState.indexOfKey(aggregatedType);
1438 if (index >= 0) {
Richard Gaywood863a7212020-03-16 17:49:54 +00001439 durationByState.put(aggregatedType, time + durationByState.valueAt(index));
Richard Gaywood57dc86a2020-03-12 17:57:10 +00001440 } else {
1441 durationByState.put(aggregatedType, time);
1442 }
1443 }
1444 if (!didCurState && mCurCombinedState != STATE_NOTHING) {
1445 final int aggregatedType = DumpUtils.aggregateCurrentProcessState(mCurCombinedState);
1446 int index = durationByState.indexOfKey(aggregatedType);
1447 if (index >= 0) {
1448 durationByState.put(aggregatedType,
1449 (now - mStartTime) + durationByState.valueAt(index));
1450 } else {
1451 durationByState.put(aggregatedType, now - mStartTime);
1452 }
1453 }
1454
1455 // Now we have total durations, aggregate the RSS values
1456 SparseLongArray meanRssByState = new SparseLongArray();
1457 SparseLongArray maxRssByState = new SparseLongArray();
1458 // compute weighted averages and max-of-max
1459 for (int i = 0; i < mPssTable.getKeyCount(); i++) {
1460 final int key = mPssTable.getKeyAt(i);
1461 final int type = SparseMappingTable.getIdFromKey(key);
1462 if (durationByState.indexOfKey(type) < 0) {
1463 // state without duration should not have stats!
1464 continue;
1465 }
1466 final int aggregatedType = DumpUtils.aggregateCurrentProcessState(type);
1467
1468 long[] rssMeanAndMax = mPssTable.getRssMeanAndMax(key);
1469
1470 // compute mean * duration, then store sum of that in meanRssByState
1471 long meanTimesDuration = rssMeanAndMax[0] * mDurations.getValue(key);
1472 if (meanRssByState.indexOfKey(aggregatedType) >= 0) {
1473 meanRssByState.put(aggregatedType,
1474 meanTimesDuration + meanRssByState.get(aggregatedType));
1475 } else {
1476 meanRssByState.put(aggregatedType, meanTimesDuration);
1477 }
1478
1479 // accumulate max-of-maxes in maxRssByState
1480 if (maxRssByState.indexOfKey(aggregatedType) >= 0
1481 && maxRssByState.get(aggregatedType) < rssMeanAndMax[1]) {
1482 maxRssByState.put(aggregatedType, rssMeanAndMax[1]);
1483 } else if (maxRssByState.indexOfKey(aggregatedType) < 0) {
1484 maxRssByState.put(aggregatedType, rssMeanAndMax[1]);
1485 }
1486 }
1487
1488 // divide the means by the durations to get the weighted mean-of-means
1489 for (int i = 0; i < durationByState.size(); i++) {
1490 int aggregatedKey = durationByState.keyAt(i);
1491 if (meanRssByState.indexOfKey(aggregatedKey) < 0) {
1492 // these data structures should be consistent
1493 continue;
1494 }
1495 meanRssByState.put(aggregatedKey,
1496 meanRssByState.get(aggregatedKey) / durationByState.get(aggregatedKey));
1497 }
1498
1499 // build the output
1500 final long token = proto.start(fieldId);
1501 proto.write(ProcessStatsProto.PROCESS, procName);
1502 proto.write(ProcessStatsProto.UID, uid);
1503
1504 for (int i = 0; i < durationByState.size(); i++) {
Richard Gaywood57dc86a2020-03-12 17:57:10 +00001505 final long stateToken = proto.start(ProcessStatsProto.STATES);
Richard Gaywood863a7212020-03-16 17:49:54 +00001506
1507 final int aggregatedKey = durationByState.keyAt(i);
1508
Richard Gaywood57dc86a2020-03-12 17:57:10 +00001509 DumpUtils.printAggregatedProcStateTagProto(proto,
1510 ProcessStatsStateProto.SCREEN_STATE,
1511 ProcessStatsStateProto.PROCESS_STATE,
Richard Gaywood863a7212020-03-16 17:49:54 +00001512 aggregatedKey);
1513 proto.write(ProcessStatsStateProto.DURATION_MS, durationByState.get(aggregatedKey));
Richard Gaywood57dc86a2020-03-12 17:57:10 +00001514
1515 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.RSS,
1516 0, /* do not output a minimum value */
1517 meanRssByState.get(aggregatedKey),
1518 maxRssByState.get(aggregatedKey));
1519
1520 proto.end(stateToken);
1521 }
1522
1523 proto.end(token);
1524 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -07001525}