Home | History | Annotate | Download | only in app
      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;
     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.util.GrowingArrayUtils;
     34 
     35 import dalvik.system.VMRuntime;
     36 import libcore.util.EmptyArray;
     37 
     38 import java.io.IOException;
     39 import java.io.InputStream;
     40 import java.io.PrintWriter;
     41 import java.util.ArrayList;
     42 import java.util.Arrays;
     43 import java.util.Collections;
     44 import java.util.Comparator;
     45 import java.util.Objects;
     46 
     47 public final class ProcessStats implements Parcelable {
     48     static final String TAG = "ProcessStats";
     49     static final boolean DEBUG = false;
     50     static final boolean DEBUG_PARCEL = false;
     51 
     52     public static final String SERVICE_NAME = "procstats";
     53 
     54     // How often the service commits its data, giving the minimum batching
     55     // that is done.
     56     public static long COMMIT_PERIOD = 3*60*60*1000;  // Commit current stats every 3 hours
     57 
     58     // Minimum uptime period before committing.  If the COMMIT_PERIOD has elapsed but
     59     // the total uptime has not exceeded this amount, then the commit will be held until
     60     // it is reached.
     61     public static long COMMIT_UPTIME_PERIOD = 60*60*1000;  // Must have at least 1 hour elapsed
     62 
     63     public static final int STATE_NOTHING = -1;
     64     public static final int STATE_PERSISTENT = 0;
     65     public static final int STATE_TOP = 1;
     66     public static final int STATE_IMPORTANT_FOREGROUND = 2;
     67     public static final int STATE_IMPORTANT_BACKGROUND = 3;
     68     public static final int STATE_BACKUP = 4;
     69     public static final int STATE_HEAVY_WEIGHT = 5;
     70     public static final int STATE_SERVICE = 6;
     71     public static final int STATE_SERVICE_RESTARTING = 7;
     72     public static final int STATE_RECEIVER = 8;
     73     public static final int STATE_HOME = 9;
     74     public static final int STATE_LAST_ACTIVITY = 10;
     75     public static final int STATE_CACHED_ACTIVITY = 11;
     76     public static final int STATE_CACHED_ACTIVITY_CLIENT = 12;
     77     public static final int STATE_CACHED_EMPTY = 13;
     78     public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
     79 
     80     public static final int PSS_SAMPLE_COUNT = 0;
     81     public static final int PSS_MINIMUM = 1;
     82     public static final int PSS_AVERAGE = 2;
     83     public static final int PSS_MAXIMUM = 3;
     84     public static final int PSS_USS_MINIMUM = 4;
     85     public static final int PSS_USS_AVERAGE = 5;
     86     public static final int PSS_USS_MAXIMUM = 6;
     87     public static final int PSS_COUNT = PSS_USS_MAXIMUM+1;
     88 
     89     public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0;
     90     public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1;
     91     public static final int SYS_MEM_USAGE_CACHED_AVERAGE = 2;
     92     public static final int SYS_MEM_USAGE_CACHED_MAXIMUM = 3;
     93     public static final int SYS_MEM_USAGE_FREE_MINIMUM = 4;
     94     public static final int SYS_MEM_USAGE_FREE_AVERAGE = 5;
     95     public static final int SYS_MEM_USAGE_FREE_MAXIMUM = 6;
     96     public static final int SYS_MEM_USAGE_ZRAM_MINIMUM = 7;
     97     public static final int SYS_MEM_USAGE_ZRAM_AVERAGE = 8;
     98     public static final int SYS_MEM_USAGE_ZRAM_MAXIMUM = 9;
     99     public static final int SYS_MEM_USAGE_KERNEL_MINIMUM = 10;
    100     public static final int SYS_MEM_USAGE_KERNEL_AVERAGE = 11;
    101     public static final int SYS_MEM_USAGE_KERNEL_MAXIMUM = 12;
    102     public static final int SYS_MEM_USAGE_NATIVE_MINIMUM = 13;
    103     public static final int SYS_MEM_USAGE_NATIVE_AVERAGE = 14;
    104     public static final int SYS_MEM_USAGE_NATIVE_MAXIMUM = 15;
    105     public static final int SYS_MEM_USAGE_COUNT = SYS_MEM_USAGE_NATIVE_MAXIMUM+1;
    106 
    107     public static final int ADJ_NOTHING = -1;
    108     public static final int ADJ_MEM_FACTOR_NORMAL = 0;
    109     public static final int ADJ_MEM_FACTOR_MODERATE = 1;
    110     public static final int ADJ_MEM_FACTOR_LOW = 2;
    111     public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
    112     public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
    113     public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
    114     public static final int ADJ_SCREEN_OFF = 0;
    115     public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
    116     public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
    117 
    118     public static final int FLAG_COMPLETE = 1<<0;
    119     public static final int FLAG_SHUTDOWN = 1<<1;
    120     public static final int FLAG_SYSPROPS = 1<<2;
    121 
    122     public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
    123             ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
    124 
    125     public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
    126 
    127     public static final int[] NON_CACHED_PROC_STATES = new int[] {
    128             STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
    129             STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT,
    130             STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
    131     };
    132 
    133     public static final int[] BACKGROUND_PROC_STATES = new int[] {
    134             STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
    135             STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
    136     };
    137 
    138     // Map from process states to the states we track.
    139     static final int[] PROCESS_STATE_TO_STATE = new int[] {
    140             STATE_PERSISTENT,               // ActivityManager.PROCESS_STATE_PERSISTENT
    141             STATE_PERSISTENT,               // ActivityManager.PROCESS_STATE_PERSISTENT_UI
    142             STATE_TOP,                      // ActivityManager.PROCESS_STATE_TOP
    143             STATE_IMPORTANT_FOREGROUND,     // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
    144             STATE_IMPORTANT_FOREGROUND,     // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
    145             STATE_TOP,                      // ActivityManager.PROCESS_STATE_TOP_SLEEPING
    146             STATE_IMPORTANT_FOREGROUND,     // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
    147             STATE_IMPORTANT_BACKGROUND,     // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
    148             STATE_BACKUP,                   // ActivityManager.PROCESS_STATE_BACKUP
    149             STATE_HEAVY_WEIGHT,             // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
    150             STATE_SERVICE,                  // ActivityManager.PROCESS_STATE_SERVICE
    151             STATE_RECEIVER,                 // ActivityManager.PROCESS_STATE_RECEIVER
    152             STATE_HOME,                     // ActivityManager.PROCESS_STATE_HOME
    153             STATE_LAST_ACTIVITY,            // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
    154             STATE_CACHED_ACTIVITY,          // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
    155             STATE_CACHED_ACTIVITY_CLIENT,   // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
    156             STATE_CACHED_EMPTY,             // ActivityManager.PROCESS_STATE_CACHED_EMPTY
    157     };
    158 
    159     public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
    160             STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
    161             STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER,
    162             STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
    163             STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
    164     };
    165 
    166     static final String[] STATE_NAMES = new String[] {
    167             "Persist", "Top    ", "ImpFg  ", "ImpBg  ",
    168             "Backup ", "HeavyWt", "Service", "ServRst",
    169             "Receivr", "Home   ",
    170             "LastAct", "CchAct ", "CchCAct", "CchEmty"
    171     };
    172 
    173     public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
    174             "off", "on"
    175     };
    176 
    177     public static final String[] ADJ_MEM_NAMES_CSV = new String[] {
    178             "norm", "mod",  "low", "crit"
    179     };
    180 
    181     public static final String[] STATE_NAMES_CSV = new String[] {
    182             "pers", "top", "impfg", "impbg", "backup", "heavy",
    183             "service", "service-rs", "receiver", "home", "lastact",
    184             "cch-activity", "cch-aclient", "cch-empty"
    185     };
    186 
    187     static final String[] ADJ_SCREEN_TAGS = new String[] {
    188             "0", "1"
    189     };
    190 
    191     static final String[] ADJ_MEM_TAGS = new String[] {
    192             "n", "m",  "l", "c"
    193     };
    194 
    195     static final String[] STATE_TAGS = new String[] {
    196             "p", "t", "f", "b", "u", "w",
    197             "s", "x", "r", "h", "l", "a", "c", "e"
    198     };
    199 
    200     static final String CSV_SEP = "\t";
    201 
    202     // Current version of the parcel format.
    203     private static final int PARCEL_VERSION = 18;
    204     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
    205     private static final int MAGIC = 0x50535453;
    206 
    207     // Where the "type"/"state" part of the data appears in an offset integer.
    208     static int OFFSET_TYPE_SHIFT = 0;
    209     static int OFFSET_TYPE_MASK = 0xff;
    210     // Where the "which array" part of the data appears in an offset integer.
    211     static int OFFSET_ARRAY_SHIFT = 8;
    212     static int OFFSET_ARRAY_MASK = 0xff;
    213     // Where the "index into array" part of the data appears in an offset integer.
    214     static int OFFSET_INDEX_SHIFT = 16;
    215     static int OFFSET_INDEX_MASK = 0xffff;
    216 
    217     public String mReadError;
    218     public String mTimePeriodStartClockStr;
    219     public int mFlags;
    220 
    221     public final ProcessMap<SparseArray<PackageState>> mPackages
    222             = new ProcessMap<SparseArray<PackageState>>();
    223     public final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
    224 
    225     public final long[] mMemFactorDurations = new long[ADJ_COUNT];
    226     public int mMemFactor = STATE_NOTHING;
    227     public long mStartTime;
    228 
    229     public int[] mSysMemUsageTable = null;
    230     public int mSysMemUsageTableSize = 0;
    231     public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT];
    232 
    233     public long mTimePeriodStartClock;
    234     public long mTimePeriodStartRealtime;
    235     public long mTimePeriodEndRealtime;
    236     public long mTimePeriodStartUptime;
    237     public long mTimePeriodEndUptime;
    238     String mRuntime;
    239     boolean mRunning;
    240 
    241     static final int LONGS_SIZE = 4096;
    242     final ArrayList<long[]> mLongs = new ArrayList<long[]>();
    243     int mNextLong;
    244 
    245     int[] mAddLongTable;
    246     int mAddLongTableSize;
    247 
    248     // For writing parcels.
    249     ArrayMap<String, Integer> mCommonStringToIndex;
    250 
    251     // For reading parcels.
    252     ArrayList<String> mIndexToCommonString;
    253 
    254     public ProcessStats(boolean running) {
    255         mRunning = running;
    256         reset();
    257     }
    258 
    259     public ProcessStats(Parcel in) {
    260         reset();
    261         readFromParcel(in);
    262     }
    263 
    264     public void add(ProcessStats other) {
    265         ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = other.mPackages.getMap();
    266         for (int ip=0; ip<pkgMap.size(); ip++) {
    267             final String pkgName = pkgMap.keyAt(ip);
    268             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
    269             for (int iu=0; iu<uids.size(); iu++) {
    270                 final int uid = uids.keyAt(iu);
    271                 final SparseArray<PackageState> versions = uids.valueAt(iu);
    272                 for (int iv=0; iv<versions.size(); iv++) {
    273                     final int vers = versions.keyAt(iv);
    274                     final PackageState otherState = versions.valueAt(iv);
    275                     final int NPROCS = otherState.mProcesses.size();
    276                     final int NSRVS = otherState.mServices.size();
    277                     for (int iproc=0; iproc<NPROCS; iproc++) {
    278                         ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
    279                         if (otherProc.mCommonProcess != otherProc) {
    280                             if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
    281                                     + " vers " + vers + " proc " + otherProc.mName);
    282                             ProcessState thisProc = getProcessStateLocked(pkgName, uid, vers,
    283                                     otherProc.mName);
    284                             if (thisProc.mCommonProcess == thisProc) {
    285                                 if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
    286                                 thisProc.mMultiPackage = true;
    287                                 long now = SystemClock.uptimeMillis();
    288                                 final PackageState pkgState = getPackageStateLocked(pkgName, uid,
    289                                         vers);
    290                                 thisProc = thisProc.clone(thisProc.mPackage, now);
    291                                 pkgState.mProcesses.put(thisProc.mName, thisProc);
    292                             }
    293                             thisProc.add(otherProc);
    294                         }
    295                     }
    296                     for (int isvc=0; isvc<NSRVS; isvc++) {
    297                         ServiceState otherSvc = otherState.mServices.valueAt(isvc);
    298                         if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
    299                                 + " service " + otherSvc.mName);
    300                         ServiceState thisSvc = getServiceStateLocked(pkgName, uid, vers,
    301                                 otherSvc.mProcessName, otherSvc.mName);
    302                         thisSvc.add(otherSvc);
    303                     }
    304                 }
    305             }
    306         }
    307 
    308         ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
    309         for (int ip=0; ip<procMap.size(); ip++) {
    310             SparseArray<ProcessState> uids = procMap.valueAt(ip);
    311             for (int iu=0; iu<uids.size(); iu++) {
    312                 int uid = uids.keyAt(iu);
    313                 ProcessState otherProc = uids.valueAt(iu);
    314                 ProcessState thisProc = mProcesses.get(otherProc.mName, uid);
    315                 if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName);
    316                 if (thisProc == null) {
    317                     if (DEBUG) Slog.d(TAG, "Creating new process!");
    318                     thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mVersion,
    319                             otherProc.mName);
    320                     mProcesses.put(otherProc.mName, uid, thisProc);
    321                     PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid,
    322                             otherProc.mVersion);
    323                     if (!thisState.mProcesses.containsKey(otherProc.mName)) {
    324                         thisState.mProcesses.put(otherProc.mName, thisProc);
    325                     }
    326                 }
    327                 thisProc.add(otherProc);
    328             }
    329         }
    330 
    331         for (int i=0; i<ADJ_COUNT; i++) {
    332             if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
    333                     + other.mMemFactorDurations[i] + " from "
    334                     + mMemFactorDurations[i]);
    335             mMemFactorDurations[i] += other.mMemFactorDurations[i];
    336         }
    337 
    338         for (int i=0; i<other.mSysMemUsageTableSize; i++) {
    339             int ent = other.mSysMemUsageTable[i];
    340             int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
    341             long[] longs = other.mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
    342             addSysMemUsage(state, longs, ((ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK));
    343         }
    344 
    345         if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
    346             mTimePeriodStartClock = other.mTimePeriodStartClock;
    347             mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
    348         }
    349         mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
    350         mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime;
    351     }
    352 
    353     public void addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem,
    354             long nativeMem) {
    355         if (mMemFactor != STATE_NOTHING) {
    356             int state = mMemFactor * STATE_COUNT;
    357             mSysMemUsageArgs[SYS_MEM_USAGE_SAMPLE_COUNT] = 1;
    358             for (int i=0; i<3; i++) {
    359                 mSysMemUsageArgs[SYS_MEM_USAGE_CACHED_MINIMUM + i] = cachedMem;
    360                 mSysMemUsageArgs[SYS_MEM_USAGE_FREE_MINIMUM + i] = freeMem;
    361                 mSysMemUsageArgs[SYS_MEM_USAGE_ZRAM_MINIMUM + i] = zramMem;
    362                 mSysMemUsageArgs[SYS_MEM_USAGE_KERNEL_MINIMUM + i] = kernelMem;
    363                 mSysMemUsageArgs[SYS_MEM_USAGE_NATIVE_MINIMUM + i] = nativeMem;
    364             }
    365             addSysMemUsage(state, mSysMemUsageArgs, 0);
    366         }
    367     }
    368 
    369     void addSysMemUsage(int state, long[] data, int dataOff) {
    370         int idx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, state);
    371         int off;
    372         if (idx >= 0) {
    373             off = mSysMemUsageTable[idx];
    374         } else {
    375             mAddLongTable = mSysMemUsageTable;
    376             mAddLongTableSize = mSysMemUsageTableSize;
    377             off = addLongData(~idx, state, SYS_MEM_USAGE_COUNT);
    378             mSysMemUsageTable = mAddLongTable;
    379             mSysMemUsageTableSize = mAddLongTableSize;
    380         }
    381         long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
    382         idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
    383         addSysMemUsage(longs, idx, data, dataOff);
    384     }
    385 
    386     static void addSysMemUsage(long[] dstData, int dstOff, long[] addData, int addOff) {
    387         final long dstCount = dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT];
    388         final long addCount = addData[addOff+SYS_MEM_USAGE_SAMPLE_COUNT];
    389         if (dstCount == 0) {
    390             dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = addCount;
    391             for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i++) {
    392                 dstData[dstOff+i] = addData[addOff+i];
    393             }
    394         } else if (addCount > 0) {
    395             dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = dstCount + addCount;
    396             for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i+=3) {
    397                 if (dstData[dstOff+i] > addData[addOff+i]) {
    398                     dstData[dstOff+i] = addData[addOff+i];
    399                 }
    400                 dstData[dstOff+i+1] = (long)(
    401                         ((dstData[dstOff+i+1]*(double)dstCount)
    402                                 + (addData[addOff+i+1]*(double)addCount))
    403                                 / (dstCount+addCount) );
    404                 if (dstData[dstOff+i+2] < addData[addOff+i+2]) {
    405                     dstData[dstOff+i+2] = addData[addOff+i+2];
    406                 }
    407             }
    408         }
    409     }
    410 
    411     public static final Parcelable.Creator<ProcessStats> CREATOR
    412             = new Parcelable.Creator<ProcessStats>() {
    413         public ProcessStats createFromParcel(Parcel in) {
    414             return new ProcessStats(in);
    415         }
    416 
    417         public ProcessStats[] newArray(int size) {
    418             return new ProcessStats[size];
    419         }
    420     };
    421 
    422     private static void printScreenLabel(PrintWriter pw, int offset) {
    423         switch (offset) {
    424             case ADJ_NOTHING:
    425                 pw.print("     ");
    426                 break;
    427             case ADJ_SCREEN_OFF:
    428                 pw.print("SOff/");
    429                 break;
    430             case ADJ_SCREEN_ON:
    431                 pw.print("SOn /");
    432                 break;
    433             default:
    434                 pw.print("????/");
    435                 break;
    436         }
    437     }
    438 
    439     public static void printScreenLabelCsv(PrintWriter pw, int offset) {
    440         switch (offset) {
    441             case ADJ_NOTHING:
    442                 break;
    443             case ADJ_SCREEN_OFF:
    444                 pw.print(ADJ_SCREEN_NAMES_CSV[0]);
    445                 break;
    446             case ADJ_SCREEN_ON:
    447                 pw.print(ADJ_SCREEN_NAMES_CSV[1]);
    448                 break;
    449             default:
    450                 pw.print("???");
    451                 break;
    452         }
    453     }
    454 
    455     private static void printMemLabel(PrintWriter pw, int offset, char sep) {
    456         switch (offset) {
    457             case ADJ_NOTHING:
    458                 pw.print("    ");
    459                 if (sep != 0) pw.print(' ');
    460                 break;
    461             case ADJ_MEM_FACTOR_NORMAL:
    462                 pw.print("Norm");
    463                 if (sep != 0) pw.print(sep);
    464                 break;
    465             case ADJ_MEM_FACTOR_MODERATE:
    466                 pw.print("Mod ");
    467                 if (sep != 0) pw.print(sep);
    468                 break;
    469             case ADJ_MEM_FACTOR_LOW:
    470                 pw.print("Low ");
    471                 if (sep != 0) pw.print(sep);
    472                 break;
    473             case ADJ_MEM_FACTOR_CRITICAL:
    474                 pw.print("Crit");
    475                 if (sep != 0) pw.print(sep);
    476                 break;
    477             default:
    478                 pw.print("????");
    479                 if (sep != 0) pw.print(sep);
    480                 break;
    481         }
    482     }
    483 
    484     public static void printMemLabelCsv(PrintWriter pw, int offset) {
    485         if (offset >= ADJ_MEM_FACTOR_NORMAL) {
    486             if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
    487                 pw.print(ADJ_MEM_NAMES_CSV[offset]);
    488             } else {
    489                 pw.print("???");
    490             }
    491         }
    492     }
    493 
    494     public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
    495             int curState, long curStartTime, long now) {
    496         long totalTime = 0;
    497         int printedScreen = -1;
    498         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
    499             int printedMem = -1;
    500             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
    501                 int state = imem+iscreen;
    502                 long time = durations[state];
    503                 String running = "";
    504                 if (curState == state) {
    505                     time += now - curStartTime;
    506                     if (pw != null) {
    507                         running = " (running)";
    508                     }
    509                 }
    510                 if (time != 0) {
    511                     if (pw != null) {
    512                         pw.print(prefix);
    513                         printScreenLabel(pw, printedScreen != iscreen
    514                                 ? iscreen : STATE_NOTHING);
    515                         printedScreen = iscreen;
    516                         printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
    517                         printedMem = imem;
    518                         pw.print(": ");
    519                         TimeUtils.formatDuration(time, pw); pw.println(running);
    520                     }
    521                     totalTime += time;
    522                 }
    523             }
    524         }
    525         if (totalTime != 0 && pw != null) {
    526             pw.print(prefix);
    527             pw.print("    TOTAL: ");
    528             TimeUtils.formatDuration(totalTime, pw);
    529             pw.println();
    530         }
    531         return totalTime;
    532     }
    533 
    534     static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,
    535             int curState, long curStartTime, long now) {
    536         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
    537             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
    538                 int state = imem+iscreen;
    539                 long time = durations[state];
    540                 if (curState == state) {
    541                     time += now - curStartTime;
    542                 }
    543                 if (time != 0) {
    544                     printAdjTagAndValue(pw, state, time);
    545                 }
    546             }
    547         }
    548     }
    549 
    550     static void dumpServiceTimeCheckin(PrintWriter pw, String label, String packageName,
    551             int uid, int vers, String serviceName, ServiceState svc, int serviceType, int opCount,
    552             int curState, long curStartTime, long now) {
    553         if (opCount <= 0) {
    554             return;
    555         }
    556         pw.print(label);
    557         pw.print(",");
    558         pw.print(packageName);
    559         pw.print(",");
    560         pw.print(uid);
    561         pw.print(",");
    562         pw.print(vers);
    563         pw.print(",");
    564         pw.print(serviceName);
    565         pw.print(",");
    566         pw.print(opCount);
    567         boolean didCurState = false;
    568         for (int i=0; i<svc.mDurationsTableSize; i++) {
    569             int off = svc.mDurationsTable[i];
    570             int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
    571             int memFactor = type / ServiceState.SERVICE_COUNT;
    572             type %= ServiceState.SERVICE_COUNT;
    573             if (type != serviceType) {
    574                 continue;
    575             }
    576             long time = svc.mStats.getLong(off, 0);
    577             if (curState == memFactor) {
    578                 didCurState = true;
    579                 time += now - curStartTime;
    580             }
    581             printAdjTagAndValue(pw, memFactor, time);
    582         }
    583         if (!didCurState && curState != STATE_NOTHING) {
    584             printAdjTagAndValue(pw, curState, now - curStartTime);
    585         }
    586         pw.println();
    587     }
    588 
    589     public static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
    590         data.totalTime = 0;
    591         data.numPss = data.minPss = data.avgPss = data.maxPss =
    592                 data.minUss = data.avgUss = data.maxUss = 0;
    593         for (int is=0; is<data.screenStates.length; is++) {
    594             for (int im=0; im<data.memStates.length; im++) {
    595                 for (int ip=0; ip<data.procStates.length; ip++) {
    596                     int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
    597                             + data.procStates[ip];
    598                     data.totalTime += proc.getDuration(bucket, now);
    599                     long samples = proc.getPssSampleCount(bucket);
    600                     if (samples > 0) {
    601                         long minPss = proc.getPssMinimum(bucket);
    602                         long avgPss = proc.getPssAverage(bucket);
    603                         long maxPss = proc.getPssMaximum(bucket);
    604                         long minUss = proc.getPssUssMinimum(bucket);
    605                         long avgUss = proc.getPssUssAverage(bucket);
    606                         long maxUss = proc.getPssUssMaximum(bucket);
    607                         if (data.numPss == 0) {
    608                             data.minPss = minPss;
    609                             data.avgPss = avgPss;
    610                             data.maxPss = maxPss;
    611                             data.minUss = minUss;
    612                             data.avgUss = avgUss;
    613                             data.maxUss = maxUss;
    614                         } else {
    615                             if (minPss < data.minPss) {
    616                                 data.minPss = minPss;
    617                             }
    618                             data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
    619                                     + (avgPss*(double)samples)) / (data.numPss+samples) );
    620                             if (maxPss > data.maxPss) {
    621                                 data.maxPss = maxPss;
    622                             }
    623                             if (minUss < data.minUss) {
    624                                 data.minUss = minUss;
    625                             }
    626                             data.avgUss = (long)( ((data.avgUss*(double)data.numPss)
    627                                     + (avgUss*(double)samples)) / (data.numPss+samples) );
    628                             if (maxUss > data.maxUss) {
    629                                 data.maxUss = maxUss;
    630                             }
    631                         }
    632                         data.numPss += samples;
    633                     }
    634                 }
    635             }
    636         }
    637     }
    638 
    639     static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
    640                 int[] procStates, long now) {
    641         long totalTime = 0;
    642         /*
    643         for (int i=0; i<proc.mDurationsTableSize; i++) {
    644             int val = proc.mDurationsTable[i];
    645             totalTime += proc.mState.getLong(val, 0);
    646             if ((val&0xff) == proc.mCurState) {
    647                 totalTime += now - proc.mStartTime;
    648             }
    649         }
    650         */
    651         for (int is=0; is<screenStates.length; is++) {
    652             for (int im=0; im<memStates.length; im++) {
    653                 for (int ip=0; ip<procStates.length; ip++) {
    654                     int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
    655                             + procStates[ip];
    656                     totalTime += proc.getDuration(bucket, now);
    657                 }
    658             }
    659         }
    660         proc.mTmpTotalTime = totalTime;
    661         return totalTime;
    662     }
    663 
    664     static class PssAggr {
    665         long pss = 0;
    666         long samples = 0;
    667 
    668         void add(long newPss, long newSamples) {
    669             pss = (long)( (pss*(double)samples) + (newPss*(double)newSamples) )
    670                     / (samples+newSamples);
    671             samples += newSamples;
    672         }
    673     }
    674 
    675     public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) {
    676         data.totalTime = 0;
    677         for (int i=0; i<STATE_COUNT; i++) {
    678             data.processStateWeight[i] = 0;
    679             data.processStatePss[i] = 0;
    680             data.processStateTime[i] = 0;
    681             data.processStateSamples[i] = 0;
    682         }
    683         for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) {
    684             data.sysMemUsage[i] = 0;
    685         }
    686         data.sysMemCachedWeight = 0;
    687         data.sysMemFreeWeight = 0;
    688         data.sysMemZRamWeight = 0;
    689         data.sysMemKernelWeight = 0;
    690         data.sysMemNativeWeight = 0;
    691         data.sysMemSamples = 0;
    692         long[] totalMemUsage = new long[SYS_MEM_USAGE_COUNT];
    693         for (int i=0; i<mSysMemUsageTableSize; i++) {
    694             int ent = mSysMemUsageTable[i];
    695             long[] longs = mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
    696             int idx = (ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK;
    697             addSysMemUsage(totalMemUsage, 0, longs, idx);
    698         }
    699         for (int is=0; is<data.screenStates.length; is++) {
    700             for (int im=0; im<data.memStates.length; im++) {
    701                 int memBucket = data.screenStates[is] + data.memStates[im];
    702                 int stateBucket = memBucket * STATE_COUNT;
    703                 long memTime = mMemFactorDurations[memBucket];
    704                 if (mMemFactor == memBucket) {
    705                     memTime += now - mStartTime;
    706                 }
    707                 data.totalTime += memTime;
    708                 int sysIdx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, stateBucket);
    709                 long[] longs = totalMemUsage;
    710                 int idx = 0;
    711                 if (sysIdx >= 0) {
    712                     int ent = mSysMemUsageTable[sysIdx];
    713                     long[] tmpLongs = mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
    714                     int tmpIdx = (ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK;
    715                     if (tmpLongs[tmpIdx+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) {
    716                         addSysMemUsage(data.sysMemUsage, 0, longs, idx);
    717                         longs = tmpLongs;
    718                         idx = tmpIdx;
    719                     }
    720                 }
    721                 data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE]
    722                         * (double)memTime;
    723                 data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE]
    724                         * (double)memTime;
    725                 data.sysMemZRamWeight += longs[idx+SYS_MEM_USAGE_ZRAM_AVERAGE]
    726                         * (double)memTime;
    727                 data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE]
    728                         * (double)memTime;
    729                 data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE]
    730                         * (double)memTime;
    731                 data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT];
    732              }
    733         }
    734         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
    735         for (int iproc=0; iproc<procMap.size(); iproc++) {
    736             SparseArray<ProcessState> uids = procMap.valueAt(iproc);
    737             for (int iu=0; iu<uids.size(); iu++) {
    738                 final ProcessState proc = uids.valueAt(iu);
    739                 final PssAggr fgPss = new PssAggr();
    740                 final PssAggr bgPss = new PssAggr();
    741                 final PssAggr cachedPss = new PssAggr();
    742                 boolean havePss = false;
    743                 for (int i=0; i<proc.mDurationsTableSize; i++) {
    744                     int off = proc.mDurationsTable[i];
    745                     int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
    746                     int procState = type % STATE_COUNT;
    747                     long samples = proc.getPssSampleCount(type);
    748                     if (samples > 0) {
    749                         long avg = proc.getPssAverage(type);
    750                         havePss = true;
    751                         if (procState <= STATE_IMPORTANT_FOREGROUND) {
    752                             fgPss.add(avg, samples);
    753                         } else if (procState <= STATE_RECEIVER) {
    754                             bgPss.add(avg, samples);
    755                         } else {
    756                             cachedPss.add(avg, samples);
    757                         }
    758                     }
    759                 }
    760                 if (!havePss) {
    761                     continue;
    762                 }
    763                 boolean fgHasBg = false;
    764                 boolean fgHasCached = false;
    765                 boolean bgHasCached = false;
    766                 if (fgPss.samples < 3 && bgPss.samples > 0) {
    767                     fgHasBg = true;
    768                     fgPss.add(bgPss.pss, bgPss.samples);
    769                 }
    770                 if (fgPss.samples < 3 && cachedPss.samples > 0) {
    771                     fgHasCached = true;
    772                     fgPss.add(cachedPss.pss, cachedPss.samples);
    773                 }
    774                 if (bgPss.samples < 3 && cachedPss.samples > 0) {
    775                     bgHasCached = true;
    776                     bgPss.add(cachedPss.pss, cachedPss.samples);
    777                 }
    778                 if (bgPss.samples < 3 && !fgHasBg && fgPss.samples > 0) {
    779                     bgPss.add(fgPss.pss, fgPss.samples);
    780                 }
    781                 if (cachedPss.samples < 3 && !bgHasCached && bgPss.samples > 0) {
    782                     cachedPss.add(bgPss.pss, bgPss.samples);
    783                 }
    784                 if (cachedPss.samples < 3 && !fgHasCached && fgPss.samples > 0) {
    785                     cachedPss.add(fgPss.pss, fgPss.samples);
    786                 }
    787                 for (int i=0; i<proc.mDurationsTableSize; i++) {
    788                     final int off = proc.mDurationsTable[i];
    789                     final int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
    790                     long time = getLong(off, 0);
    791                     if (proc.mCurState == type) {
    792                         time += now - proc.mStartTime;
    793                     }
    794                     final int procState = type % STATE_COUNT;
    795                     data.processStateTime[procState] += time;
    796                     long samples = proc.getPssSampleCount(type);
    797                     long avg;
    798                     if (samples > 0) {
    799                         avg = proc.getPssAverage(type);
    800                     } else if (procState <= STATE_IMPORTANT_FOREGROUND) {
    801                         samples = fgPss.samples;
    802                         avg = fgPss.pss;
    803                     } else if (procState <= STATE_RECEIVER) {
    804                         samples = bgPss.samples;
    805                         avg = bgPss.pss;
    806                     } else {
    807                         samples = cachedPss.samples;
    808                         avg = cachedPss.pss;
    809                     }
    810                     double newAvg = ( (data.processStatePss[procState]
    811                             * (double)data.processStateSamples[procState])
    812                                 + (avg*(double)samples)
    813                             ) / (data.processStateSamples[procState]+samples);
    814                     data.processStatePss[procState] = (long)newAvg;
    815                     data.processStateSamples[procState] += samples;
    816                     data.processStateWeight[procState] += avg * (double)time;
    817                 }
    818             }
    819         }
    820     }
    821 
    822     static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc,
    823             int[] screenStates, int[] memStates, int[] procStates, long now) {
    824         long totalTime = 0;
    825         int printedScreen = -1;
    826         for (int is=0; is<screenStates.length; is++) {
    827             int printedMem = -1;
    828             for (int im=0; im<memStates.length; im++) {
    829                 for (int ip=0; ip<procStates.length; ip++) {
    830                     final int iscreen = screenStates[is];
    831                     final int imem = memStates[im];
    832                     final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
    833                     long time = proc.getDuration(bucket, now);
    834                     String running = "";
    835                     if (proc.mCurState == bucket) {
    836                         running = " (running)";
    837                     }
    838                     if (time != 0) {
    839                         pw.print(prefix);
    840                         if (screenStates.length > 1) {
    841                             printScreenLabel(pw, printedScreen != iscreen
    842                                     ? iscreen : STATE_NOTHING);
    843                             printedScreen = iscreen;
    844                         }
    845                         if (memStates.length > 1) {
    846                             printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
    847                             printedMem = imem;
    848                         }
    849                         pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
    850                         TimeUtils.formatDuration(time, pw); pw.println(running);
    851                         totalTime += time;
    852                     }
    853                 }
    854             }
    855         }
    856         if (totalTime != 0) {
    857             pw.print(prefix);
    858             if (screenStates.length > 1) {
    859                 printScreenLabel(pw, STATE_NOTHING);
    860             }
    861             if (memStates.length > 1) {
    862                 printMemLabel(pw, STATE_NOTHING, '/');
    863             }
    864             pw.print("TOTAL  : ");
    865             TimeUtils.formatDuration(totalTime, pw);
    866             pw.println();
    867         }
    868     }
    869 
    870     static void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
    871             int[] memStates, int[] procStates) {
    872         boolean printedHeader = false;
    873         int printedScreen = -1;
    874         for (int is=0; is<screenStates.length; is++) {
    875             int printedMem = -1;
    876             for (int im=0; im<memStates.length; im++) {
    877                 for (int ip=0; ip<procStates.length; ip++) {
    878                     final int iscreen = screenStates[is];
    879                     final int imem = memStates[im];
    880                     final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
    881                     long count = proc.getPssSampleCount(bucket);
    882                     if (count > 0) {
    883                         if (!printedHeader) {
    884                             pw.print(prefix);
    885                             pw.print("PSS/USS (");
    886                             pw.print(proc.mPssTableSize);
    887                             pw.println(" entries):");
    888                             printedHeader = true;
    889                         }
    890                         pw.print(prefix);
    891                         pw.print("  ");
    892                         if (screenStates.length > 1) {
    893                             printScreenLabel(pw, printedScreen != iscreen
    894                                     ? iscreen : STATE_NOTHING);
    895                             printedScreen = iscreen;
    896                         }
    897                         if (memStates.length > 1) {
    898                             printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
    899                             printedMem = imem;
    900                         }
    901                         pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
    902                         pw.print(count);
    903                         pw.print(" samples ");
    904                         DebugUtils.printSizeValue(pw, proc.getPssMinimum(bucket) * 1024);
    905                         pw.print(" ");
    906                         DebugUtils.printSizeValue(pw, proc.getPssAverage(bucket) * 1024);
    907                         pw.print(" ");
    908                         DebugUtils.printSizeValue(pw, proc.getPssMaximum(bucket) * 1024);
    909                         pw.print(" / ");
    910                         DebugUtils.printSizeValue(pw, proc.getPssUssMinimum(bucket) * 1024);
    911                         pw.print(" ");
    912                         DebugUtils.printSizeValue(pw, proc.getPssUssAverage(bucket) * 1024);
    913                         pw.print(" ");
    914                         DebugUtils.printSizeValue(pw, proc.getPssUssMaximum(bucket) * 1024);
    915                         pw.println();
    916                     }
    917                 }
    918             }
    919         }
    920         if (proc.mNumExcessiveWake != 0) {
    921             pw.print(prefix); pw.print("Killed for excessive wake locks: ");
    922                     pw.print(proc.mNumExcessiveWake); pw.println(" times");
    923         }
    924         if (proc.mNumExcessiveCpu != 0) {
    925             pw.print(prefix); pw.print("Killed for excessive CPU use: ");
    926                     pw.print(proc.mNumExcessiveCpu); pw.println(" times");
    927         }
    928         if (proc.mNumCachedKill != 0) {
    929             pw.print(prefix); pw.print("Killed from cached state: ");
    930                     pw.print(proc.mNumCachedKill); pw.print(" times from pss ");
    931                     DebugUtils.printSizeValue(pw, proc.mMinCachedKillPss * 1024); pw.print("-");
    932                     DebugUtils.printSizeValue(pw, proc.mAvgCachedKillPss * 1024); pw.print("-");
    933                     DebugUtils.printSizeValue(pw, proc.mMaxCachedKillPss * 1024); pw.println();
    934         }
    935     }
    936 
    937     long getSysMemUsageValue(int state, int index) {
    938         int idx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, state);
    939         return idx >= 0 ? getLong(mSysMemUsageTable[idx], index) : 0;
    940     }
    941 
    942     void dumpSysMemUsageCategory(PrintWriter pw, String prefix, String label,
    943             int bucket, int index) {
    944         pw.print(prefix); pw.print(label);
    945         pw.print(": ");
    946         DebugUtils.printSizeValue(pw, getSysMemUsageValue(bucket, index) * 1024);
    947         pw.print(" min, ");
    948         DebugUtils.printSizeValue(pw, getSysMemUsageValue(bucket, index + 1) * 1024);
    949         pw.print(" avg, ");
    950         DebugUtils.printSizeValue(pw, getSysMemUsageValue(bucket, index+2) * 1024);
    951         pw.println(" max");
    952     }
    953 
    954     void dumpSysMemUsage(PrintWriter pw, String prefix, int[] screenStates,
    955             int[] memStates) {
    956         int printedScreen = -1;
    957         for (int is=0; is<screenStates.length; is++) {
    958             int printedMem = -1;
    959             for (int im=0; im<memStates.length; im++) {
    960                 final int iscreen = screenStates[is];
    961                 final int imem = memStates[im];
    962                 final int bucket = ((iscreen + imem) * STATE_COUNT);
    963                 long count = getSysMemUsageValue(bucket, SYS_MEM_USAGE_SAMPLE_COUNT);
    964                 if (count > 0) {
    965                     pw.print(prefix);
    966                     if (screenStates.length > 1) {
    967                         printScreenLabel(pw, printedScreen != iscreen
    968                                 ? iscreen : STATE_NOTHING);
    969                         printedScreen = iscreen;
    970                     }
    971                     if (memStates.length > 1) {
    972                         printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '\0');
    973                         printedMem = imem;
    974                     }
    975                     pw.print(": ");
    976                     pw.print(count);
    977                     pw.println(" samples:");
    978                     dumpSysMemUsageCategory(pw, prefix, "  Cached", bucket,
    979                             SYS_MEM_USAGE_CACHED_MINIMUM);
    980                     dumpSysMemUsageCategory(pw, prefix, "  Free", bucket,
    981                             SYS_MEM_USAGE_FREE_MINIMUM);
    982                     dumpSysMemUsageCategory(pw, prefix, "  ZRam", bucket,
    983                             SYS_MEM_USAGE_ZRAM_MINIMUM);
    984                     dumpSysMemUsageCategory(pw, prefix, "  Kernel", bucket,
    985                             SYS_MEM_USAGE_KERNEL_MINIMUM);
    986                     dumpSysMemUsageCategory(pw, prefix, "  Native", bucket,
    987                             SYS_MEM_USAGE_NATIVE_MINIMUM);
    988                 }
    989             }
    990         }
    991     }
    992 
    993     static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
    994             int[] memStates, int[] procStates) {
    995         final int NS = screenStates != null ? screenStates.length : 1;
    996         final int NM = memStates != null ? memStates.length : 1;
    997         final int NP = procStates != null ? procStates.length : 1;
    998         for (int is=0; is<NS; is++) {
    999             for (int im=0; im<NM; im++) {
   1000                 for (int ip=0; ip<NP; ip++) {
   1001                     pw.print(sep);
   1002                     boolean printed = false;
   1003                     if (screenStates != null && screenStates.length > 1) {
   1004                         printScreenLabelCsv(pw, screenStates[is]);
   1005                         printed = true;
   1006                     }
   1007                     if (memStates != null && memStates.length > 1) {
   1008                         if (printed) {
   1009                             pw.print("-");
   1010                         }
   1011                         printMemLabelCsv(pw, memStates[im]);
   1012                         printed = true;
   1013                     }
   1014                     if (procStates != null && procStates.length > 1) {
   1015                         if (printed) {
   1016                             pw.print("-");
   1017                         }
   1018                         pw.print(STATE_NAMES_CSV[procStates[ip]]);
   1019                     }
   1020                 }
   1021             }
   1022         }
   1023     }
   1024 
   1025     static void dumpProcessStateCsv(PrintWriter pw, ProcessState proc,
   1026             boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
   1027             boolean sepProcStates, int[] procStates, long now) {
   1028         final int NSS = sepScreenStates ? screenStates.length : 1;
   1029         final int NMS = sepMemStates ? memStates.length : 1;
   1030         final int NPS = sepProcStates ? procStates.length : 1;
   1031         for (int iss=0; iss<NSS; iss++) {
   1032             for (int ims=0; ims<NMS; ims++) {
   1033                 for (int ips=0; ips<NPS; ips++) {
   1034                     final int vsscreen = sepScreenStates ? screenStates[iss] : 0;
   1035                     final int vsmem = sepMemStates ? memStates[ims] : 0;
   1036                     final int vsproc = sepProcStates ? procStates[ips] : 0;
   1037                     final int NSA = sepScreenStates ? 1 : screenStates.length;
   1038                     final int NMA = sepMemStates ? 1 : memStates.length;
   1039                     final int NPA = sepProcStates ? 1 : procStates.length;
   1040                     long totalTime = 0;
   1041                     for (int isa=0; isa<NSA; isa++) {
   1042                         for (int ima=0; ima<NMA; ima++) {
   1043                             for (int ipa=0; ipa<NPA; ipa++) {
   1044                                 final int vascreen = sepScreenStates ? 0 : screenStates[isa];
   1045                                 final int vamem = sepMemStates ? 0 : memStates[ima];
   1046                                 final int vaproc = sepProcStates ? 0 : procStates[ipa];
   1047                                 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
   1048                                         * STATE_COUNT) + vsproc + vaproc;
   1049                                 totalTime += proc.getDuration(bucket, now);
   1050                             }
   1051                         }
   1052                     }
   1053                     pw.print(CSV_SEP);
   1054                     pw.print(totalTime);
   1055                 }
   1056             }
   1057         }
   1058     }
   1059 
   1060     static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
   1061             int[] screenStates, int[] memStates, int[] procStates, long now) {
   1062         String innerPrefix = prefix + "  ";
   1063         for (int i=procs.size()-1; i>=0; i--) {
   1064             ProcessState proc = procs.get(i);
   1065             pw.print(prefix);
   1066             pw.print(proc.mName);
   1067             pw.print(" / ");
   1068             UserHandle.formatUid(pw, proc.mUid);
   1069             pw.print(" (");
   1070             pw.print(proc.mDurationsTableSize);
   1071             pw.print(" entries)");
   1072             pw.println(":");
   1073             dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
   1074             if (proc.mPssTableSize > 0) {
   1075                 dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates);
   1076             }
   1077         }
   1078     }
   1079 
   1080     static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix,
   1081             String label, int[] screenStates, int[] memStates, int[] procStates,
   1082             long now, long totalTime, boolean full) {
   1083         ProcessDataCollection totals = new ProcessDataCollection(screenStates,
   1084                 memStates, procStates);
   1085         computeProcessData(proc, totals, now);
   1086         double percentage = (double) totals.totalTime / (double) totalTime * 100;
   1087         // We don't print percentages < .01, so just drop those.
   1088         if (percentage >= 0.005 || totals.numPss != 0) {
   1089             if (prefix != null) {
   1090                 pw.print(prefix);
   1091             }
   1092             if (label != null) {
   1093                 pw.print(label);
   1094             }
   1095             totals.print(pw, totalTime, full);
   1096             if (prefix != null) {
   1097                 pw.println();
   1098             }
   1099         }
   1100     }
   1101 
   1102     static void dumpProcessSummaryLocked(PrintWriter pw, String prefix,
   1103             ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
   1104             boolean inclUidVers, long now, long totalTime) {
   1105         for (int i=procs.size()-1; i>=0; i--) {
   1106             ProcessState proc = procs.get(i);
   1107             pw.print(prefix);
   1108             pw.print("* ");
   1109             pw.print(proc.mName);
   1110             pw.print(" / ");
   1111             UserHandle.formatUid(pw, proc.mUid);
   1112             pw.print(" / v");
   1113             pw.print(proc.mVersion);
   1114             pw.println(":");
   1115             dumpProcessSummaryDetails(pw, proc, prefix, "         TOTAL: ", screenStates, memStates,
   1116                     procStates, now, totalTime, true);
   1117             dumpProcessSummaryDetails(pw, proc, prefix, "    Persistent: ", screenStates, memStates,
   1118                     new int[] { STATE_PERSISTENT }, now, totalTime, true);
   1119             dumpProcessSummaryDetails(pw, proc, prefix, "           Top: ", screenStates, memStates,
   1120                     new int[] {STATE_TOP}, now, totalTime, true);
   1121             dumpProcessSummaryDetails(pw, proc, prefix, "        Imp Fg: ", screenStates, memStates,
   1122                     new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true);
   1123             dumpProcessSummaryDetails(pw, proc, prefix, "        Imp Bg: ", screenStates, memStates,
   1124                     new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true);
   1125             dumpProcessSummaryDetails(pw, proc, prefix, "        Backup: ", screenStates, memStates,
   1126                     new int[] {STATE_BACKUP}, now, totalTime, true);
   1127             dumpProcessSummaryDetails(pw, proc, prefix, "     Heavy Wgt: ", screenStates, memStates,
   1128                     new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
   1129             dumpProcessSummaryDetails(pw, proc, prefix, "       Service: ", screenStates, memStates,
   1130                     new int[] {STATE_SERVICE}, now, totalTime, true);
   1131             dumpProcessSummaryDetails(pw, proc, prefix, "    Service Rs: ", screenStates, memStates,
   1132                     new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
   1133             dumpProcessSummaryDetails(pw, proc, prefix, "      Receiver: ", screenStates, memStates,
   1134                     new int[] {STATE_RECEIVER}, now, totalTime, true);
   1135             dumpProcessSummaryDetails(pw, proc, prefix, "        (Home): ", screenStates, memStates,
   1136                     new int[] {STATE_HOME}, now, totalTime, true);
   1137             dumpProcessSummaryDetails(pw, proc, prefix, "    (Last Act): ", screenStates, memStates,
   1138                     new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
   1139             dumpProcessSummaryDetails(pw, proc, prefix, "      (Cached): ", screenStates, memStates,
   1140                     new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT,
   1141                             STATE_CACHED_EMPTY}, now, totalTime, true);
   1142         }
   1143     }
   1144 
   1145     static void printPercent(PrintWriter pw, double fraction) {
   1146         fraction *= 100;
   1147         if (fraction < 1) {
   1148             pw.print(String.format("%.2f", fraction));
   1149         } else if (fraction < 10) {
   1150             pw.print(String.format("%.1f", fraction));
   1151         } else {
   1152             pw.print(String.format("%.0f", fraction));
   1153         }
   1154         pw.print("%");
   1155     }
   1156 
   1157     public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
   1158             boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
   1159             boolean sepProcStates, int[] procStates, long now) {
   1160         pw.print("process");
   1161         pw.print(CSV_SEP);
   1162         pw.print("uid");
   1163         pw.print(CSV_SEP);
   1164         pw.print("vers");
   1165         dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
   1166                 sepMemStates ? memStates : null,
   1167                 sepProcStates ? procStates : null);
   1168         pw.println();
   1169         for (int i=procs.size()-1; i>=0; i--) {
   1170             ProcessState proc = procs.get(i);
   1171             pw.print(proc.mName);
   1172             pw.print(CSV_SEP);
   1173             UserHandle.formatUid(pw, proc.mUid);
   1174             pw.print(CSV_SEP);
   1175             pw.print(proc.mVersion);
   1176             dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates,
   1177                     sepMemStates, memStates, sepProcStates, procStates, now);
   1178             pw.println();
   1179         }
   1180     }
   1181 
   1182     static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
   1183         int index = value/mod;
   1184         if (index >= 0 && index < array.length) {
   1185             pw.print(array[index]);
   1186         } else {
   1187             pw.print('?');
   1188         }
   1189         return value - index*mod;
   1190     }
   1191 
   1192     static void printProcStateTag(PrintWriter pw, int state) {
   1193         state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD*STATE_COUNT);
   1194         state = printArrayEntry(pw, ADJ_MEM_TAGS,  state, STATE_COUNT);
   1195         printArrayEntry(pw, STATE_TAGS,  state, 1);
   1196     }
   1197 
   1198     static void printAdjTag(PrintWriter pw, int state) {
   1199         state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD);
   1200         printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
   1201     }
   1202 
   1203     static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
   1204         pw.print(',');
   1205         printProcStateTag(pw, state);
   1206         pw.print(':');
   1207         pw.print(value);
   1208     }
   1209 
   1210     static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
   1211         pw.print(',');
   1212         printAdjTag(pw, state);
   1213         pw.print(':');
   1214         pw.print(value);
   1215     }
   1216 
   1217     static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
   1218         boolean didCurState = false;
   1219         for (int i=0; i<proc.mDurationsTableSize; i++) {
   1220             int off = proc.mDurationsTable[i];
   1221             int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   1222             long time = proc.mStats.getLong(off, 0);
   1223             if (proc.mCurState == type) {
   1224                 didCurState = true;
   1225                 time += now - proc.mStartTime;
   1226             }
   1227             printProcStateTagAndValue(pw, type, time);
   1228         }
   1229         if (!didCurState && proc.mCurState != STATE_NOTHING) {
   1230             printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
   1231         }
   1232     }
   1233 
   1234     static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) {
   1235         for (int i=0; i<proc.mPssTableSize; i++) {
   1236             int off = proc.mPssTable[i];
   1237             int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   1238             long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT);
   1239             long min = proc.mStats.getLong(off, PSS_MINIMUM);
   1240             long avg = proc.mStats.getLong(off, PSS_AVERAGE);
   1241             long max = proc.mStats.getLong(off, PSS_MAXIMUM);
   1242             long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM);
   1243             long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE);
   1244             long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM);
   1245             pw.print(',');
   1246             printProcStateTag(pw, type);
   1247             pw.print(':');
   1248             pw.print(count);
   1249             pw.print(':');
   1250             pw.print(min);
   1251             pw.print(':');
   1252             pw.print(avg);
   1253             pw.print(':');
   1254             pw.print(max);
   1255             pw.print(':');
   1256             pw.print(umin);
   1257             pw.print(':');
   1258             pw.print(uavg);
   1259             pw.print(':');
   1260             pw.print(umax);
   1261         }
   1262     }
   1263 
   1264     public void reset() {
   1265         if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr);
   1266         resetCommon();
   1267         mPackages.getMap().clear();
   1268         mProcesses.getMap().clear();
   1269         mMemFactor = STATE_NOTHING;
   1270         mStartTime = 0;
   1271         if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
   1272     }
   1273 
   1274     public void resetSafely() {
   1275         if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
   1276         resetCommon();
   1277 
   1278         // First initialize use count of all common processes.
   1279         final long now = SystemClock.uptimeMillis();
   1280         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   1281         for (int ip=procMap.size()-1; ip>=0; ip--) {
   1282             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1283             for (int iu=uids.size()-1; iu>=0; iu--) {
   1284                 uids.valueAt(iu).mTmpNumInUse = 0;
   1285            }
   1286         }
   1287 
   1288         // Next reset or prune all per-package processes, and for the ones that are reset
   1289         // track this back to the common processes.
   1290         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   1291         for (int ip=pkgMap.size()-1; ip>=0; ip--) {
   1292             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   1293             for (int iu=uids.size()-1; iu>=0; iu--) {
   1294                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   1295                 for (int iv=vpkgs.size()-1; iv>=0; iv--) {
   1296                     final PackageState pkgState = vpkgs.valueAt(iv);
   1297                     for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
   1298                         final ProcessState ps = pkgState.mProcesses.valueAt(iproc);
   1299                         if (ps.isInUse()) {
   1300                             ps.resetSafely(now);
   1301                             ps.mCommonProcess.mTmpNumInUse++;
   1302                             ps.mCommonProcess.mTmpFoundSubProc = ps;
   1303                         } else {
   1304                             pkgState.mProcesses.valueAt(iproc).makeDead();
   1305                             pkgState.mProcesses.removeAt(iproc);
   1306                         }
   1307                     }
   1308                     for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
   1309                         final ServiceState ss = pkgState.mServices.valueAt(isvc);
   1310                         if (ss.isInUse()) {
   1311                             ss.resetSafely(now);
   1312                         } else {
   1313                             pkgState.mServices.removeAt(isvc);
   1314                         }
   1315                     }
   1316                     if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
   1317                         vpkgs.removeAt(iv);
   1318                     }
   1319                 }
   1320                 if (vpkgs.size() <= 0) {
   1321                     uids.removeAt(iu);
   1322                 }
   1323             }
   1324             if (uids.size() <= 0) {
   1325                 pkgMap.removeAt(ip);
   1326             }
   1327         }
   1328 
   1329         // Finally prune out any common processes that are no longer in use.
   1330         for (int ip=procMap.size()-1; ip>=0; ip--) {
   1331             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1332             for (int iu=uids.size()-1; iu>=0; iu--) {
   1333                 ProcessState ps = uids.valueAt(iu);
   1334                 if (ps.isInUse() || ps.mTmpNumInUse > 0) {
   1335                     // If this is a process for multiple packages, we could at this point
   1336                     // be back down to one package.  In that case, we want to revert back
   1337                     // to a single shared ProcessState.  We can do this by converting the
   1338                     // current package-specific ProcessState up to the shared ProcessState,
   1339                     // throwing away the current one we have here (because nobody else is
   1340                     // using it).
   1341                     if (!ps.mActive && ps.mMultiPackage && ps.mTmpNumInUse == 1) {
   1342                         // Here we go...
   1343                         ps = ps.mTmpFoundSubProc;
   1344                         ps.mCommonProcess = ps;
   1345                         uids.setValueAt(iu, ps);
   1346                     } else {
   1347                         ps.resetSafely(now);
   1348                     }
   1349                 } else {
   1350                     ps.makeDead();
   1351                     uids.removeAt(iu);
   1352                 }
   1353             }
   1354             if (uids.size() <= 0) {
   1355                 procMap.removeAt(ip);
   1356             }
   1357         }
   1358 
   1359         mStartTime = now;
   1360         if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
   1361     }
   1362 
   1363     private void resetCommon() {
   1364         mTimePeriodStartClock = System.currentTimeMillis();
   1365         buildTimePeriodStartClockStr();
   1366         mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
   1367         mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis();
   1368         mLongs.clear();
   1369         mLongs.add(new long[LONGS_SIZE]);
   1370         mNextLong = 0;
   1371         Arrays.fill(mMemFactorDurations, 0);
   1372         mSysMemUsageTable = null;
   1373         mSysMemUsageTableSize = 0;
   1374         mStartTime = 0;
   1375         mReadError = null;
   1376         mFlags = 0;
   1377         evaluateSystemProperties(true);
   1378     }
   1379 
   1380     public boolean evaluateSystemProperties(boolean update) {
   1381         boolean changed = false;
   1382         String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2",
   1383                 VMRuntime.getRuntime().vmLibrary());
   1384         if (!Objects.equals(runtime, mRuntime)) {
   1385             changed = true;
   1386             if (update) {
   1387                 mRuntime = runtime;
   1388             }
   1389         }
   1390         return changed;
   1391     }
   1392 
   1393     private void buildTimePeriodStartClockStr() {
   1394         mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
   1395                 mTimePeriodStartClock).toString();
   1396     }
   1397 
   1398     static final int[] BAD_TABLE = new int[0];
   1399 
   1400     private int[] readTableFromParcel(Parcel in, String name, String what) {
   1401         final int size = in.readInt();
   1402         if (size < 0) {
   1403             Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size);
   1404             return BAD_TABLE;
   1405         }
   1406         if (size == 0) {
   1407             return null;
   1408         }
   1409         final int[] table = new int[size];
   1410         for (int i=0; i<size; i++) {
   1411             table[i] = in.readInt();
   1412             if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
   1413                     + ProcessStats.printLongOffset(table[i]));
   1414             if (!validateLongOffset(table[i])) {
   1415                 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
   1416                         + ProcessStats.printLongOffset(table[i]));
   1417                 return null;
   1418             }
   1419         }
   1420         return table;
   1421     }
   1422 
   1423     private void writeCompactedLongArray(Parcel out, long[] array, int num) {
   1424         for (int i=0; i<num; i++) {
   1425             long val = array[i];
   1426             if (val < 0) {
   1427                 Slog.w(TAG, "Time val negative: " + val);
   1428                 val = 0;
   1429             }
   1430             if (val <= Integer.MAX_VALUE) {
   1431                 out.writeInt((int)val);
   1432             } else {
   1433                 int top = ~((int)((val>>32)&0x7fffffff));
   1434                 int bottom = (int)(val&0xfffffff);
   1435                 out.writeInt(top);
   1436                 out.writeInt(bottom);
   1437             }
   1438         }
   1439     }
   1440 
   1441     private void readCompactedLongArray(Parcel in, int version, long[] array, int num) {
   1442         if (version <= 10) {
   1443             in.readLongArray(array);
   1444             return;
   1445         }
   1446         final int alen = array.length;
   1447         if (num > alen) {
   1448             throw new RuntimeException("bad array lengths: got " + num + " array is " + alen);
   1449         }
   1450         int i;
   1451         for (i=0; i<num; i++) {
   1452             int val = in.readInt();
   1453             if (val >= 0) {
   1454                 array[i] = val;
   1455             } else {
   1456                 int bottom = in.readInt();
   1457                 array[i] = (((long)~val)<<32) | bottom;
   1458             }
   1459         }
   1460         while (i < alen) {
   1461             array[i] = 0;
   1462             i++;
   1463         }
   1464     }
   1465 
   1466     private void writeCommonString(Parcel out, String name) {
   1467         Integer index = mCommonStringToIndex.get(name);
   1468         if (index != null) {
   1469             out.writeInt(index);
   1470             return;
   1471         }
   1472         index = mCommonStringToIndex.size();
   1473         mCommonStringToIndex.put(name, index);
   1474         out.writeInt(~index);
   1475         out.writeString(name);
   1476     }
   1477 
   1478     private String readCommonString(Parcel in, int version) {
   1479         if (version <= 9) {
   1480             return in.readString();
   1481         }
   1482         int index = in.readInt();
   1483         if (index >= 0) {
   1484             return mIndexToCommonString.get(index);
   1485         }
   1486         index = ~index;
   1487         String name = in.readString();
   1488         while (mIndexToCommonString.size() <= index) {
   1489             mIndexToCommonString.add(null);
   1490         }
   1491         mIndexToCommonString.set(index, name);
   1492         return name;
   1493     }
   1494 
   1495     @Override
   1496     public int describeContents() {
   1497         return 0;
   1498     }
   1499 
   1500     @Override
   1501     public void writeToParcel(Parcel out, int flags) {
   1502         writeToParcel(out, SystemClock.uptimeMillis(), flags);
   1503     }
   1504 
   1505     /** @hide */
   1506     public void writeToParcel(Parcel out, long now, int flags) {
   1507         out.writeInt(MAGIC);
   1508         out.writeInt(PARCEL_VERSION);
   1509         out.writeInt(STATE_COUNT);
   1510         out.writeInt(ADJ_COUNT);
   1511         out.writeInt(PSS_COUNT);
   1512         out.writeInt(SYS_MEM_USAGE_COUNT);
   1513         out.writeInt(LONGS_SIZE);
   1514 
   1515         mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size());
   1516 
   1517         // First commit all running times.
   1518         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   1519         final int NPROC = procMap.size();
   1520         for (int ip=0; ip<NPROC; ip++) {
   1521             SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1522             final int NUID = uids.size();
   1523             for (int iu=0; iu<NUID; iu++) {
   1524                 uids.valueAt(iu).commitStateTime(now);
   1525             }
   1526         }
   1527         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   1528         final int NPKG = pkgMap.size();
   1529         for (int ip=0; ip<NPKG; ip++) {
   1530             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   1531             final int NUID = uids.size();
   1532             for (int iu=0; iu<NUID; iu++) {
   1533                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   1534                 final int NVERS = vpkgs.size();
   1535                 for (int iv=0; iv<NVERS; iv++) {
   1536                     PackageState pkgState = vpkgs.valueAt(iv);
   1537                     final int NPROCS = pkgState.mProcesses.size();
   1538                     for (int iproc=0; iproc<NPROCS; iproc++) {
   1539                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   1540                         if (proc.mCommonProcess != proc) {
   1541                             proc.commitStateTime(now);
   1542                         }
   1543                     }
   1544                     final int NSRVS = pkgState.mServices.size();
   1545                     for (int isvc=0; isvc<NSRVS; isvc++) {
   1546                         pkgState.mServices.valueAt(isvc).commitStateTime(now);
   1547                     }
   1548                 }
   1549             }
   1550         }
   1551 
   1552         out.writeLong(mTimePeriodStartClock);
   1553         out.writeLong(mTimePeriodStartRealtime);
   1554         out.writeLong(mTimePeriodEndRealtime);
   1555         out.writeLong(mTimePeriodStartUptime);
   1556         out.writeLong(mTimePeriodEndUptime);
   1557         out.writeString(mRuntime);
   1558         out.writeInt(mFlags);
   1559 
   1560         out.writeInt(mLongs.size());
   1561         out.writeInt(mNextLong);
   1562         for (int i=0; i<(mLongs.size()-1); i++) {
   1563             long[] array = mLongs.get(i);
   1564             writeCompactedLongArray(out, array, array.length);
   1565         }
   1566         long[] lastLongs = mLongs.get(mLongs.size() - 1);
   1567         writeCompactedLongArray(out, lastLongs, mNextLong);
   1568 
   1569         if (mMemFactor != STATE_NOTHING) {
   1570             mMemFactorDurations[mMemFactor] += now - mStartTime;
   1571             mStartTime = now;
   1572         }
   1573         writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length);
   1574 
   1575         out.writeInt(mSysMemUsageTableSize);
   1576         for (int i=0; i<mSysMemUsageTableSize; i++) {
   1577             if (DEBUG_PARCEL) Slog.i(TAG, "Writing sys mem usage #" + i + ": "
   1578                     + printLongOffset(mSysMemUsageTable[i]));
   1579             out.writeInt(mSysMemUsageTable[i]);
   1580         }
   1581 
   1582         out.writeInt(NPROC);
   1583         for (int ip=0; ip<NPROC; ip++) {
   1584             writeCommonString(out, procMap.keyAt(ip));
   1585             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1586             final int NUID = uids.size();
   1587             out.writeInt(NUID);
   1588             for (int iu=0; iu<NUID; iu++) {
   1589                 out.writeInt(uids.keyAt(iu));
   1590                 final ProcessState proc = uids.valueAt(iu);
   1591                 writeCommonString(out, proc.mPackage);
   1592                 out.writeInt(proc.mVersion);
   1593                 proc.writeToParcel(out, now);
   1594             }
   1595         }
   1596         out.writeInt(NPKG);
   1597         for (int ip=0; ip<NPKG; ip++) {
   1598             writeCommonString(out, pkgMap.keyAt(ip));
   1599             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   1600             final int NUID = uids.size();
   1601             out.writeInt(NUID);
   1602             for (int iu=0; iu<NUID; iu++) {
   1603                 out.writeInt(uids.keyAt(iu));
   1604                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   1605                 final int NVERS = vpkgs.size();
   1606                 out.writeInt(NVERS);
   1607                 for (int iv=0; iv<NVERS; iv++) {
   1608                     out.writeInt(vpkgs.keyAt(iv));
   1609                     final PackageState pkgState = vpkgs.valueAt(iv);
   1610                     final int NPROCS = pkgState.mProcesses.size();
   1611                     out.writeInt(NPROCS);
   1612                     for (int iproc=0; iproc<NPROCS; iproc++) {
   1613                         writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
   1614                         final ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   1615                         if (proc.mCommonProcess == proc) {
   1616                             // This is the same as the common process we wrote above.
   1617                             out.writeInt(0);
   1618                         } else {
   1619                             // There is separate data for this package's process.
   1620                             out.writeInt(1);
   1621                             proc.writeToParcel(out, now);
   1622                         }
   1623                     }
   1624                     final int NSRVS = pkgState.mServices.size();
   1625                     out.writeInt(NSRVS);
   1626                     for (int isvc=0; isvc<NSRVS; isvc++) {
   1627                         out.writeString(pkgState.mServices.keyAt(isvc));
   1628                         final ServiceState svc = pkgState.mServices.valueAt(isvc);
   1629                         writeCommonString(out, svc.mProcessName);
   1630                         svc.writeToParcel(out, now);
   1631                     }
   1632                 }
   1633             }
   1634         }
   1635 
   1636         mCommonStringToIndex = null;
   1637     }
   1638 
   1639     private boolean readCheckedInt(Parcel in, int val, String what) {
   1640         int got;
   1641         if ((got=in.readInt()) != val) {
   1642             mReadError = "bad " + what + ": " + got;
   1643             return false;
   1644         }
   1645         return true;
   1646     }
   1647 
   1648     static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
   1649         int pos = 0;
   1650         final int initialAvail = stream.available();
   1651         byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
   1652         while (true) {
   1653             int amt = stream.read(data, pos, data.length-pos);
   1654             if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
   1655                     + " of avail " + data.length);
   1656             if (amt < 0) {
   1657                 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
   1658                         + " len=" + data.length);
   1659                 outLen[0] = pos;
   1660                 return data;
   1661             }
   1662             pos += amt;
   1663             if (pos >= data.length) {
   1664                 byte[] newData = new byte[pos+16384];
   1665                 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
   1666                         + newData.length);
   1667                 System.arraycopy(data, 0, newData, 0, pos);
   1668                 data = newData;
   1669             }
   1670         }
   1671     }
   1672 
   1673     public void read(InputStream stream) {
   1674         try {
   1675             int[] len = new int[1];
   1676             byte[] raw = readFully(stream, len);
   1677             Parcel in = Parcel.obtain();
   1678             in.unmarshall(raw, 0, len[0]);
   1679             in.setDataPosition(0);
   1680             stream.close();
   1681 
   1682             readFromParcel(in);
   1683         } catch (IOException e) {
   1684             mReadError = "caught exception: " + e;
   1685         }
   1686     }
   1687 
   1688     public void readFromParcel(Parcel in) {
   1689         final boolean hadData = mPackages.getMap().size() > 0
   1690                 || mProcesses.getMap().size() > 0;
   1691         if (hadData) {
   1692             resetSafely();
   1693         }
   1694 
   1695         if (!readCheckedInt(in, MAGIC, "magic number")) {
   1696             return;
   1697         }
   1698         int version = in.readInt();
   1699         if (version != PARCEL_VERSION) {
   1700             mReadError = "bad version: " + version;
   1701             return;
   1702         }
   1703         if (!readCheckedInt(in, STATE_COUNT, "state count")) {
   1704             return;
   1705         }
   1706         if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
   1707             return;
   1708         }
   1709         if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
   1710             return;
   1711         }
   1712         if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) {
   1713             return;
   1714         }
   1715         if (!readCheckedInt(in, LONGS_SIZE, "longs size")) {
   1716             return;
   1717         }
   1718 
   1719         mIndexToCommonString = new ArrayList<String>();
   1720 
   1721         mTimePeriodStartClock = in.readLong();
   1722         buildTimePeriodStartClockStr();
   1723         mTimePeriodStartRealtime = in.readLong();
   1724         mTimePeriodEndRealtime = in.readLong();
   1725         mTimePeriodStartUptime = in.readLong();
   1726         mTimePeriodEndUptime = in.readLong();
   1727         mRuntime = in.readString();
   1728         mFlags = in.readInt();
   1729 
   1730         final int NLONGS = in.readInt();
   1731         final int NEXTLONG = in.readInt();
   1732         mLongs.clear();
   1733         for (int i=0; i<(NLONGS-1); i++) {
   1734             while (i >= mLongs.size()) {
   1735                 mLongs.add(new long[LONGS_SIZE]);
   1736             }
   1737             readCompactedLongArray(in, version, mLongs.get(i), LONGS_SIZE);
   1738         }
   1739         long[] longs = new long[LONGS_SIZE];
   1740         mNextLong = NEXTLONG;
   1741         readCompactedLongArray(in, version, longs, NEXTLONG);
   1742         mLongs.add(longs);
   1743 
   1744         readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length);
   1745 
   1746         mSysMemUsageTable = readTableFromParcel(in, TAG, "sys mem usage");
   1747         if (mSysMemUsageTable == BAD_TABLE) {
   1748             return;
   1749         }
   1750         mSysMemUsageTableSize = mSysMemUsageTable != null ? mSysMemUsageTable.length : 0;
   1751 
   1752         int NPROC = in.readInt();
   1753         if (NPROC < 0) {
   1754             mReadError = "bad process count: " + NPROC;
   1755             return;
   1756         }
   1757         while (NPROC > 0) {
   1758             NPROC--;
   1759             final String procName = readCommonString(in, version);
   1760             if (procName == null) {
   1761                 mReadError = "bad process name";
   1762                 return;
   1763             }
   1764             int NUID = in.readInt();
   1765             if (NUID < 0) {
   1766                 mReadError = "bad uid count: " + NUID;
   1767                 return;
   1768             }
   1769             while (NUID > 0) {
   1770                 NUID--;
   1771                 final int uid = in.readInt();
   1772                 if (uid < 0) {
   1773                     mReadError = "bad uid: " + uid;
   1774                     return;
   1775                 }
   1776                 final String pkgName = readCommonString(in, version);
   1777                 if (pkgName == null) {
   1778                     mReadError = "bad process package name";
   1779                     return;
   1780                 }
   1781                 final int vers = in.readInt();
   1782                 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
   1783                 if (proc != null) {
   1784                     if (!proc.readFromParcel(in, false)) {
   1785                         return;
   1786                     }
   1787                 } else {
   1788                     proc = new ProcessState(this, pkgName, uid, vers, procName);
   1789                     if (!proc.readFromParcel(in, true)) {
   1790                         return;
   1791                     }
   1792                 }
   1793                 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
   1794                         + " " + proc);
   1795                 mProcesses.put(procName, uid, proc);
   1796             }
   1797         }
   1798 
   1799         if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
   1800 
   1801         int NPKG = in.readInt();
   1802         if (NPKG < 0) {
   1803             mReadError = "bad package count: " + NPKG;
   1804             return;
   1805         }
   1806         while (NPKG > 0) {
   1807             NPKG--;
   1808             final String pkgName = readCommonString(in, version);
   1809             if (pkgName == null) {
   1810                 mReadError = "bad package name";
   1811                 return;
   1812             }
   1813             int NUID = in.readInt();
   1814             if (NUID < 0) {
   1815                 mReadError = "bad uid count: " + NUID;
   1816                 return;
   1817             }
   1818             while (NUID > 0) {
   1819                 NUID--;
   1820                 final int uid = in.readInt();
   1821                 if (uid < 0) {
   1822                     mReadError = "bad uid: " + uid;
   1823                     return;
   1824                 }
   1825                 int NVERS = in.readInt();
   1826                 if (NVERS < 0) {
   1827                     mReadError = "bad versions count: " + NVERS;
   1828                     return;
   1829                 }
   1830                 while (NVERS > 0) {
   1831                     NVERS--;
   1832                     final int vers = in.readInt();
   1833                     PackageState pkgState = new PackageState(pkgName, uid);
   1834                     SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid);
   1835                     if (vpkg == null) {
   1836                         vpkg = new SparseArray<PackageState>();
   1837                         mPackages.put(pkgName, uid, vpkg);
   1838                     }
   1839                     vpkg.put(vers, pkgState);
   1840                     int NPROCS = in.readInt();
   1841                     if (NPROCS < 0) {
   1842                         mReadError = "bad package process count: " + NPROCS;
   1843                         return;
   1844                     }
   1845                     while (NPROCS > 0) {
   1846                         NPROCS--;
   1847                         String procName = readCommonString(in, version);
   1848                         if (procName == null) {
   1849                             mReadError = "bad package process name";
   1850                             return;
   1851                         }
   1852                         int hasProc = in.readInt();
   1853                         if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
   1854                                 + " process " + procName + " hasProc=" + hasProc);
   1855                         ProcessState commonProc = mProcesses.get(procName, uid);
   1856                         if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
   1857                                 + ": " + commonProc);
   1858                         if (commonProc == null) {
   1859                             mReadError = "no common proc: " + procName;
   1860                             return;
   1861                         }
   1862                         if (hasProc != 0) {
   1863                             // The process for this package is unique to the package; we
   1864                             // need to load it.  We don't need to do anything about it if
   1865                             // it is not unique because if someone later looks for it
   1866                             // they will find and use it from the global procs.
   1867                             ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
   1868                             if (proc != null) {
   1869                                 if (!proc.readFromParcel(in, false)) {
   1870                                     return;
   1871                                 }
   1872                             } else {
   1873                                 proc = new ProcessState(commonProc, pkgName, uid, vers, procName,
   1874                                         0);
   1875                                 if (!proc.readFromParcel(in, true)) {
   1876                                     return;
   1877                                 }
   1878                             }
   1879                             if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
   1880                                     + procName + " " + uid + " " + proc);
   1881                             pkgState.mProcesses.put(procName, proc);
   1882                         } else {
   1883                             if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
   1884                                     + procName + " " + uid + " " + commonProc);
   1885                             pkgState.mProcesses.put(procName, commonProc);
   1886                         }
   1887                     }
   1888                     int NSRVS = in.readInt();
   1889                     if (NSRVS < 0) {
   1890                         mReadError = "bad package service count: " + NSRVS;
   1891                         return;
   1892                     }
   1893                     while (NSRVS > 0) {
   1894                         NSRVS--;
   1895                         String serviceName = in.readString();
   1896                         if (serviceName == null) {
   1897                             mReadError = "bad package service name";
   1898                             return;
   1899                         }
   1900                         String processName = version > 9 ? readCommonString(in, version) : null;
   1901                         ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
   1902                         if (serv == null) {
   1903                             serv = new ServiceState(this, pkgName, serviceName, processName, null);
   1904                         }
   1905                         if (!serv.readFromParcel(in)) {
   1906                             return;
   1907                         }
   1908                         if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
   1909                                 + serviceName + " " + uid + " " + serv);
   1910                         pkgState.mServices.put(serviceName, serv);
   1911                     }
   1912                 }
   1913             }
   1914         }
   1915 
   1916         mIndexToCommonString = null;
   1917 
   1918         if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
   1919     }
   1920 
   1921     int addLongData(int index, int type, int num) {
   1922         int off = allocLongData(num);
   1923         mAddLongTable = GrowingArrayUtils.insert(
   1924                 mAddLongTable != null ? mAddLongTable : EmptyArray.INT,
   1925                 mAddLongTableSize, index, type | off);
   1926         mAddLongTableSize++;
   1927         return off;
   1928     }
   1929 
   1930     int allocLongData(int num) {
   1931         int whichLongs = mLongs.size()-1;
   1932         long[] longs = mLongs.get(whichLongs);
   1933         if (mNextLong + num > longs.length) {
   1934             longs = new long[LONGS_SIZE];
   1935             mLongs.add(longs);
   1936             whichLongs++;
   1937             mNextLong = 0;
   1938         }
   1939         int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
   1940         mNextLong += num;
   1941         return off;
   1942     }
   1943 
   1944     boolean validateLongOffset(int off) {
   1945         int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK;
   1946         if (arr >= mLongs.size()) {
   1947             return false;
   1948         }
   1949         int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
   1950         if (idx >= LONGS_SIZE) {
   1951             return false;
   1952         }
   1953         if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off)
   1954                 + ": " + getLong(off, 0));
   1955         return true;
   1956     }
   1957 
   1958     static String printLongOffset(int off) {
   1959         StringBuilder sb = new StringBuilder(16);
   1960         sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   1961         sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK);
   1962         sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK);
   1963         return sb.toString();
   1964     }
   1965 
   1966     void setLong(int off, int index, long value) {
   1967         long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   1968         longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
   1969     }
   1970 
   1971     long getLong(int off, int index) {
   1972         long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   1973         return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
   1974     }
   1975 
   1976     static int binarySearch(int[] array, int size, int value) {
   1977         int lo = 0;
   1978         int hi = size - 1;
   1979 
   1980         while (lo <= hi) {
   1981             int mid = (lo + hi) >>> 1;
   1982             int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
   1983 
   1984             if (midVal < value) {
   1985                 lo = mid + 1;
   1986             } else if (midVal > value) {
   1987                 hi = mid - 1;
   1988             } else {
   1989                 return mid;  // value found
   1990             }
   1991         }
   1992         return ~lo;  // value not present
   1993     }
   1994 
   1995     public PackageState getPackageStateLocked(String packageName, int uid, int vers) {
   1996         SparseArray<PackageState> vpkg = mPackages.get(packageName, uid);
   1997         if (vpkg == null) {
   1998             vpkg = new SparseArray<PackageState>();
   1999             mPackages.put(packageName, uid, vpkg);
   2000         }
   2001         PackageState as = vpkg.get(vers);
   2002         if (as != null) {
   2003             return as;
   2004         }
   2005         as = new PackageState(packageName, uid);
   2006         vpkg.put(vers, as);
   2007         return as;
   2008     }
   2009 
   2010     public ProcessState getProcessStateLocked(String packageName, int uid, int vers,
   2011             String processName) {
   2012         final PackageState pkgState = getPackageStateLocked(packageName, uid, vers);
   2013         ProcessState ps = pkgState.mProcesses.get(processName);
   2014         if (ps != null) {
   2015             return ps;
   2016         }
   2017         ProcessState commonProc = mProcesses.get(processName, uid);
   2018         if (commonProc == null) {
   2019             commonProc = new ProcessState(this, packageName, uid, vers, processName);
   2020             mProcesses.put(processName, uid, commonProc);
   2021             if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
   2022         }
   2023         if (!commonProc.mMultiPackage) {
   2024             if (packageName.equals(commonProc.mPackage) && vers == commonProc.mVersion) {
   2025                 // This common process is not in use by multiple packages, and
   2026                 // is for the calling package, so we can just use it directly.
   2027                 ps = commonProc;
   2028                 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
   2029             } else {
   2030                 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
   2031                 // This common process has not been in use by multiple packages,
   2032                 // but it was created for a different package than the caller.
   2033                 // We need to convert it to a multi-package process.
   2034                 commonProc.mMultiPackage = true;
   2035                 // To do this, we need to make two new process states, one a copy
   2036                 // of the current state for the process under the original package
   2037                 // name, and the second a free new process state for it as the
   2038                 // new package name.
   2039                 long now = SystemClock.uptimeMillis();
   2040                 // First let's make a copy of the current process state and put
   2041                 // that under the now unique state for its original package name.
   2042                 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage,
   2043                         uid, commonProc.mVersion);
   2044                 if (commonPkgState != null) {
   2045                     ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
   2046                     if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
   2047                             + ": " + cloned);
   2048                     commonPkgState.mProcesses.put(commonProc.mName, cloned);
   2049                     // If this has active services, we need to update their process pointer
   2050                     // to point to the new package-specific process state.
   2051                     for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
   2052                         ServiceState ss = commonPkgState.mServices.valueAt(i);
   2053                         if (ss.mProc == commonProc) {
   2054                             if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
   2055                                     + ss);
   2056                             ss.mProc = cloned;
   2057                         } else if (DEBUG) {
   2058                             Slog.d(TAG, "GETPROC leaving proc of " + ss);
   2059                         }
   2060                     }
   2061                 } else {
   2062                     Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
   2063                             + "/" + uid + " for proc " + commonProc.mName);
   2064                 }
   2065                 // And now make a fresh new process state for the new package name.
   2066                 ps = new ProcessState(commonProc, packageName, uid, vers, processName, now);
   2067                 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
   2068             }
   2069         } else {
   2070             // The common process is for multiple packages, we need to create a
   2071             // separate object for the per-package data.
   2072             ps = new ProcessState(commonProc, packageName, uid, vers, processName,
   2073                     SystemClock.uptimeMillis());
   2074             if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
   2075         }
   2076         pkgState.mProcesses.put(processName, ps);
   2077         if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
   2078         return ps;
   2079     }
   2080 
   2081     public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid, int vers,
   2082             String processName, String className) {
   2083         final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers);
   2084         ProcessStats.ServiceState ss = as.mServices.get(className);
   2085         if (ss != null) {
   2086             if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
   2087             return ss;
   2088         }
   2089         final ProcessStats.ProcessState ps = processName != null
   2090                 ? getProcessStateLocked(packageName, uid, vers, processName) : null;
   2091         ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
   2092         as.mServices.put(className, ss);
   2093         if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
   2094         return ss;
   2095     }
   2096 
   2097     private void dumpProcessInternalLocked(PrintWriter pw, String prefix, ProcessState proc,
   2098             boolean dumpAll) {
   2099         if (dumpAll) {
   2100             pw.print(prefix); pw.print("myID=");
   2101                     pw.print(Integer.toHexString(System.identityHashCode(proc)));
   2102                     pw.print(" mCommonProcess=");
   2103                     pw.print(Integer.toHexString(System.identityHashCode(proc.mCommonProcess)));
   2104                     pw.print(" mPackage="); pw.println(proc.mPackage);
   2105             if (proc.mMultiPackage) {
   2106                 pw.print(prefix); pw.print("mMultiPackage="); pw.println(proc.mMultiPackage);
   2107             }
   2108             if (proc != proc.mCommonProcess) {
   2109                 pw.print(prefix); pw.print("Common Proc: "); pw.print(proc.mCommonProcess.mName);
   2110                         pw.print("/"); pw.print(proc.mCommonProcess.mUid);
   2111                         pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage);
   2112             }
   2113         }
   2114         if (proc.mActive) {
   2115             pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive);
   2116         }
   2117         if (proc.mDead) {
   2118             pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead);
   2119         }
   2120         if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) {
   2121             pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices);
   2122                     pw.print(" mNumStartedServices=");
   2123                     pw.println(proc.mNumStartedServices);
   2124         }
   2125     }
   2126 
   2127     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
   2128             boolean dumpAll, boolean activeOnly) {
   2129         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
   2130                 mStartTime, now);
   2131         boolean sepNeeded = false;
   2132         if (mSysMemUsageTable != null) {
   2133             pw.println("System memory usage:");
   2134             dumpSysMemUsage(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
   2135             sepNeeded = true;
   2136         }
   2137         ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   2138         boolean printedHeader = false;
   2139         for (int ip=0; ip<pkgMap.size(); ip++) {
   2140             final String pkgName = pkgMap.keyAt(ip);
   2141             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   2142             for (int iu=0; iu<uids.size(); iu++) {
   2143                 final int uid = uids.keyAt(iu);
   2144                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   2145                 for (int iv=0; iv<vpkgs.size(); iv++) {
   2146                     final int vers = vpkgs.keyAt(iv);
   2147                     final PackageState pkgState = vpkgs.valueAt(iv);
   2148                     final int NPROCS = pkgState.mProcesses.size();
   2149                     final int NSRVS = pkgState.mServices.size();
   2150                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
   2151                     if (!pkgMatch) {
   2152                         boolean procMatch = false;
   2153                         for (int iproc=0; iproc<NPROCS; iproc++) {
   2154                             ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2155                             if (reqPackage.equals(proc.mName)) {
   2156                                 procMatch = true;
   2157                                 break;
   2158                             }
   2159                         }
   2160                         if (!procMatch) {
   2161                             continue;
   2162                         }
   2163                     }
   2164                     if (NPROCS > 0 || NSRVS > 0) {
   2165                         if (!printedHeader) {
   2166                             if (sepNeeded) pw.println();
   2167                             pw.println("Per-Package Stats:");
   2168                             printedHeader = true;
   2169                             sepNeeded = true;
   2170                         }
   2171                         pw.print("  * "); pw.print(pkgName); pw.print(" / ");
   2172                                 UserHandle.formatUid(pw, uid); pw.print(" / v");
   2173                                 pw.print(vers); pw.println(":");
   2174                     }
   2175                     if (!dumpSummary || dumpAll) {
   2176                         for (int iproc=0; iproc<NPROCS; iproc++) {
   2177                             ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2178                             if (!pkgMatch && !reqPackage.equals(proc.mName)) {
   2179                                 continue;
   2180                             }
   2181                             if (activeOnly && !proc.isInUse()) {
   2182                                 pw.print("      (Not active: ");
   2183                                         pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
   2184                                 continue;
   2185                             }
   2186                             pw.print("      Process ");
   2187                             pw.print(pkgState.mProcesses.keyAt(iproc));
   2188                             if (proc.mCommonProcess.mMultiPackage) {
   2189                                 pw.print(" (multi, ");
   2190                             } else {
   2191                                 pw.print(" (unique, ");
   2192                             }
   2193                             pw.print(proc.mDurationsTableSize);
   2194                             pw.print(" entries)");
   2195                             pw.println(":");
   2196                             dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2197                                     ALL_PROC_STATES, now);
   2198                             dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2199                                     ALL_PROC_STATES);
   2200                             dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
   2201                         }
   2202                     } else {
   2203                         ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
   2204                         for (int iproc=0; iproc<NPROCS; iproc++) {
   2205                             ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2206                             if (!pkgMatch && !reqPackage.equals(proc.mName)) {
   2207                                 continue;
   2208                             }
   2209                             if (activeOnly && !proc.isInUse()) {
   2210                                 continue;
   2211                             }
   2212                             procs.add(proc);
   2213                         }
   2214                         dumpProcessSummaryLocked(pw, "      ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2215                                 NON_CACHED_PROC_STATES, false, now, totalTime);
   2216                     }
   2217                     for (int isvc=0; isvc<NSRVS; isvc++) {
   2218                         ServiceState svc = pkgState.mServices.valueAt(isvc);
   2219                         if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
   2220                             continue;
   2221                         }
   2222                         if (activeOnly && !svc.isInUse()) {
   2223                             pw.print("      (Not active: ");
   2224                                     pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
   2225                             continue;
   2226                         }
   2227                         if (dumpAll) {
   2228                             pw.print("      Service ");
   2229                         } else {
   2230                             pw.print("      * ");
   2231                         }
   2232                         pw.print(pkgState.mServices.keyAt(isvc));
   2233                         pw.println(":");
   2234                         pw.print("        Process: "); pw.println(svc.mProcessName);
   2235                         dumpServiceStats(pw, "        ", "          ", "    ", "Running", svc,
   2236                                 svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
   2237                                 svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll);
   2238                         dumpServiceStats(pw, "        ", "          ", "    ", "Started", svc,
   2239                                 svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState,
   2240                                 svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll);
   2241                         dumpServiceStats(pw, "        ", "          ", "      ", "Bound", svc,
   2242                                 svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState,
   2243                                 svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll);
   2244                         dumpServiceStats(pw, "        ", "          ", "  ", "Executing", svc,
   2245                                 svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
   2246                                 svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
   2247                         if (dumpAll) {
   2248                             if (svc.mOwner != null) {
   2249                                 pw.print("        mOwner="); pw.println(svc.mOwner);
   2250                             }
   2251                             if (svc.mStarted || svc.mRestarting) {
   2252                                 pw.print("        mStarted="); pw.print(svc.mStarted);
   2253                                 pw.print(" mRestarting="); pw.println(svc.mRestarting);
   2254                             }
   2255                         }
   2256                     }
   2257                 }
   2258             }
   2259         }
   2260 
   2261         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   2262         printedHeader = false;
   2263         int numShownProcs = 0, numTotalProcs = 0;
   2264         for (int ip=0; ip<procMap.size(); ip++) {
   2265             String procName = procMap.keyAt(ip);
   2266             SparseArray<ProcessState> uids = procMap.valueAt(ip);
   2267             for (int iu=0; iu<uids.size(); iu++) {
   2268                 int uid = uids.keyAt(iu);
   2269                 numTotalProcs++;
   2270                 ProcessState proc = uids.valueAt(iu);
   2271                 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
   2272                         && proc.mPssTableSize == 0) {
   2273                     continue;
   2274                 }
   2275                 if (!proc.mMultiPackage) {
   2276                     continue;
   2277                 }
   2278                 if (reqPackage != null && !reqPackage.equals(procName)
   2279                         && !reqPackage.equals(proc.mPackage)) {
   2280                     continue;
   2281                 }
   2282                 numShownProcs++;
   2283                 if (sepNeeded) {
   2284                     pw.println();
   2285                 }
   2286                 sepNeeded = true;
   2287                 if (!printedHeader) {
   2288                     pw.println("Multi-Package Common Processes:");
   2289                     printedHeader = true;
   2290                 }
   2291                 if (activeOnly && !proc.isInUse()) {
   2292                     pw.print("      (Not active: "); pw.print(procName); pw.println(")");
   2293                     continue;
   2294                 }
   2295                 pw.print("  * "); pw.print(procName); pw.print(" / ");
   2296                         UserHandle.formatUid(pw, uid);
   2297                         pw.print(" ("); pw.print(proc.mDurationsTableSize);
   2298                         pw.print(" entries)"); pw.println(":");
   2299                 dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2300                         ALL_PROC_STATES, now);
   2301                 dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2302                         ALL_PROC_STATES);
   2303                 dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
   2304             }
   2305         }
   2306         if (dumpAll) {
   2307             pw.println();
   2308             pw.print("  Total procs: "); pw.print(numShownProcs);
   2309                     pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
   2310         }
   2311 
   2312         if (sepNeeded) {
   2313             pw.println();
   2314         }
   2315         if (dumpSummary) {
   2316             pw.println("Summary:");
   2317             dumpSummaryLocked(pw, reqPackage, now, activeOnly);
   2318         } else {
   2319             dumpTotalsLocked(pw, now);
   2320         }
   2321 
   2322         if (dumpAll) {
   2323             pw.println();
   2324             pw.println("Internal state:");
   2325             pw.print("  Num long arrays: "); pw.println(mLongs.size());
   2326             pw.print("  Next long entry: "); pw.println(mNextLong);
   2327             pw.print("  mRunning="); pw.println(mRunning);
   2328         }
   2329     }
   2330 
   2331     public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
   2332             int serviceType, int curState, long curStartTime, long now) {
   2333         long totalTime = 0;
   2334         int printedScreen = -1;
   2335         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
   2336             int printedMem = -1;
   2337             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
   2338                 int state = imem+iscreen;
   2339                 long time = service.getDuration(serviceType, curState, curStartTime,
   2340                         state, now);
   2341                 String running = "";
   2342                 if (curState == state && pw != null) {
   2343                     running = " (running)";
   2344                 }
   2345                 if (time != 0) {
   2346                     if (pw != null) {
   2347                         pw.print(prefix);
   2348                         printScreenLabel(pw, printedScreen != iscreen
   2349                                 ? iscreen : STATE_NOTHING);
   2350                         printedScreen = iscreen;
   2351                         printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
   2352                         printedMem = imem;
   2353                         pw.print(": ");
   2354                         TimeUtils.formatDuration(time, pw); pw.println(running);
   2355                     }
   2356                     totalTime += time;
   2357                 }
   2358             }
   2359         }
   2360         if (totalTime != 0 && pw != null) {
   2361             pw.print(prefix);
   2362             pw.print("    TOTAL: ");
   2363             TimeUtils.formatDuration(totalTime, pw);
   2364             pw.println();
   2365         }
   2366         return totalTime;
   2367     }
   2368 
   2369     void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner,
   2370             String headerPrefix, String header, ServiceState service,
   2371             int count, int serviceType, int state, long startTime, long now, long totalTime,
   2372             boolean dumpAll) {
   2373         if (count != 0) {
   2374             if (dumpAll) {
   2375                 pw.print(prefix); pw.print(header);
   2376                 pw.print(" op count "); pw.print(count); pw.println(":");
   2377                 dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime,
   2378                         now);
   2379             } else {
   2380                 long myTime = dumpSingleServiceTime(null, null, service, serviceType, state,
   2381                         startTime, now);
   2382                 pw.print(prefix); pw.print(headerPrefix); pw.print(header);
   2383                 pw.print(" count "); pw.print(count);
   2384                 pw.print(" / time ");
   2385                 printPercent(pw, (double)myTime/(double)totalTime);
   2386                 pw.println();
   2387             }
   2388         }
   2389     }
   2390 
   2391     public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
   2392         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
   2393                 mStartTime, now);
   2394         dumpFilteredSummaryLocked(pw, null, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2395                 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
   2396         pw.println();
   2397         dumpTotalsLocked(pw, now);
   2398     }
   2399 
   2400     long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight,
   2401             long totalTime, long curTotalMem, int samples) {
   2402         if (memWeight != 0) {
   2403             long mem = (long)(memWeight * 1024 / totalTime);
   2404             pw.print(prefix);
   2405             pw.print(label);
   2406             pw.print(": ");
   2407             DebugUtils.printSizeValue(pw, mem);
   2408             pw.print(" (");
   2409             pw.print(samples);
   2410             pw.print(" samples)");
   2411             pw.println();
   2412             return curTotalMem + mem;
   2413         }
   2414         return curTotalMem;
   2415     }
   2416 
   2417     void dumpTotalsLocked(PrintWriter pw, long now) {
   2418         pw.println("Run time Stats:");
   2419         dumpSingleTime(pw, "  ", mMemFactorDurations, mMemFactor, mStartTime, now);
   2420         pw.println();
   2421         pw.println("Memory usage:");
   2422         TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
   2423                 ALL_MEM_ADJ);
   2424         computeTotalMemoryUse(totalMem, now);
   2425         long totalPss = 0;
   2426         totalPss = printMemoryCategory(pw, "  ", "Kernel ", totalMem.sysMemKernelWeight,
   2427                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2428         totalPss = printMemoryCategory(pw, "  ", "Native ", totalMem.sysMemNativeWeight,
   2429                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2430         for (int i=0; i<STATE_COUNT; i++) {
   2431             // Skip restarting service state -- that is not actually a running process.
   2432             if (i != STATE_SERVICE_RESTARTING) {
   2433                 totalPss = printMemoryCategory(pw, "  ", STATE_NAMES[i],
   2434                         totalMem.processStateWeight[i], totalMem.totalTime, totalPss,
   2435                         totalMem.processStateSamples[i]);
   2436             }
   2437         }
   2438         totalPss = printMemoryCategory(pw, "  ", "Cached ", totalMem.sysMemCachedWeight,
   2439                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2440         totalPss = printMemoryCategory(pw, "  ", "Free   ", totalMem.sysMemFreeWeight,
   2441                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2442         totalPss = printMemoryCategory(pw, "  ", "Z-Ram  ", totalMem.sysMemZRamWeight,
   2443                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2444         pw.print("  TOTAL  : ");
   2445         DebugUtils.printSizeValue(pw, totalPss);
   2446         pw.println();
   2447         printMemoryCategory(pw, "  ", STATE_NAMES[STATE_SERVICE_RESTARTING],
   2448                 totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss,
   2449                 totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
   2450         pw.println();
   2451         pw.print("          Start time: ");
   2452         pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
   2453         pw.println();
   2454         pw.print("  Total elapsed time: ");
   2455         TimeUtils.formatDuration(
   2456                 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
   2457                         - mTimePeriodStartRealtime, pw);
   2458         boolean partial = true;
   2459         if ((mFlags&FLAG_SHUTDOWN) != 0) {
   2460             pw.print(" (shutdown)");
   2461             partial = false;
   2462         }
   2463         if ((mFlags&FLAG_SYSPROPS) != 0) {
   2464             pw.print(" (sysprops)");
   2465             partial = false;
   2466         }
   2467         if ((mFlags&FLAG_COMPLETE) != 0) {
   2468             pw.print(" (complete)");
   2469             partial = false;
   2470         }
   2471         if (partial) {
   2472             pw.print(" (partial)");
   2473         }
   2474         pw.print(' ');
   2475         pw.print(mRuntime);
   2476         pw.println();
   2477     }
   2478 
   2479     void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
   2480             int[] screenStates, int[] memStates, int[] procStates,
   2481             int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
   2482         ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
   2483                 procStates, sortProcStates, now, reqPackage, activeOnly);
   2484         if (procs.size() > 0) {
   2485             if (header != null) {
   2486                 pw.println();
   2487                 pw.println(header);
   2488             }
   2489             dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
   2490                     sortProcStates, true, now, totalTime);
   2491         }
   2492     }
   2493 
   2494     public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
   2495             int[] procStates, int sortProcStates[], long now, String reqPackage,
   2496             boolean activeOnly) {
   2497         final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
   2498         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   2499         for (int ip=0; ip<pkgMap.size(); ip++) {
   2500             final String pkgName = pkgMap.keyAt(ip);
   2501             final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip);
   2502             for (int iu=0; iu<procs.size(); iu++) {
   2503                 final SparseArray<PackageState> vpkgs = procs.valueAt(iu);
   2504                 final int NVERS = vpkgs.size();
   2505                 for (int iv=0; iv<NVERS; iv++) {
   2506                     final PackageState state = vpkgs.valueAt(iv);
   2507                     final int NPROCS = state.mProcesses.size();
   2508                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
   2509                     for (int iproc=0; iproc<NPROCS; iproc++) {
   2510                         final ProcessState proc = state.mProcesses.valueAt(iproc);
   2511                         if (!pkgMatch && !reqPackage.equals(proc.mName)) {
   2512                             continue;
   2513                         }
   2514                         if (activeOnly && !proc.isInUse()) {
   2515                             continue;
   2516                         }
   2517                         foundProcs.add(proc.mCommonProcess);
   2518                     }
   2519                 }
   2520             }
   2521         }
   2522         ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
   2523         for (int i=0; i<foundProcs.size(); i++) {
   2524             ProcessState proc = foundProcs.valueAt(i);
   2525             if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
   2526                 outProcs.add(proc);
   2527                 if (procStates != sortProcStates) {
   2528                     computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
   2529                 }
   2530             }
   2531         }
   2532         Collections.sort(outProcs, new Comparator<ProcessState>() {
   2533             @Override
   2534             public int compare(ProcessState lhs, ProcessState rhs) {
   2535                 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
   2536                     return -1;
   2537                 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
   2538                     return 1;
   2539                 }
   2540                 return 0;
   2541             }
   2542         });
   2543         return outProcs;
   2544     }
   2545 
   2546     String collapseString(String pkgName, String itemName) {
   2547         if (itemName.startsWith(pkgName)) {
   2548             final int ITEMLEN = itemName.length();
   2549             final int PKGLEN = pkgName.length();
   2550             if (ITEMLEN == PKGLEN) {
   2551                 return "";
   2552             } else if (ITEMLEN >= PKGLEN) {
   2553                 if (itemName.charAt(PKGLEN) == '.') {
   2554                     return itemName.substring(PKGLEN);
   2555                 }
   2556             }
   2557         }
   2558         return itemName;
   2559     }
   2560 
   2561     public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
   2562         final long now = SystemClock.uptimeMillis();
   2563         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   2564         pw.println("vers,5");
   2565         pw.print("period,"); pw.print(mTimePeriodStartClockStr);
   2566         pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
   2567         pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
   2568         boolean partial = true;
   2569         if ((mFlags&FLAG_SHUTDOWN) != 0) {
   2570             pw.print(",shutdown");
   2571             partial = false;
   2572         }
   2573         if ((mFlags&FLAG_SYSPROPS) != 0) {
   2574             pw.print(",sysprops");
   2575             partial = false;
   2576         }
   2577         if ((mFlags&FLAG_COMPLETE) != 0) {
   2578             pw.print(",complete");
   2579             partial = false;
   2580         }
   2581         if (partial) {
   2582             pw.print(",partial");
   2583         }
   2584         pw.println();
   2585         pw.print("config,"); pw.println(mRuntime);
   2586         for (int ip=0; ip<pkgMap.size(); ip++) {
   2587             final String pkgName = pkgMap.keyAt(ip);
   2588             if (reqPackage != null && !reqPackage.equals(pkgName)) {
   2589                 continue;
   2590             }
   2591             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   2592             for (int iu=0; iu<uids.size(); iu++) {
   2593                 final int uid = uids.keyAt(iu);
   2594                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   2595                 for (int iv=0; iv<vpkgs.size(); iv++) {
   2596                     final int vers = vpkgs.keyAt(iv);
   2597                     final PackageState pkgState = vpkgs.valueAt(iv);
   2598                     final int NPROCS = pkgState.mProcesses.size();
   2599                     final int NSRVS = pkgState.mServices.size();
   2600                     for (int iproc=0; iproc<NPROCS; iproc++) {
   2601                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2602                         pw.print("pkgproc,");
   2603                         pw.print(pkgName);
   2604                         pw.print(",");
   2605                         pw.print(uid);
   2606                         pw.print(",");
   2607                         pw.print(vers);
   2608                         pw.print(",");
   2609                         pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
   2610                         dumpAllProcessStateCheckin(pw, proc, now);
   2611                         pw.println();
   2612                         if (proc.mPssTableSize > 0) {
   2613                             pw.print("pkgpss,");
   2614                             pw.print(pkgName);
   2615                             pw.print(",");
   2616                             pw.print(uid);
   2617                             pw.print(",");
   2618                             pw.print(vers);
   2619                             pw.print(",");
   2620                             pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
   2621                             dumpAllProcessPssCheckin(pw, proc);
   2622                             pw.println();
   2623                         }
   2624                         if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0
   2625                                 || proc.mNumCachedKill > 0) {
   2626                             pw.print("pkgkills,");
   2627                             pw.print(pkgName);
   2628                             pw.print(",");
   2629                             pw.print(uid);
   2630                             pw.print(",");
   2631                             pw.print(vers);
   2632                             pw.print(",");
   2633                             pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
   2634                             pw.print(",");
   2635                             pw.print(proc.mNumExcessiveWake);
   2636                             pw.print(",");
   2637                             pw.print(proc.mNumExcessiveCpu);
   2638                             pw.print(",");
   2639                             pw.print(proc.mNumCachedKill);
   2640                             pw.print(",");
   2641                             pw.print(proc.mMinCachedKillPss);
   2642                             pw.print(":");
   2643                             pw.print(proc.mAvgCachedKillPss);
   2644                             pw.print(":");
   2645                             pw.print(proc.mMaxCachedKillPss);
   2646                             pw.println();
   2647                         }
   2648                     }
   2649                     for (int isvc=0; isvc<NSRVS; isvc++) {
   2650                         String serviceName = collapseString(pkgName,
   2651                                 pkgState.mServices.keyAt(isvc));
   2652                         ServiceState svc = pkgState.mServices.valueAt(isvc);
   2653                         dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, vers, serviceName,
   2654                                 svc, ServiceState.SERVICE_RUN, svc.mRunCount,
   2655                                 svc.mRunState, svc.mRunStartTime, now);
   2656                         dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName,
   2657                                 svc, ServiceState.SERVICE_STARTED, svc.mStartedCount,
   2658                                 svc.mStartedState, svc.mStartedStartTime, now);
   2659                         dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName,
   2660                                 svc, ServiceState.SERVICE_BOUND, svc.mBoundCount,
   2661                                 svc.mBoundState, svc.mBoundStartTime, now);
   2662                         dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName,
   2663                                 svc, ServiceState.SERVICE_EXEC, svc.mExecCount,
   2664                                 svc.mExecState, svc.mExecStartTime, now);
   2665                     }
   2666                 }
   2667             }
   2668         }
   2669 
   2670         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   2671         for (int ip=0; ip<procMap.size(); ip++) {
   2672             String procName = procMap.keyAt(ip);
   2673             SparseArray<ProcessState> uids = procMap.valueAt(ip);
   2674             for (int iu=0; iu<uids.size(); iu++) {
   2675                 int uid = uids.keyAt(iu);
   2676                 ProcessState procState = uids.valueAt(iu);
   2677                 if (procState.mDurationsTableSize > 0) {
   2678                     pw.print("proc,");
   2679                     pw.print(procName);
   2680                     pw.print(",");
   2681                     pw.print(uid);
   2682                     dumpAllProcessStateCheckin(pw, procState, now);
   2683                     pw.println();
   2684                 }
   2685                 if (procState.mPssTableSize > 0) {
   2686                     pw.print("pss,");
   2687                     pw.print(procName);
   2688                     pw.print(",");
   2689                     pw.print(uid);
   2690                     dumpAllProcessPssCheckin(pw, procState);
   2691                     pw.println();
   2692                 }
   2693                 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0
   2694                         || procState.mNumCachedKill > 0) {
   2695                     pw.print("kills,");
   2696                     pw.print(procName);
   2697                     pw.print(",");
   2698                     pw.print(uid);
   2699                     pw.print(",");
   2700                     pw.print(procState.mNumExcessiveWake);
   2701                     pw.print(",");
   2702                     pw.print(procState.mNumExcessiveCpu);
   2703                     pw.print(",");
   2704                     pw.print(procState.mNumCachedKill);
   2705                     pw.print(",");
   2706                     pw.print(procState.mMinCachedKillPss);
   2707                     pw.print(":");
   2708                     pw.print(procState.mAvgCachedKillPss);
   2709                     pw.print(":");
   2710                     pw.print(procState.mMaxCachedKillPss);
   2711                     pw.println();
   2712                 }
   2713             }
   2714         }
   2715         pw.print("total");
   2716         dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor,
   2717                 mStartTime, now);
   2718         pw.println();
   2719         if (mSysMemUsageTable != null) {
   2720             pw.print("sysmemusage");
   2721             for (int i=0; i<mSysMemUsageTableSize; i++) {
   2722                 int off = mSysMemUsageTable[i];
   2723                 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2724                 pw.print(",");
   2725                 printProcStateTag(pw, type);
   2726                 for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) {
   2727                     if (j > SYS_MEM_USAGE_CACHED_MINIMUM) {
   2728                         pw.print(":");
   2729                     }
   2730                     pw.print(getLong(off, j));
   2731                 }
   2732             }
   2733         }
   2734         pw.println();
   2735         TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
   2736                 ALL_MEM_ADJ);
   2737         computeTotalMemoryUse(totalMem, now);
   2738         pw.print("weights,");
   2739         pw.print(totalMem.totalTime);
   2740         pw.print(",");
   2741         pw.print(totalMem.sysMemCachedWeight);
   2742         pw.print(":");
   2743         pw.print(totalMem.sysMemSamples);
   2744         pw.print(",");
   2745         pw.print(totalMem.sysMemFreeWeight);
   2746         pw.print(":");
   2747         pw.print(totalMem.sysMemSamples);
   2748         pw.print(",");
   2749         pw.print(totalMem.sysMemZRamWeight);
   2750         pw.print(":");
   2751         pw.print(totalMem.sysMemSamples);
   2752         pw.print(",");
   2753         pw.print(totalMem.sysMemKernelWeight);
   2754         pw.print(":");
   2755         pw.print(totalMem.sysMemSamples);
   2756         pw.print(",");
   2757         pw.print(totalMem.sysMemNativeWeight);
   2758         pw.print(":");
   2759         pw.print(totalMem.sysMemSamples);
   2760         for (int i=0; i<STATE_COUNT; i++) {
   2761             pw.print(",");
   2762             pw.print(totalMem.processStateWeight[i]);
   2763             pw.print(":");
   2764             pw.print(totalMem.processStateSamples[i]);
   2765         }
   2766         pw.println();
   2767     }
   2768 
   2769     public static class DurationsTable {
   2770         public final ProcessStats mStats;
   2771         public final String mName;
   2772         public int[] mDurationsTable;
   2773         public int mDurationsTableSize;
   2774 
   2775         public DurationsTable(ProcessStats stats, String name) {
   2776             mStats = stats;
   2777             mName = name;
   2778         }
   2779 
   2780         void copyDurationsTo(DurationsTable other) {
   2781             if (mDurationsTable != null) {
   2782                 mStats.mAddLongTable = new int[mDurationsTable.length];
   2783                 mStats.mAddLongTableSize = 0;
   2784                 for (int i=0; i<mDurationsTableSize; i++) {
   2785                     int origEnt = mDurationsTable[i];
   2786                     int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2787                     int newOff = mStats.addLongData(i, type, 1);
   2788                     mStats.mAddLongTable[i] = newOff | type;
   2789                     mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0));
   2790                 }
   2791                 other.mDurationsTable = mStats.mAddLongTable;
   2792                 other.mDurationsTableSize = mStats.mAddLongTableSize;
   2793             } else {
   2794                 other.mDurationsTable = null;
   2795                 other.mDurationsTableSize = 0;
   2796             }
   2797         }
   2798 
   2799         void addDurations(DurationsTable other) {
   2800             for (int i=0; i<other.mDurationsTableSize; i++) {
   2801                 int ent = other.mDurationsTable[i];
   2802                 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2803                 if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
   2804                         + other.mStats.getLong(ent, 0));
   2805                 addDuration(state, other.mStats.getLong(ent, 0));
   2806             }
   2807         }
   2808 
   2809         void resetDurationsSafely() {
   2810             mDurationsTable = null;
   2811             mDurationsTableSize = 0;
   2812         }
   2813 
   2814         void writeDurationsToParcel(Parcel out) {
   2815             out.writeInt(mDurationsTableSize);
   2816             for (int i=0; i<mDurationsTableSize; i++) {
   2817                 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
   2818                         + printLongOffset(mDurationsTable[i]));
   2819                 out.writeInt(mDurationsTable[i]);
   2820             }
   2821         }
   2822 
   2823         boolean readDurationsFromParcel(Parcel in) {
   2824             mDurationsTable = mStats.readTableFromParcel(in, mName, "durations");
   2825             if (mDurationsTable == BAD_TABLE) {
   2826                 return false;
   2827             }
   2828             mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
   2829             return true;
   2830         }
   2831 
   2832         void addDuration(int state, long dur) {
   2833             int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
   2834             int off;
   2835             if (idx >= 0) {
   2836                 off = mDurationsTable[idx];
   2837             } else {
   2838                 mStats.mAddLongTable = mDurationsTable;
   2839                 mStats.mAddLongTableSize = mDurationsTableSize;
   2840                 off = mStats.addLongData(~idx, state, 1);
   2841                 mDurationsTable = mStats.mAddLongTable;
   2842                 mDurationsTableSize = mStats.mAddLongTableSize;
   2843             }
   2844             long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   2845             if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
   2846                     + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
   2847             longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
   2848         }
   2849 
   2850         long getDuration(int state, long now) {
   2851             int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
   2852             return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
   2853         }
   2854     }
   2855 
   2856     final public static class ProcessStateHolder {
   2857         public final int appVersion;
   2858         public ProcessStats.ProcessState state;
   2859 
   2860         public ProcessStateHolder(int _appVersion) {
   2861             appVersion = _appVersion;
   2862         }
   2863     }
   2864 
   2865     public static final class ProcessState extends DurationsTable {
   2866         public ProcessState mCommonProcess;
   2867         public final String mPackage;
   2868         public final int mUid;
   2869         public final int mVersion;
   2870 
   2871         //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
   2872         int mCurState = STATE_NOTHING;
   2873         long mStartTime;
   2874 
   2875         int mLastPssState = STATE_NOTHING;
   2876         long mLastPssTime;
   2877         int[] mPssTable;
   2878         int mPssTableSize;
   2879 
   2880         boolean mActive;
   2881         int mNumActiveServices;
   2882         int mNumStartedServices;
   2883 
   2884         int mNumExcessiveWake;
   2885         int mNumExcessiveCpu;
   2886 
   2887         int mNumCachedKill;
   2888         long mMinCachedKillPss;
   2889         long mAvgCachedKillPss;
   2890         long mMaxCachedKillPss;
   2891 
   2892         boolean mMultiPackage;
   2893         boolean mDead;
   2894 
   2895         public long mTmpTotalTime;
   2896         int mTmpNumInUse;
   2897         ProcessState mTmpFoundSubProc;
   2898 
   2899         /**
   2900          * Create a new top-level process state, for the initial case where there is only
   2901          * a single package running in a process.  The initial state is not running.
   2902          */
   2903         public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) {
   2904             super(processStats, name);
   2905             mCommonProcess = this;
   2906             mPackage = pkg;
   2907             mUid = uid;
   2908             mVersion = vers;
   2909         }
   2910 
   2911         /**
   2912          * Create a new per-package process state for an existing top-level process
   2913          * state.  The current running state of the top-level process is also copied,
   2914          * marked as started running at 'now'.
   2915          */
   2916         public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name,
   2917                 long now) {
   2918             super(commonProcess.mStats, name);
   2919             mCommonProcess = commonProcess;
   2920             mPackage = pkg;
   2921             mUid = uid;
   2922             mVersion = vers;
   2923             mCurState = commonProcess.mCurState;
   2924             mStartTime = now;
   2925         }
   2926 
   2927         ProcessState clone(String pkg, long now) {
   2928             ProcessState pnew = new ProcessState(this, pkg, mUid, mVersion, mName, now);
   2929             copyDurationsTo(pnew);
   2930             if (mPssTable != null) {
   2931                 mStats.mAddLongTable = new int[mPssTable.length];
   2932                 mStats.mAddLongTableSize = 0;
   2933                 for (int i=0; i<mPssTableSize; i++) {
   2934                     int origEnt = mPssTable[i];
   2935                     int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2936                     int newOff = mStats.addLongData(i, type, PSS_COUNT);
   2937                     mStats.mAddLongTable[i] = newOff | type;
   2938                     for (int j=0; j<PSS_COUNT; j++) {
   2939                         mStats.setLong(newOff, j, mStats.getLong(origEnt, j));
   2940                     }
   2941                 }
   2942                 pnew.mPssTable = mStats.mAddLongTable;
   2943                 pnew.mPssTableSize = mStats.mAddLongTableSize;
   2944             }
   2945             pnew.mNumExcessiveWake = mNumExcessiveWake;
   2946             pnew.mNumExcessiveCpu = mNumExcessiveCpu;
   2947             pnew.mNumCachedKill = mNumCachedKill;
   2948             pnew.mMinCachedKillPss = mMinCachedKillPss;
   2949             pnew.mAvgCachedKillPss = mAvgCachedKillPss;
   2950             pnew.mMaxCachedKillPss = mMaxCachedKillPss;
   2951             pnew.mActive = mActive;
   2952             pnew.mNumActiveServices = mNumActiveServices;
   2953             pnew.mNumStartedServices = mNumStartedServices;
   2954             return pnew;
   2955         }
   2956 
   2957         void add(ProcessState other) {
   2958             addDurations(other);
   2959             for (int i=0; i<other.mPssTableSize; i++) {
   2960                 int ent = other.mPssTable[i];
   2961                 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2962                 addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
   2963                         other.mStats.getLong(ent, PSS_MINIMUM),
   2964                         other.mStats.getLong(ent, PSS_AVERAGE),
   2965                         other.mStats.getLong(ent, PSS_MAXIMUM),
   2966                         other.mStats.getLong(ent, PSS_USS_MINIMUM),
   2967                         other.mStats.getLong(ent, PSS_USS_AVERAGE),
   2968                         other.mStats.getLong(ent, PSS_USS_MAXIMUM));
   2969             }
   2970             mNumExcessiveWake += other.mNumExcessiveWake;
   2971             mNumExcessiveCpu += other.mNumExcessiveCpu;
   2972             if (other.mNumCachedKill > 0) {
   2973                 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
   2974                         other.mAvgCachedKillPss, other.mMaxCachedKillPss);
   2975             }
   2976         }
   2977 
   2978         void resetSafely(long now) {
   2979             resetDurationsSafely();
   2980             mStartTime = now;
   2981             mLastPssState = STATE_NOTHING;
   2982             mLastPssTime = 0;
   2983             mPssTable = null;
   2984             mPssTableSize = 0;
   2985             mNumExcessiveWake = 0;
   2986             mNumExcessiveCpu = 0;
   2987             mNumCachedKill = 0;
   2988             mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
   2989         }
   2990 
   2991         void makeDead() {
   2992             mDead = true;
   2993         }
   2994 
   2995         private void ensureNotDead() {
   2996             if (!mDead) {
   2997                 return;
   2998             }
   2999             Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
   3000                     + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
   3001         }
   3002 
   3003         void writeToParcel(Parcel out, long now) {
   3004             out.writeInt(mMultiPackage ? 1 : 0);
   3005             writeDurationsToParcel(out);
   3006             out.writeInt(mPssTableSize);
   3007             for (int i=0; i<mPssTableSize; i++) {
   3008                 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
   3009                         + printLongOffset(mPssTable[i]));
   3010                 out.writeInt(mPssTable[i]);
   3011             }
   3012             out.writeInt(mNumExcessiveWake);
   3013             out.writeInt(mNumExcessiveCpu);
   3014             out.writeInt(mNumCachedKill);
   3015             if (mNumCachedKill > 0) {
   3016                 out.writeLong(mMinCachedKillPss);
   3017                 out.writeLong(mAvgCachedKillPss);
   3018                 out.writeLong(mMaxCachedKillPss);
   3019             }
   3020         }
   3021 
   3022         boolean readFromParcel(Parcel in, boolean fully) {
   3023             boolean multiPackage = in.readInt() != 0;
   3024             if (fully) {
   3025                 mMultiPackage = multiPackage;
   3026             }
   3027             if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
   3028             if (!readDurationsFromParcel(in)) {
   3029                 return false;
   3030             }
   3031             if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
   3032             mPssTable = mStats.readTableFromParcel(in, mName, "pss");
   3033             if (mPssTable == BAD_TABLE) {
   3034                 return false;
   3035             }
   3036             mPssTableSize = mPssTable != null ? mPssTable.length : 0;
   3037             mNumExcessiveWake = in.readInt();
   3038             mNumExcessiveCpu = in.readInt();
   3039             mNumCachedKill = in.readInt();
   3040             if (mNumCachedKill > 0) {
   3041                 mMinCachedKillPss = in.readLong();
   3042                 mAvgCachedKillPss = in.readLong();
   3043                 mMaxCachedKillPss = in.readLong();
   3044             } else {
   3045                 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
   3046             }
   3047             return true;
   3048         }
   3049 
   3050         public void makeActive() {
   3051             ensureNotDead();
   3052             mActive = true;
   3053         }
   3054 
   3055         public void makeInactive() {
   3056             mActive = false;
   3057         }
   3058 
   3059         public boolean isInUse() {
   3060             return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
   3061                     || mCurState != STATE_NOTHING;
   3062         }
   3063 
   3064         /**
   3065          * Update the current state of the given list of processes.
   3066          *
   3067          * @param state Current ActivityManager.PROCESS_STATE_*
   3068          * @param memFactor Current mem factor constant.
   3069          * @param now Current time.
   3070          * @param pkgList Processes to update.
   3071          */
   3072         public void setState(int state, int memFactor, long now,
   3073                 ArrayMap<String, ProcessStateHolder> pkgList) {
   3074             if (state < 0) {
   3075                 state = mNumStartedServices > 0
   3076                         ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
   3077             } else {
   3078                 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
   3079             }
   3080 
   3081             // First update the common process.
   3082             mCommonProcess.setState(state, now);
   3083 
   3084             // If the common process is not multi-package, there is nothing else to do.
   3085             if (!mCommonProcess.mMultiPackage) {
   3086                 return;
   3087             }
   3088 
   3089             if (pkgList != null) {
   3090                 for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3091                     pullFixedProc(pkgList, ip).setState(state, now);
   3092                 }
   3093             }
   3094         }
   3095 
   3096         void setState(int state, long now) {
   3097             ensureNotDead();
   3098             if (mCurState != state) {
   3099                 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
   3100                 commitStateTime(now);
   3101                 mCurState = state;
   3102             }
   3103         }
   3104 
   3105         void commitStateTime(long now) {
   3106             if (mCurState != STATE_NOTHING) {
   3107                 long dur = now - mStartTime;
   3108                 if (dur > 0) {
   3109                     addDuration(mCurState, dur);
   3110                 }
   3111             }
   3112             mStartTime = now;
   3113         }
   3114 
   3115         void incActiveServices(String serviceName) {
   3116             if (DEBUG && "".equals(mName)) {
   3117                 RuntimeException here = new RuntimeException("here");
   3118                 here.fillInStackTrace();
   3119                 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
   3120                         + " to " + (mNumActiveServices+1), here);
   3121             }
   3122             if (mCommonProcess != this) {
   3123                 mCommonProcess.incActiveServices(serviceName);
   3124             }
   3125             mNumActiveServices++;
   3126         }
   3127 
   3128         void decActiveServices(String serviceName) {
   3129             if (DEBUG && "".equals(mName)) {
   3130                 RuntimeException here = new RuntimeException("here");
   3131                 here.fillInStackTrace();
   3132                 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
   3133                         + " to " + (mNumActiveServices-1), here);
   3134             }
   3135             if (mCommonProcess != this) {
   3136                 mCommonProcess.decActiveServices(serviceName);
   3137             }
   3138             mNumActiveServices--;
   3139             if (mNumActiveServices < 0) {
   3140                 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
   3141                         + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
   3142                 mNumActiveServices = 0;
   3143             }
   3144         }
   3145 
   3146         void incStartedServices(int memFactor, long now, String serviceName) {
   3147             if (false) {
   3148                 RuntimeException here = new RuntimeException("here");
   3149                 here.fillInStackTrace();
   3150                 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
   3151                         + " to " + (mNumStartedServices+1), here);
   3152             }
   3153             if (mCommonProcess != this) {
   3154                 mCommonProcess.incStartedServices(memFactor, now, serviceName);
   3155             }
   3156             mNumStartedServices++;
   3157             if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
   3158                 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
   3159             }
   3160         }
   3161 
   3162         void decStartedServices(int memFactor, long now, String serviceName) {
   3163             if (false) {
   3164                 RuntimeException here = new RuntimeException("here");
   3165                 here.fillInStackTrace();
   3166                 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
   3167                         + " to " + (mNumStartedServices-1), here);
   3168             }
   3169             if (mCommonProcess != this) {
   3170                 mCommonProcess.decStartedServices(memFactor, now, serviceName);
   3171             }
   3172             mNumStartedServices--;
   3173             if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
   3174                 setState(STATE_NOTHING, now);
   3175             } else if (mNumStartedServices < 0) {
   3176                 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
   3177                         + mPackage + " uid=" + mUid + " name=" + mName);
   3178                 mNumStartedServices = 0;
   3179             }
   3180         }
   3181 
   3182         public void addPss(long pss, long uss, boolean always,
   3183                 ArrayMap<String, ProcessStateHolder> pkgList) {
   3184             ensureNotDead();
   3185             if (!always) {
   3186                 if (mLastPssState == mCurState && SystemClock.uptimeMillis()
   3187                         < (mLastPssTime+(30*1000))) {
   3188                     return;
   3189                 }
   3190             }
   3191             mLastPssState = mCurState;
   3192             mLastPssTime = SystemClock.uptimeMillis();
   3193             if (mCurState != STATE_NOTHING) {
   3194                 // First update the common process.
   3195                 mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
   3196 
   3197                 // If the common process is not multi-package, there is nothing else to do.
   3198                 if (!mCommonProcess.mMultiPackage) {
   3199                     return;
   3200                 }
   3201 
   3202                 if (pkgList != null) {
   3203                     for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3204                         pullFixedProc(pkgList, ip).addPss(mCurState, 1,
   3205                                 pss, pss, pss, uss, uss, uss);
   3206                     }
   3207                 }
   3208             }
   3209         }
   3210 
   3211         void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
   3212                 long avgUss, long maxUss) {
   3213             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3214             int off;
   3215             if (idx >= 0) {
   3216                 off = mPssTable[idx];
   3217             } else {
   3218                 mStats.mAddLongTable = mPssTable;
   3219                 mStats.mAddLongTableSize = mPssTableSize;
   3220                 off = mStats.addLongData(~idx, state, PSS_COUNT);
   3221                 mPssTable = mStats.mAddLongTable;
   3222                 mPssTableSize = mStats.mAddLongTableSize;
   3223             }
   3224             long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   3225             idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
   3226             long count = longs[idx+PSS_SAMPLE_COUNT];
   3227             if (count == 0) {
   3228                 longs[idx+PSS_SAMPLE_COUNT] = inCount;
   3229                 longs[idx+PSS_MINIMUM] = minPss;
   3230                 longs[idx+PSS_AVERAGE] = avgPss;
   3231                 longs[idx+PSS_MAXIMUM] = maxPss;
   3232                 longs[idx+PSS_USS_MINIMUM] = minUss;
   3233                 longs[idx+PSS_USS_AVERAGE] = avgUss;
   3234                 longs[idx+PSS_USS_MAXIMUM] = maxUss;
   3235             } else {
   3236                 longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
   3237                 if (longs[idx+PSS_MINIMUM] > minPss) {
   3238                     longs[idx+PSS_MINIMUM] = minPss;
   3239                 }
   3240                 longs[idx+PSS_AVERAGE] = (long)(
   3241                         ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
   3242                                 / (count+inCount) );
   3243                 if (longs[idx+PSS_MAXIMUM] < maxPss) {
   3244                     longs[idx+PSS_MAXIMUM] = maxPss;
   3245                 }
   3246                 if (longs[idx+PSS_USS_MINIMUM] > minUss) {
   3247                     longs[idx+PSS_USS_MINIMUM] = minUss;
   3248                 }
   3249                 longs[idx+PSS_USS_AVERAGE] = (long)(
   3250                         ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
   3251                                 / (count+inCount) );
   3252                 if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
   3253                     longs[idx+PSS_USS_MAXIMUM] = maxUss;
   3254                 }
   3255             }
   3256         }
   3257 
   3258         public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) {
   3259             ensureNotDead();
   3260             mCommonProcess.mNumExcessiveWake++;
   3261             if (!mCommonProcess.mMultiPackage) {
   3262                 return;
   3263             }
   3264 
   3265             for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3266                 pullFixedProc(pkgList, ip).mNumExcessiveWake++;
   3267             }
   3268         }
   3269 
   3270         public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) {
   3271             ensureNotDead();
   3272             mCommonProcess.mNumExcessiveCpu++;
   3273             if (!mCommonProcess.mMultiPackage) {
   3274                 return;
   3275             }
   3276 
   3277             for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3278                 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
   3279             }
   3280         }
   3281 
   3282         private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
   3283             if (mNumCachedKill <= 0) {
   3284                 mNumCachedKill = num;
   3285                 mMinCachedKillPss = minPss;
   3286                 mAvgCachedKillPss = avgPss;
   3287                 mMaxCachedKillPss = maxPss;
   3288             } else {
   3289                 if (minPss < mMinCachedKillPss) {
   3290                     mMinCachedKillPss = minPss;
   3291                 }
   3292                 if (maxPss > mMaxCachedKillPss) {
   3293                     mMaxCachedKillPss = maxPss;
   3294                 }
   3295                 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
   3296                         / (mNumCachedKill+num) );
   3297                 mNumCachedKill += num;
   3298             }
   3299         }
   3300 
   3301         public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) {
   3302             ensureNotDead();
   3303             mCommonProcess.addCachedKill(1, pss, pss, pss);
   3304             if (!mCommonProcess.mMultiPackage) {
   3305                 return;
   3306             }
   3307 
   3308             for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3309                 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
   3310             }
   3311         }
   3312 
   3313         ProcessState pullFixedProc(String pkgName) {
   3314             if (mMultiPackage) {
   3315                 // The array map is still pointing to a common process state
   3316                 // that is now shared across packages.  Update it to point to
   3317                 // the new per-package state.
   3318                 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid);
   3319                 if (vpkg == null) {
   3320                     throw new IllegalStateException("Didn't find package " + pkgName
   3321                             + " / " + mUid);
   3322                 }
   3323                 PackageState pkg = vpkg.get(mVersion);
   3324                 if (pkg == null) {
   3325                     throw new IllegalStateException("Didn't find package " + pkgName
   3326                             + " / " + mUid + " vers " + mVersion);
   3327                 }
   3328                 ProcessState proc = pkg.mProcesses.get(mName);
   3329                 if (proc == null) {
   3330                     throw new IllegalStateException("Didn't create per-package process "
   3331                             + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion);
   3332                 }
   3333                 return proc;
   3334             }
   3335             return this;
   3336         }
   3337 
   3338         private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList,
   3339                 int index) {
   3340             ProcessStateHolder holder = pkgList.valueAt(index);
   3341             ProcessState proc = holder.state;
   3342             if (mDead && proc.mCommonProcess != proc) {
   3343                 // Somehow we are contining to use a process state that is dead, because
   3344                 // it was not being told it was active during the last commit.  We can recover
   3345                 // from this by generating a fresh new state, but this is bad because we
   3346                 // are losing whatever data we had in the old process state.
   3347                 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
   3348                         + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
   3349                 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion,
   3350                         proc.mName);
   3351             }
   3352             if (proc.mMultiPackage) {
   3353                 // The array map is still pointing to a common process state
   3354                 // that is now shared across packages.  Update it to point to
   3355                 // the new per-package state.
   3356                 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index),
   3357                         proc.mUid);
   3358                 if (vpkg == null) {
   3359                     throw new IllegalStateException("No existing package "
   3360                             + pkgList.keyAt(index) + "/" + proc.mUid
   3361                             + " for multi-proc " + proc.mName);
   3362                 }
   3363                 PackageState pkg = vpkg.get(proc.mVersion);
   3364                 if (pkg == null) {
   3365                     throw new IllegalStateException("No existing package "
   3366                             + pkgList.keyAt(index) + "/" + proc.mUid
   3367                             + " for multi-proc " + proc.mName + " version " + proc.mVersion);
   3368                 }
   3369                 proc = pkg.mProcesses.get(proc.mName);
   3370                 if (proc == null) {
   3371                     throw new IllegalStateException("Didn't create per-package process "
   3372                             + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
   3373                 }
   3374                 holder.state = proc;
   3375             }
   3376             return proc;
   3377         }
   3378 
   3379         long getDuration(int state, long now) {
   3380             long time = super.getDuration(state, now);
   3381             if (mCurState == state) {
   3382                 time += now - mStartTime;
   3383             }
   3384             return time;
   3385         }
   3386 
   3387         long getPssSampleCount(int state) {
   3388             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3389             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
   3390         }
   3391 
   3392         long getPssMinimum(int state) {
   3393             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3394             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
   3395         }
   3396 
   3397         long getPssAverage(int state) {
   3398             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3399             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
   3400         }
   3401 
   3402         long getPssMaximum(int state) {
   3403             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3404             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
   3405         }
   3406 
   3407         long getPssUssMinimum(int state) {
   3408             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3409             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
   3410         }
   3411 
   3412         long getPssUssAverage(int state) {
   3413             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3414             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
   3415         }
   3416 
   3417         long getPssUssMaximum(int state) {
   3418             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3419             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
   3420         }
   3421 
   3422         public String toString() {
   3423             StringBuilder sb = new StringBuilder(128);
   3424             sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
   3425                     .append(" ").append(mName).append("/").append(mUid)
   3426                     .append(" pkg=").append(mPackage);
   3427             if (mMultiPackage) sb.append(" (multi)");
   3428             if (mCommonProcess != this) sb.append(" (sub)");
   3429             sb.append("}");
   3430             return sb.toString();
   3431         }
   3432     }
   3433 
   3434     public static final class ServiceState extends DurationsTable {
   3435         public final String mPackage;
   3436         public final String mProcessName;
   3437         ProcessState mProc;
   3438 
   3439         Object mOwner;
   3440 
   3441         public static final int SERVICE_RUN = 0;
   3442         public static final int SERVICE_STARTED = 1;
   3443         public static final int SERVICE_BOUND = 2;
   3444         public static final int SERVICE_EXEC = 3;
   3445         static final int SERVICE_COUNT = 4;
   3446 
   3447         int mRunCount;
   3448         public int mRunState = STATE_NOTHING;
   3449         long mRunStartTime;
   3450 
   3451         boolean mStarted;
   3452         boolean mRestarting;
   3453         int mStartedCount;
   3454         public int mStartedState = STATE_NOTHING;
   3455         long mStartedStartTime;
   3456 
   3457         int mBoundCount;
   3458         public int mBoundState = STATE_NOTHING;
   3459         long mBoundStartTime;
   3460 
   3461         int mExecCount;
   3462         public int mExecState = STATE_NOTHING;
   3463         long mExecStartTime;
   3464 
   3465         public ServiceState(ProcessStats processStats, String pkg, String name,
   3466                 String processName, ProcessState proc) {
   3467             super(processStats, name);
   3468             mPackage = pkg;
   3469             mProcessName = processName;
   3470             mProc = proc;
   3471         }
   3472 
   3473         public void applyNewOwner(Object newOwner) {
   3474             if (mOwner != newOwner) {
   3475                 if (mOwner == null) {
   3476                     mOwner = newOwner;
   3477                     mProc.incActiveServices(mName);
   3478                 } else {
   3479                     // There was already an old owner, reset this object for its
   3480                     // new owner.
   3481                     mOwner = newOwner;
   3482                     if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
   3483                         long now = SystemClock.uptimeMillis();
   3484                         if (mStarted) {
   3485                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
   3486                                     + " from " + mOwner + " while started: pkg="
   3487                                     + mPackage + " service=" + mName + " proc=" + mProc);
   3488                             setStarted(false, 0, now);
   3489                         }
   3490                         if (mBoundState != STATE_NOTHING) {
   3491                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
   3492                                     + " from " + mOwner + " while bound: pkg="
   3493                                     + mPackage + " service=" + mName + " proc=" + mProc);
   3494                             setBound(false, 0, now);
   3495                         }
   3496                         if (mExecState != STATE_NOTHING) {
   3497                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
   3498                                     + " from " + mOwner + " while executing: pkg="
   3499                                     + mPackage + " service=" + mName + " proc=" + mProc);
   3500                             setExecuting(false, 0, now);
   3501                         }
   3502                     }
   3503                 }
   3504             }
   3505         }
   3506 
   3507         public void clearCurrentOwner(Object owner, boolean silently) {
   3508             if (mOwner == owner) {
   3509                 mProc.decActiveServices(mName);
   3510                 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
   3511                     long now = SystemClock.uptimeMillis();
   3512                     if (mStarted) {
   3513                         if (!silently) {
   3514                             Slog.wtfStack(TAG, "Service owner " + owner
   3515                                     + " cleared while started: pkg=" + mPackage + " service="
   3516                                     + mName + " proc=" + mProc);
   3517                         }
   3518                         setStarted(false, 0, now);
   3519                     }
   3520                     if (mBoundState != STATE_NOTHING) {
   3521                         if (!silently) {
   3522                             Slog.wtfStack(TAG, "Service owner " + owner
   3523                                     + " cleared while bound: pkg=" + mPackage + " service="
   3524                                     + mName + " proc=" + mProc);
   3525                         }
   3526                         setBound(false, 0, now);
   3527                     }
   3528                     if (mExecState != STATE_NOTHING) {
   3529                         if (!silently) {
   3530                             Slog.wtfStack(TAG, "Service owner " + owner
   3531                                     + " cleared while exec: pkg=" + mPackage + " service="
   3532                                     + mName + " proc=" + mProc);
   3533                         }
   3534                         setExecuting(false, 0, now);
   3535                     }
   3536                 }
   3537                 mOwner = null;
   3538             }
   3539         }
   3540 
   3541         public boolean isInUse() {
   3542             return mOwner != null || mRestarting;
   3543         }
   3544 
   3545         public boolean isRestarting() {
   3546             return mRestarting;
   3547         }
   3548 
   3549         void add(ServiceState other) {
   3550             addDurations(other);
   3551             mRunCount += other.mRunCount;
   3552             mStartedCount += other.mStartedCount;
   3553             mBoundCount += other.mBoundCount;
   3554             mExecCount += other.mExecCount;
   3555         }
   3556 
   3557         void resetSafely(long now) {
   3558             resetDurationsSafely();
   3559             mRunCount = mRunState != STATE_NOTHING ? 1 : 0;
   3560             mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
   3561             mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
   3562             mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
   3563             mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now;
   3564         }
   3565 
   3566         void writeToParcel(Parcel out, long now) {
   3567             writeDurationsToParcel(out);
   3568             out.writeInt(mRunCount);
   3569             out.writeInt(mStartedCount);
   3570             out.writeInt(mBoundCount);
   3571             out.writeInt(mExecCount);
   3572         }
   3573 
   3574         boolean readFromParcel(Parcel in) {
   3575             if (!readDurationsFromParcel(in)) {
   3576                 return false;
   3577             }
   3578             mRunCount = in.readInt();
   3579             mStartedCount = in.readInt();
   3580             mBoundCount = in.readInt();
   3581             mExecCount = in.readInt();
   3582             return true;
   3583         }
   3584 
   3585         void commitStateTime(long now) {
   3586             if (mRunState != STATE_NOTHING) {
   3587                 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime);
   3588                 mRunStartTime = now;
   3589             }
   3590             if (mStartedState != STATE_NOTHING) {
   3591                 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
   3592                         now - mStartedStartTime);
   3593                 mStartedStartTime = now;
   3594             }
   3595             if (mBoundState != STATE_NOTHING) {
   3596                 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
   3597                 mBoundStartTime = now;
   3598             }
   3599             if (mExecState != STATE_NOTHING) {
   3600                 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
   3601                 mExecStartTime = now;
   3602             }
   3603         }
   3604 
   3605         private void updateRunning(int memFactor, long now) {
   3606             final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
   3607                     || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
   3608             if (mRunState != state) {
   3609                 if (mRunState != STATE_NOTHING) {
   3610                     addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT),
   3611                             now - mRunStartTime);
   3612                 } else if (state != STATE_NOTHING) {
   3613                     mRunCount++;
   3614                 }
   3615                 mRunState = state;
   3616                 mRunStartTime = now;
   3617             }
   3618         }
   3619 
   3620         public void setStarted(boolean started, int memFactor, long now) {
   3621             if (mOwner == null) {
   3622                 Slog.wtf(TAG, "Starting service " + this + " without owner");
   3623             }
   3624             mStarted = started;
   3625             updateStartedState(memFactor, now);
   3626         }
   3627 
   3628         public void setRestarting(boolean restarting, int memFactor, long now) {
   3629             mRestarting = restarting;
   3630             updateStartedState(memFactor, now);
   3631         }
   3632 
   3633         void updateStartedState(int memFactor, long now) {
   3634             final boolean wasStarted = mStartedState != STATE_NOTHING;
   3635             final boolean started = mStarted || mRestarting;
   3636             final int state = started ? memFactor : STATE_NOTHING;
   3637             if (mStartedState != state) {
   3638                 if (mStartedState != STATE_NOTHING) {
   3639                     addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
   3640                             now - mStartedStartTime);
   3641                 } else if (started) {
   3642                     mStartedCount++;
   3643                 }
   3644                 mStartedState = state;
   3645                 mStartedStartTime = now;
   3646                 mProc = mProc.pullFixedProc(mPackage);
   3647                 if (wasStarted != started) {
   3648                     if (started) {
   3649                         mProc.incStartedServices(memFactor, now, mName);
   3650                     } else {
   3651                         mProc.decStartedServices(memFactor, now, mName);
   3652                     }
   3653                 }
   3654                 updateRunning(memFactor, now);
   3655             }
   3656         }
   3657 
   3658         public void setBound(boolean bound, int memFactor, long now) {
   3659             if (mOwner == null) {
   3660                 Slog.wtf(TAG, "Binding service " + this + " without owner");
   3661             }
   3662             final int state = bound ? memFactor : STATE_NOTHING;
   3663             if (mBoundState != state) {
   3664                 if (mBoundState != STATE_NOTHING) {
   3665                     addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
   3666                             now - mBoundStartTime);
   3667                 } else if (bound) {
   3668                     mBoundCount++;
   3669                 }
   3670                 mBoundState = state;
   3671                 mBoundStartTime = now;
   3672                 updateRunning(memFactor, now);
   3673             }
   3674         }
   3675 
   3676         public void setExecuting(boolean executing, int memFactor, long now) {
   3677             if (mOwner == null) {
   3678                 Slog.wtf(TAG, "Executing service " + this + " without owner");
   3679             }
   3680             final int state = executing ? memFactor : STATE_NOTHING;
   3681             if (mExecState != state) {
   3682                 if (mExecState != STATE_NOTHING) {
   3683                     addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
   3684                 } else if (executing) {
   3685                     mExecCount++;
   3686                 }
   3687                 mExecState = state;
   3688                 mExecStartTime = now;
   3689                 updateRunning(memFactor, now);
   3690             }
   3691         }
   3692 
   3693         private long getDuration(int opType, int curState, long startTime, int memFactor,
   3694                 long now) {
   3695             int state = opType + (memFactor*SERVICE_COUNT);
   3696             long time = getDuration(state, now);
   3697             if (curState == memFactor) {
   3698                 time += now - startTime;
   3699             }
   3700             return time;
   3701         }
   3702 
   3703         public String toString() {
   3704             return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
   3705                     + " " + mName + " pkg=" + mPackage + " proc="
   3706                     + Integer.toHexString(System.identityHashCode(this)) + "}";
   3707         }
   3708     }
   3709 
   3710     public static final class PackageState {
   3711         public final ArrayMap<String, ProcessState> mProcesses
   3712                 = new ArrayMap<String, ProcessState>();
   3713         public final ArrayMap<String, ServiceState> mServices
   3714                 = new ArrayMap<String, ServiceState>();
   3715         public final String mPackageName;
   3716         public final int mUid;
   3717 
   3718         public PackageState(String packageName, int uid) {
   3719             mUid = uid;
   3720             mPackageName = packageName;
   3721         }
   3722     }
   3723 
   3724     public static final class ProcessDataCollection {
   3725         final int[] screenStates;
   3726         final int[] memStates;
   3727         final int[] procStates;
   3728 
   3729         public long totalTime;
   3730         public long numPss;
   3731         public long minPss;
   3732         public long avgPss;
   3733         public long maxPss;
   3734         public long minUss;
   3735         public long avgUss;
   3736         public long maxUss;
   3737 
   3738         public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
   3739             screenStates = _screenStates;
   3740             memStates = _memStates;
   3741             procStates = _procStates;
   3742         }
   3743 
   3744         void print(PrintWriter pw, long overallTime, boolean full) {
   3745             if (totalTime > overallTime) {
   3746                 pw.print("*");
   3747             }
   3748             printPercent(pw, (double) totalTime / (double) overallTime);
   3749             if (numPss > 0) {
   3750                 pw.print(" (");
   3751                 DebugUtils.printSizeValue(pw, minPss * 1024);
   3752                 pw.print("-");
   3753                 DebugUtils.printSizeValue(pw, avgPss * 1024);
   3754                 pw.print("-");
   3755                 DebugUtils.printSizeValue(pw, maxPss * 1024);
   3756                 pw.print("/");
   3757                 DebugUtils.printSizeValue(pw, minUss * 1024);
   3758                 pw.print("-");
   3759                 DebugUtils.printSizeValue(pw, avgUss * 1024);
   3760                 pw.print("-");
   3761                 DebugUtils.printSizeValue(pw, maxUss * 1024);
   3762                 if (full) {
   3763                     pw.print(" over ");
   3764                     pw.print(numPss);
   3765                 }
   3766                 pw.print(")");
   3767             }
   3768         }
   3769     }
   3770 
   3771     public static class TotalMemoryUseCollection {
   3772         final int[] screenStates;
   3773         final int[] memStates;
   3774 
   3775         public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) {
   3776             screenStates = _screenStates;
   3777             memStates = _memStates;
   3778         }
   3779 
   3780         public long totalTime;
   3781         public long[] processStatePss = new long[STATE_COUNT];
   3782         public double[] processStateWeight = new double[STATE_COUNT];
   3783         public long[] processStateTime = new long[STATE_COUNT];
   3784         public int[] processStateSamples = new int[STATE_COUNT];
   3785         public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT];
   3786         public double sysMemCachedWeight;
   3787         public double sysMemFreeWeight;
   3788         public double sysMemZRamWeight;
   3789         public double sysMemKernelWeight;
   3790         public double sysMemNativeWeight;
   3791         public int sysMemSamples;
   3792     }
   3793 }
   3794