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