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