Home | History | Annotate | Download | only in procstats
      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 
    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      */
    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      */
    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 
    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 
    210     public String getName() {
    211         return mName;
    212     }
    213 
    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      */
    221     public void makeStandalone() {
    222         mCommonProcess = this;
    223     }
    224 
    225     public String getPackage() {
    226         return mPackage;
    227     }
    228 
    229     public int getUid() {
    230         return mUid;
    231     }
    232 
    233     public int getVersion() {
    234         return mVersion;
    235     }
    236 
    237     public boolean isMultiPackage() {
    238         return mMultiPackage;
    239     }
    240 
    241     public void setMultiPackage(boolean val) {
    242         mMultiPackage = val;
    243     }
    244 
    245     public int getDurationsBucketCount() {
    246         return mDurations.getKeyCount();
    247     }
    248 
    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 
    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 
    272     public void makeDead() {
    273         mDead = true;
    274     }
    275 
    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 
    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 
    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 
    324     public void makeActive() {
    325         ensureNotDead();
    326         mActive = true;
    327     }
    328 
    329     public void makeInactive() {
    330         mActive = false;
    331     }
    332 
    333     public boolean isInUse() {
    334         return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
    335                 || mCurState != STATE_NOTHING;
    336     }
    337 
    338     public boolean isActive() {
    339         return mActive;
    340     }
    341 
    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      */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    625     public long getPssSampleCount(int state) {
    626         return mPssTable.getValueForId((byte)state, PSS_SAMPLE_COUNT);
    627     }
    628 
    629     public long getPssMinimum(int state) {
    630         return mPssTable.getValueForId((byte)state, PSS_MINIMUM);
    631     }
    632 
    633     public long getPssAverage(int state) {
    634         return mPssTable.getValueForId((byte)state, PSS_AVERAGE);
    635     }
    636 
    637     public long getPssMaximum(int state) {
    638         return mPssTable.getValueForId((byte)state, PSS_MAXIMUM);
    639     }
    640 
    641     public long getPssUssMinimum(int state) {
    642         return mPssTable.getValueForId((byte)state, PSS_USS_MINIMUM);
    643     }
    644 
    645     public long getPssUssAverage(int state) {
    646         return mPssTable.getValueForId((byte)state, PSS_USS_AVERAGE);
    647     }
    648 
    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      */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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