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