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         double percentage = (double) totals.totalTime / (double) totalTime * 100;
   1083         // We don't print percentages < .01, so just drop those.
   1084         if (percentage >= 0.005 || totals.numPss != 0) {
   1085             if (prefix != null) {
   1086                 pw.print(prefix);
   1087             }
   1088             if (label != null) {
   1089                 pw.print(label);
   1090             }
   1091             totals.print(pw, totalTime, full);
   1092             if (prefix != null) {
   1093                 pw.println();
   1094             }
   1095         }
   1096     }
   1097 
   1098     static void dumpProcessSummaryLocked(PrintWriter pw, String prefix,
   1099             ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
   1100             boolean inclUidVers, long now, long totalTime) {
   1101         for (int i=procs.size()-1; i>=0; i--) {
   1102             ProcessState proc = procs.get(i);
   1103             pw.print(prefix);
   1104             pw.print("* ");
   1105             pw.print(proc.mName);
   1106             pw.print(" / ");
   1107             UserHandle.formatUid(pw, proc.mUid);
   1108             pw.print(" / v");
   1109             pw.print(proc.mVersion);
   1110             pw.println(":");
   1111             dumpProcessSummaryDetails(pw, proc, prefix, "         TOTAL: ", screenStates, memStates,
   1112                     procStates, now, totalTime, true);
   1113             dumpProcessSummaryDetails(pw, proc, prefix, "    Persistent: ", screenStates, memStates,
   1114                     new int[] { STATE_PERSISTENT }, now, totalTime, true);
   1115             dumpProcessSummaryDetails(pw, proc, prefix, "           Top: ", screenStates, memStates,
   1116                     new int[] {STATE_TOP}, now, totalTime, true);
   1117             dumpProcessSummaryDetails(pw, proc, prefix, "        Imp Fg: ", screenStates, memStates,
   1118                     new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true);
   1119             dumpProcessSummaryDetails(pw, proc, prefix, "        Imp Bg: ", screenStates, memStates,
   1120                     new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true);
   1121             dumpProcessSummaryDetails(pw, proc, prefix, "        Backup: ", screenStates, memStates,
   1122                     new int[] {STATE_BACKUP}, now, totalTime, true);
   1123             dumpProcessSummaryDetails(pw, proc, prefix, "     Heavy Wgt: ", screenStates, memStates,
   1124                     new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
   1125             dumpProcessSummaryDetails(pw, proc, prefix, "       Service: ", screenStates, memStates,
   1126                     new int[] {STATE_SERVICE}, now, totalTime, true);
   1127             dumpProcessSummaryDetails(pw, proc, prefix, "    Service Rs: ", screenStates, memStates,
   1128                     new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
   1129             dumpProcessSummaryDetails(pw, proc, prefix, "      Receiver: ", screenStates, memStates,
   1130                     new int[] {STATE_RECEIVER}, now, totalTime, true);
   1131             dumpProcessSummaryDetails(pw, proc, prefix, "        (Home): ", screenStates, memStates,
   1132                     new int[] {STATE_HOME}, now, totalTime, true);
   1133             dumpProcessSummaryDetails(pw, proc, prefix, "    (Last Act): ", screenStates, memStates,
   1134                     new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
   1135             dumpProcessSummaryDetails(pw, proc, prefix, "      (Cached): ", screenStates, memStates,
   1136                     new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT,
   1137                             STATE_CACHED_EMPTY}, now, totalTime, true);
   1138         }
   1139     }
   1140 
   1141     static void printPercent(PrintWriter pw, double fraction) {
   1142         fraction *= 100;
   1143         if (fraction < 1) {
   1144             pw.print(String.format("%.2f", fraction));
   1145         } else if (fraction < 10) {
   1146             pw.print(String.format("%.1f", fraction));
   1147         } else {
   1148             pw.print(String.format("%.0f", fraction));
   1149         }
   1150         pw.print("%");
   1151     }
   1152 
   1153     static void printSizeValue(PrintWriter pw, long number) {
   1154         float result = number;
   1155         String suffix = "";
   1156         if (result > 900) {
   1157             suffix = "KB";
   1158             result = result / 1024;
   1159         }
   1160         if (result > 900) {
   1161             suffix = "MB";
   1162             result = result / 1024;
   1163         }
   1164         if (result > 900) {
   1165             suffix = "GB";
   1166             result = result / 1024;
   1167         }
   1168         if (result > 900) {
   1169             suffix = "TB";
   1170             result = result / 1024;
   1171         }
   1172         if (result > 900) {
   1173             suffix = "PB";
   1174             result = result / 1024;
   1175         }
   1176         String value;
   1177         if (result < 1) {
   1178             value = String.format("%.2f", result);
   1179         } else if (result < 10) {
   1180             value = String.format("%.1f", result);
   1181         } else if (result < 100) {
   1182             value = String.format("%.0f", result);
   1183         } else {
   1184             value = String.format("%.0f", result);
   1185         }
   1186         pw.print(value);
   1187         pw.print(suffix);
   1188     }
   1189 
   1190     public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
   1191             boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
   1192             boolean sepProcStates, int[] procStates, long now) {
   1193         pw.print("process");
   1194         pw.print(CSV_SEP);
   1195         pw.print("uid");
   1196         pw.print(CSV_SEP);
   1197         pw.print("vers");
   1198         dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
   1199                 sepMemStates ? memStates : null,
   1200                 sepProcStates ? procStates : null);
   1201         pw.println();
   1202         for (int i=procs.size()-1; i>=0; i--) {
   1203             ProcessState proc = procs.get(i);
   1204             pw.print(proc.mName);
   1205             pw.print(CSV_SEP);
   1206             UserHandle.formatUid(pw, proc.mUid);
   1207             pw.print(CSV_SEP);
   1208             pw.print(proc.mVersion);
   1209             dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates,
   1210                     sepMemStates, memStates, sepProcStates, procStates, now);
   1211             pw.println();
   1212         }
   1213     }
   1214 
   1215     static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
   1216         int index = value/mod;
   1217         if (index >= 0 && index < array.length) {
   1218             pw.print(array[index]);
   1219         } else {
   1220             pw.print('?');
   1221         }
   1222         return value - index*mod;
   1223     }
   1224 
   1225     static void printProcStateTag(PrintWriter pw, int state) {
   1226         state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD*STATE_COUNT);
   1227         state = printArrayEntry(pw, ADJ_MEM_TAGS,  state, STATE_COUNT);
   1228         printArrayEntry(pw, STATE_TAGS,  state, 1);
   1229     }
   1230 
   1231     static void printAdjTag(PrintWriter pw, int state) {
   1232         state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD);
   1233         printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
   1234     }
   1235 
   1236     static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
   1237         pw.print(',');
   1238         printProcStateTag(pw, state);
   1239         pw.print(':');
   1240         pw.print(value);
   1241     }
   1242 
   1243     static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
   1244         pw.print(',');
   1245         printAdjTag(pw, state);
   1246         pw.print(':');
   1247         pw.print(value);
   1248     }
   1249 
   1250     static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
   1251         boolean didCurState = false;
   1252         for (int i=0; i<proc.mDurationsTableSize; i++) {
   1253             int off = proc.mDurationsTable[i];
   1254             int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   1255             long time = proc.mStats.getLong(off, 0);
   1256             if (proc.mCurState == type) {
   1257                 didCurState = true;
   1258                 time += now - proc.mStartTime;
   1259             }
   1260             printProcStateTagAndValue(pw, type, time);
   1261         }
   1262         if (!didCurState && proc.mCurState != STATE_NOTHING) {
   1263             printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
   1264         }
   1265     }
   1266 
   1267     static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) {
   1268         for (int i=0; i<proc.mPssTableSize; i++) {
   1269             int off = proc.mPssTable[i];
   1270             int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   1271             long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT);
   1272             long min = proc.mStats.getLong(off, PSS_MINIMUM);
   1273             long avg = proc.mStats.getLong(off, PSS_AVERAGE);
   1274             long max = proc.mStats.getLong(off, PSS_MAXIMUM);
   1275             long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM);
   1276             long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE);
   1277             long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM);
   1278             pw.print(',');
   1279             printProcStateTag(pw, type);
   1280             pw.print(':');
   1281             pw.print(count);
   1282             pw.print(':');
   1283             pw.print(min);
   1284             pw.print(':');
   1285             pw.print(avg);
   1286             pw.print(':');
   1287             pw.print(max);
   1288             pw.print(':');
   1289             pw.print(umin);
   1290             pw.print(':');
   1291             pw.print(uavg);
   1292             pw.print(':');
   1293             pw.print(umax);
   1294         }
   1295     }
   1296 
   1297     public void reset() {
   1298         if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr);
   1299         resetCommon();
   1300         mPackages.getMap().clear();
   1301         mProcesses.getMap().clear();
   1302         mMemFactor = STATE_NOTHING;
   1303         mStartTime = 0;
   1304         if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
   1305     }
   1306 
   1307     public void resetSafely() {
   1308         if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
   1309         resetCommon();
   1310 
   1311         // First initialize use count of all common processes.
   1312         final long now = SystemClock.uptimeMillis();
   1313         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   1314         for (int ip=procMap.size()-1; ip>=0; ip--) {
   1315             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1316             for (int iu=uids.size()-1; iu>=0; iu--) {
   1317                 uids.valueAt(iu).mTmpNumInUse = 0;
   1318            }
   1319         }
   1320 
   1321         // Next reset or prune all per-package processes, and for the ones that are reset
   1322         // track this back to the common processes.
   1323         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   1324         for (int ip=pkgMap.size()-1; ip>=0; ip--) {
   1325             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   1326             for (int iu=uids.size()-1; iu>=0; iu--) {
   1327                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   1328                 for (int iv=vpkgs.size()-1; iv>=0; iv--) {
   1329                     final PackageState pkgState = vpkgs.valueAt(iv);
   1330                     for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
   1331                         final ProcessState ps = pkgState.mProcesses.valueAt(iproc);
   1332                         if (ps.isInUse()) {
   1333                             ps.resetSafely(now);
   1334                             ps.mCommonProcess.mTmpNumInUse++;
   1335                             ps.mCommonProcess.mTmpFoundSubProc = ps;
   1336                         } else {
   1337                             pkgState.mProcesses.valueAt(iproc).makeDead();
   1338                             pkgState.mProcesses.removeAt(iproc);
   1339                         }
   1340                     }
   1341                     for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
   1342                         final ServiceState ss = pkgState.mServices.valueAt(isvc);
   1343                         if (ss.isInUse()) {
   1344                             ss.resetSafely(now);
   1345                         } else {
   1346                             pkgState.mServices.removeAt(isvc);
   1347                         }
   1348                     }
   1349                     if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
   1350                         vpkgs.removeAt(iv);
   1351                     }
   1352                 }
   1353                 if (vpkgs.size() <= 0) {
   1354                     uids.removeAt(iu);
   1355                 }
   1356             }
   1357             if (uids.size() <= 0) {
   1358                 pkgMap.removeAt(ip);
   1359             }
   1360         }
   1361 
   1362         // Finally prune out any common processes that are no longer in use.
   1363         for (int ip=procMap.size()-1; ip>=0; ip--) {
   1364             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1365             for (int iu=uids.size()-1; iu>=0; iu--) {
   1366                 ProcessState ps = uids.valueAt(iu);
   1367                 if (ps.isInUse() || ps.mTmpNumInUse > 0) {
   1368                     // If this is a process for multiple packages, we could at this point
   1369                     // be back down to one package.  In that case, we want to revert back
   1370                     // to a single shared ProcessState.  We can do this by converting the
   1371                     // current package-specific ProcessState up to the shared ProcessState,
   1372                     // throwing away the current one we have here (because nobody else is
   1373                     // using it).
   1374                     if (!ps.mActive && ps.mMultiPackage && ps.mTmpNumInUse == 1) {
   1375                         // Here we go...
   1376                         ps = ps.mTmpFoundSubProc;
   1377                         ps.mCommonProcess = ps;
   1378                         uids.setValueAt(iu, ps);
   1379                     } else {
   1380                         ps.resetSafely(now);
   1381                     }
   1382                 } else {
   1383                     ps.makeDead();
   1384                     uids.removeAt(iu);
   1385                 }
   1386             }
   1387             if (uids.size() <= 0) {
   1388                 procMap.removeAt(ip);
   1389             }
   1390         }
   1391 
   1392         mStartTime = now;
   1393         if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
   1394     }
   1395 
   1396     private void resetCommon() {
   1397         mTimePeriodStartClock = System.currentTimeMillis();
   1398         buildTimePeriodStartClockStr();
   1399         mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
   1400         mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis();
   1401         mLongs.clear();
   1402         mLongs.add(new long[LONGS_SIZE]);
   1403         mNextLong = 0;
   1404         Arrays.fill(mMemFactorDurations, 0);
   1405         mSysMemUsageTable = null;
   1406         mSysMemUsageTableSize = 0;
   1407         mStartTime = 0;
   1408         mReadError = null;
   1409         mFlags = 0;
   1410         evaluateSystemProperties(true);
   1411     }
   1412 
   1413     public boolean evaluateSystemProperties(boolean update) {
   1414         boolean changed = false;
   1415         String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2",
   1416                 VMRuntime.getRuntime().vmLibrary());
   1417         if (!Objects.equals(runtime, mRuntime)) {
   1418             changed = true;
   1419             if (update) {
   1420                 mRuntime = runtime;
   1421             }
   1422         }
   1423         return changed;
   1424     }
   1425 
   1426     private void buildTimePeriodStartClockStr() {
   1427         mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
   1428                 mTimePeriodStartClock).toString();
   1429     }
   1430 
   1431     static final int[] BAD_TABLE = new int[0];
   1432 
   1433     private int[] readTableFromParcel(Parcel in, String name, String what) {
   1434         final int size = in.readInt();
   1435         if (size < 0) {
   1436             Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size);
   1437             return BAD_TABLE;
   1438         }
   1439         if (size == 0) {
   1440             return null;
   1441         }
   1442         final int[] table = new int[size];
   1443         for (int i=0; i<size; i++) {
   1444             table[i] = in.readInt();
   1445             if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
   1446                     + ProcessStats.printLongOffset(table[i]));
   1447             if (!validateLongOffset(table[i])) {
   1448                 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
   1449                         + ProcessStats.printLongOffset(table[i]));
   1450                 return null;
   1451             }
   1452         }
   1453         return table;
   1454     }
   1455 
   1456     private void writeCompactedLongArray(Parcel out, long[] array, int num) {
   1457         for (int i=0; i<num; i++) {
   1458             long val = array[i];
   1459             if (val < 0) {
   1460                 Slog.w(TAG, "Time val negative: " + val);
   1461                 val = 0;
   1462             }
   1463             if (val <= Integer.MAX_VALUE) {
   1464                 out.writeInt((int)val);
   1465             } else {
   1466                 int top = ~((int)((val>>32)&0x7fffffff));
   1467                 int bottom = (int)(val&0xfffffff);
   1468                 out.writeInt(top);
   1469                 out.writeInt(bottom);
   1470             }
   1471         }
   1472     }
   1473 
   1474     private void readCompactedLongArray(Parcel in, int version, long[] array, int num) {
   1475         if (version <= 10) {
   1476             in.readLongArray(array);
   1477             return;
   1478         }
   1479         final int alen = array.length;
   1480         if (num > alen) {
   1481             throw new RuntimeException("bad array lengths: got " + num + " array is " + alen);
   1482         }
   1483         int i;
   1484         for (i=0; i<num; i++) {
   1485             int val = in.readInt();
   1486             if (val >= 0) {
   1487                 array[i] = val;
   1488             } else {
   1489                 int bottom = in.readInt();
   1490                 array[i] = (((long)~val)<<32) | bottom;
   1491             }
   1492         }
   1493         while (i < alen) {
   1494             array[i] = 0;
   1495             i++;
   1496         }
   1497     }
   1498 
   1499     private void writeCommonString(Parcel out, String name) {
   1500         Integer index = mCommonStringToIndex.get(name);
   1501         if (index != null) {
   1502             out.writeInt(index);
   1503             return;
   1504         }
   1505         index = mCommonStringToIndex.size();
   1506         mCommonStringToIndex.put(name, index);
   1507         out.writeInt(~index);
   1508         out.writeString(name);
   1509     }
   1510 
   1511     private String readCommonString(Parcel in, int version) {
   1512         if (version <= 9) {
   1513             return in.readString();
   1514         }
   1515         int index = in.readInt();
   1516         if (index >= 0) {
   1517             return mIndexToCommonString.get(index);
   1518         }
   1519         index = ~index;
   1520         String name = in.readString();
   1521         while (mIndexToCommonString.size() <= index) {
   1522             mIndexToCommonString.add(null);
   1523         }
   1524         mIndexToCommonString.set(index, name);
   1525         return name;
   1526     }
   1527 
   1528     @Override
   1529     public int describeContents() {
   1530         return 0;
   1531     }
   1532 
   1533     @Override
   1534     public void writeToParcel(Parcel out, int flags) {
   1535         writeToParcel(out, SystemClock.uptimeMillis(), flags);
   1536     }
   1537 
   1538     /** @hide */
   1539     public void writeToParcel(Parcel out, long now, int flags) {
   1540         out.writeInt(MAGIC);
   1541         out.writeInt(PARCEL_VERSION);
   1542         out.writeInt(STATE_COUNT);
   1543         out.writeInt(ADJ_COUNT);
   1544         out.writeInt(PSS_COUNT);
   1545         out.writeInt(SYS_MEM_USAGE_COUNT);
   1546         out.writeInt(LONGS_SIZE);
   1547 
   1548         mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size());
   1549 
   1550         // First commit all running times.
   1551         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   1552         final int NPROC = procMap.size();
   1553         for (int ip=0; ip<NPROC; ip++) {
   1554             SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1555             final int NUID = uids.size();
   1556             for (int iu=0; iu<NUID; iu++) {
   1557                 uids.valueAt(iu).commitStateTime(now);
   1558             }
   1559         }
   1560         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   1561         final int NPKG = pkgMap.size();
   1562         for (int ip=0; ip<NPKG; ip++) {
   1563             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   1564             final int NUID = uids.size();
   1565             for (int iu=0; iu<NUID; iu++) {
   1566                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   1567                 final int NVERS = vpkgs.size();
   1568                 for (int iv=0; iv<NVERS; iv++) {
   1569                     PackageState pkgState = vpkgs.valueAt(iv);
   1570                     final int NPROCS = pkgState.mProcesses.size();
   1571                     for (int iproc=0; iproc<NPROCS; iproc++) {
   1572                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   1573                         if (proc.mCommonProcess != proc) {
   1574                             proc.commitStateTime(now);
   1575                         }
   1576                     }
   1577                     final int NSRVS = pkgState.mServices.size();
   1578                     for (int isvc=0; isvc<NSRVS; isvc++) {
   1579                         pkgState.mServices.valueAt(isvc).commitStateTime(now);
   1580                     }
   1581                 }
   1582             }
   1583         }
   1584 
   1585         out.writeLong(mTimePeriodStartClock);
   1586         out.writeLong(mTimePeriodStartRealtime);
   1587         out.writeLong(mTimePeriodEndRealtime);
   1588         out.writeLong(mTimePeriodStartUptime);
   1589         out.writeLong(mTimePeriodEndUptime);
   1590         out.writeString(mRuntime);
   1591         out.writeInt(mFlags);
   1592 
   1593         out.writeInt(mLongs.size());
   1594         out.writeInt(mNextLong);
   1595         for (int i=0; i<(mLongs.size()-1); i++) {
   1596             long[] array = mLongs.get(i);
   1597             writeCompactedLongArray(out, array, array.length);
   1598         }
   1599         long[] lastLongs = mLongs.get(mLongs.size() - 1);
   1600         writeCompactedLongArray(out, lastLongs, mNextLong);
   1601 
   1602         if (mMemFactor != STATE_NOTHING) {
   1603             mMemFactorDurations[mMemFactor] += now - mStartTime;
   1604             mStartTime = now;
   1605         }
   1606         writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length);
   1607 
   1608         out.writeInt(mSysMemUsageTableSize);
   1609         for (int i=0; i<mSysMemUsageTableSize; i++) {
   1610             if (DEBUG_PARCEL) Slog.i(TAG, "Writing sys mem usage #" + i + ": "
   1611                     + printLongOffset(mSysMemUsageTable[i]));
   1612             out.writeInt(mSysMemUsageTable[i]);
   1613         }
   1614 
   1615         out.writeInt(NPROC);
   1616         for (int ip=0; ip<NPROC; ip++) {
   1617             writeCommonString(out, procMap.keyAt(ip));
   1618             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
   1619             final int NUID = uids.size();
   1620             out.writeInt(NUID);
   1621             for (int iu=0; iu<NUID; iu++) {
   1622                 out.writeInt(uids.keyAt(iu));
   1623                 final ProcessState proc = uids.valueAt(iu);
   1624                 writeCommonString(out, proc.mPackage);
   1625                 out.writeInt(proc.mVersion);
   1626                 proc.writeToParcel(out, now);
   1627             }
   1628         }
   1629         out.writeInt(NPKG);
   1630         for (int ip=0; ip<NPKG; ip++) {
   1631             writeCommonString(out, pkgMap.keyAt(ip));
   1632             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   1633             final int NUID = uids.size();
   1634             out.writeInt(NUID);
   1635             for (int iu=0; iu<NUID; iu++) {
   1636                 out.writeInt(uids.keyAt(iu));
   1637                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   1638                 final int NVERS = vpkgs.size();
   1639                 out.writeInt(NVERS);
   1640                 for (int iv=0; iv<NVERS; iv++) {
   1641                     out.writeInt(vpkgs.keyAt(iv));
   1642                     final PackageState pkgState = vpkgs.valueAt(iv);
   1643                     final int NPROCS = pkgState.mProcesses.size();
   1644                     out.writeInt(NPROCS);
   1645                     for (int iproc=0; iproc<NPROCS; iproc++) {
   1646                         writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
   1647                         final ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   1648                         if (proc.mCommonProcess == proc) {
   1649                             // This is the same as the common process we wrote above.
   1650                             out.writeInt(0);
   1651                         } else {
   1652                             // There is separate data for this package's process.
   1653                             out.writeInt(1);
   1654                             proc.writeToParcel(out, now);
   1655                         }
   1656                     }
   1657                     final int NSRVS = pkgState.mServices.size();
   1658                     out.writeInt(NSRVS);
   1659                     for (int isvc=0; isvc<NSRVS; isvc++) {
   1660                         out.writeString(pkgState.mServices.keyAt(isvc));
   1661                         final ServiceState svc = pkgState.mServices.valueAt(isvc);
   1662                         writeCommonString(out, svc.mProcessName);
   1663                         svc.writeToParcel(out, now);
   1664                     }
   1665                 }
   1666             }
   1667         }
   1668 
   1669         mCommonStringToIndex = null;
   1670     }
   1671 
   1672     private boolean readCheckedInt(Parcel in, int val, String what) {
   1673         int got;
   1674         if ((got=in.readInt()) != val) {
   1675             mReadError = "bad " + what + ": " + got;
   1676             return false;
   1677         }
   1678         return true;
   1679     }
   1680 
   1681     static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
   1682         int pos = 0;
   1683         final int initialAvail = stream.available();
   1684         byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
   1685         while (true) {
   1686             int amt = stream.read(data, pos, data.length-pos);
   1687             if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
   1688                     + " of avail " + data.length);
   1689             if (amt < 0) {
   1690                 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
   1691                         + " len=" + data.length);
   1692                 outLen[0] = pos;
   1693                 return data;
   1694             }
   1695             pos += amt;
   1696             if (pos >= data.length) {
   1697                 byte[] newData = new byte[pos+16384];
   1698                 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
   1699                         + newData.length);
   1700                 System.arraycopy(data, 0, newData, 0, pos);
   1701                 data = newData;
   1702             }
   1703         }
   1704     }
   1705 
   1706     public void read(InputStream stream) {
   1707         try {
   1708             int[] len = new int[1];
   1709             byte[] raw = readFully(stream, len);
   1710             Parcel in = Parcel.obtain();
   1711             in.unmarshall(raw, 0, len[0]);
   1712             in.setDataPosition(0);
   1713             stream.close();
   1714 
   1715             readFromParcel(in);
   1716         } catch (IOException e) {
   1717             mReadError = "caught exception: " + e;
   1718         }
   1719     }
   1720 
   1721     public void readFromParcel(Parcel in) {
   1722         final boolean hadData = mPackages.getMap().size() > 0
   1723                 || mProcesses.getMap().size() > 0;
   1724         if (hadData) {
   1725             resetSafely();
   1726         }
   1727 
   1728         if (!readCheckedInt(in, MAGIC, "magic number")) {
   1729             return;
   1730         }
   1731         int version = in.readInt();
   1732         if (version != PARCEL_VERSION) {
   1733             mReadError = "bad version: " + version;
   1734             return;
   1735         }
   1736         if (!readCheckedInt(in, STATE_COUNT, "state count")) {
   1737             return;
   1738         }
   1739         if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
   1740             return;
   1741         }
   1742         if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
   1743             return;
   1744         }
   1745         if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) {
   1746             return;
   1747         }
   1748         if (!readCheckedInt(in, LONGS_SIZE, "longs size")) {
   1749             return;
   1750         }
   1751 
   1752         mIndexToCommonString = new ArrayList<String>();
   1753 
   1754         mTimePeriodStartClock = in.readLong();
   1755         buildTimePeriodStartClockStr();
   1756         mTimePeriodStartRealtime = in.readLong();
   1757         mTimePeriodEndRealtime = in.readLong();
   1758         mTimePeriodStartUptime = in.readLong();
   1759         mTimePeriodEndUptime = in.readLong();
   1760         mRuntime = in.readString();
   1761         mFlags = in.readInt();
   1762 
   1763         final int NLONGS = in.readInt();
   1764         final int NEXTLONG = in.readInt();
   1765         mLongs.clear();
   1766         for (int i=0; i<(NLONGS-1); i++) {
   1767             while (i >= mLongs.size()) {
   1768                 mLongs.add(new long[LONGS_SIZE]);
   1769             }
   1770             readCompactedLongArray(in, version, mLongs.get(i), LONGS_SIZE);
   1771         }
   1772         long[] longs = new long[LONGS_SIZE];
   1773         mNextLong = NEXTLONG;
   1774         readCompactedLongArray(in, version, longs, NEXTLONG);
   1775         mLongs.add(longs);
   1776 
   1777         readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length);
   1778 
   1779         mSysMemUsageTable = readTableFromParcel(in, TAG, "sys mem usage");
   1780         if (mSysMemUsageTable == BAD_TABLE) {
   1781             return;
   1782         }
   1783         mSysMemUsageTableSize = mSysMemUsageTable != null ? mSysMemUsageTable.length : 0;
   1784 
   1785         int NPROC = in.readInt();
   1786         if (NPROC < 0) {
   1787             mReadError = "bad process count: " + NPROC;
   1788             return;
   1789         }
   1790         while (NPROC > 0) {
   1791             NPROC--;
   1792             final String procName = readCommonString(in, version);
   1793             if (procName == null) {
   1794                 mReadError = "bad process name";
   1795                 return;
   1796             }
   1797             int NUID = in.readInt();
   1798             if (NUID < 0) {
   1799                 mReadError = "bad uid count: " + NUID;
   1800                 return;
   1801             }
   1802             while (NUID > 0) {
   1803                 NUID--;
   1804                 final int uid = in.readInt();
   1805                 if (uid < 0) {
   1806                     mReadError = "bad uid: " + uid;
   1807                     return;
   1808                 }
   1809                 final String pkgName = readCommonString(in, version);
   1810                 if (pkgName == null) {
   1811                     mReadError = "bad process package name";
   1812                     return;
   1813                 }
   1814                 final int vers = in.readInt();
   1815                 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
   1816                 if (proc != null) {
   1817                     if (!proc.readFromParcel(in, false)) {
   1818                         return;
   1819                     }
   1820                 } else {
   1821                     proc = new ProcessState(this, pkgName, uid, vers, procName);
   1822                     if (!proc.readFromParcel(in, true)) {
   1823                         return;
   1824                     }
   1825                 }
   1826                 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
   1827                         + " " + proc);
   1828                 mProcesses.put(procName, uid, proc);
   1829             }
   1830         }
   1831 
   1832         if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
   1833 
   1834         int NPKG = in.readInt();
   1835         if (NPKG < 0) {
   1836             mReadError = "bad package count: " + NPKG;
   1837             return;
   1838         }
   1839         while (NPKG > 0) {
   1840             NPKG--;
   1841             final String pkgName = readCommonString(in, version);
   1842             if (pkgName == null) {
   1843                 mReadError = "bad package name";
   1844                 return;
   1845             }
   1846             int NUID = in.readInt();
   1847             if (NUID < 0) {
   1848                 mReadError = "bad uid count: " + NUID;
   1849                 return;
   1850             }
   1851             while (NUID > 0) {
   1852                 NUID--;
   1853                 final int uid = in.readInt();
   1854                 if (uid < 0) {
   1855                     mReadError = "bad uid: " + uid;
   1856                     return;
   1857                 }
   1858                 int NVERS = in.readInt();
   1859                 if (NVERS < 0) {
   1860                     mReadError = "bad versions count: " + NVERS;
   1861                     return;
   1862                 }
   1863                 while (NVERS > 0) {
   1864                     NVERS--;
   1865                     final int vers = in.readInt();
   1866                     PackageState pkgState = new PackageState(pkgName, uid);
   1867                     SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid);
   1868                     if (vpkg == null) {
   1869                         vpkg = new SparseArray<PackageState>();
   1870                         mPackages.put(pkgName, uid, vpkg);
   1871                     }
   1872                     vpkg.put(vers, pkgState);
   1873                     int NPROCS = in.readInt();
   1874                     if (NPROCS < 0) {
   1875                         mReadError = "bad package process count: " + NPROCS;
   1876                         return;
   1877                     }
   1878                     while (NPROCS > 0) {
   1879                         NPROCS--;
   1880                         String procName = readCommonString(in, version);
   1881                         if (procName == null) {
   1882                             mReadError = "bad package process name";
   1883                             return;
   1884                         }
   1885                         int hasProc = in.readInt();
   1886                         if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
   1887                                 + " process " + procName + " hasProc=" + hasProc);
   1888                         ProcessState commonProc = mProcesses.get(procName, uid);
   1889                         if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
   1890                                 + ": " + commonProc);
   1891                         if (commonProc == null) {
   1892                             mReadError = "no common proc: " + procName;
   1893                             return;
   1894                         }
   1895                         if (hasProc != 0) {
   1896                             // The process for this package is unique to the package; we
   1897                             // need to load it.  We don't need to do anything about it if
   1898                             // it is not unique because if someone later looks for it
   1899                             // they will find and use it from the global procs.
   1900                             ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
   1901                             if (proc != null) {
   1902                                 if (!proc.readFromParcel(in, false)) {
   1903                                     return;
   1904                                 }
   1905                             } else {
   1906                                 proc = new ProcessState(commonProc, pkgName, uid, vers, procName,
   1907                                         0);
   1908                                 if (!proc.readFromParcel(in, true)) {
   1909                                     return;
   1910                                 }
   1911                             }
   1912                             if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
   1913                                     + procName + " " + uid + " " + proc);
   1914                             pkgState.mProcesses.put(procName, proc);
   1915                         } else {
   1916                             if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
   1917                                     + procName + " " + uid + " " + commonProc);
   1918                             pkgState.mProcesses.put(procName, commonProc);
   1919                         }
   1920                     }
   1921                     int NSRVS = in.readInt();
   1922                     if (NSRVS < 0) {
   1923                         mReadError = "bad package service count: " + NSRVS;
   1924                         return;
   1925                     }
   1926                     while (NSRVS > 0) {
   1927                         NSRVS--;
   1928                         String serviceName = in.readString();
   1929                         if (serviceName == null) {
   1930                             mReadError = "bad package service name";
   1931                             return;
   1932                         }
   1933                         String processName = version > 9 ? readCommonString(in, version) : null;
   1934                         ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
   1935                         if (serv == null) {
   1936                             serv = new ServiceState(this, pkgName, serviceName, processName, null);
   1937                         }
   1938                         if (!serv.readFromParcel(in)) {
   1939                             return;
   1940                         }
   1941                         if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
   1942                                 + serviceName + " " + uid + " " + serv);
   1943                         pkgState.mServices.put(serviceName, serv);
   1944                     }
   1945                 }
   1946             }
   1947         }
   1948 
   1949         mIndexToCommonString = null;
   1950 
   1951         if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
   1952     }
   1953 
   1954     int addLongData(int index, int type, int num) {
   1955         int off = allocLongData(num);
   1956         mAddLongTable = GrowingArrayUtils.insert(
   1957                 mAddLongTable != null ? mAddLongTable : EmptyArray.INT,
   1958                 mAddLongTableSize, index, type | off);
   1959         mAddLongTableSize++;
   1960         return off;
   1961     }
   1962 
   1963     int allocLongData(int num) {
   1964         int whichLongs = mLongs.size()-1;
   1965         long[] longs = mLongs.get(whichLongs);
   1966         if (mNextLong + num > longs.length) {
   1967             longs = new long[LONGS_SIZE];
   1968             mLongs.add(longs);
   1969             whichLongs++;
   1970             mNextLong = 0;
   1971         }
   1972         int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
   1973         mNextLong += num;
   1974         return off;
   1975     }
   1976 
   1977     boolean validateLongOffset(int off) {
   1978         int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK;
   1979         if (arr >= mLongs.size()) {
   1980             return false;
   1981         }
   1982         int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
   1983         if (idx >= LONGS_SIZE) {
   1984             return false;
   1985         }
   1986         if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off)
   1987                 + ": " + getLong(off, 0));
   1988         return true;
   1989     }
   1990 
   1991     static String printLongOffset(int off) {
   1992         StringBuilder sb = new StringBuilder(16);
   1993         sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   1994         sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK);
   1995         sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK);
   1996         return sb.toString();
   1997     }
   1998 
   1999     void setLong(int off, int index, long value) {
   2000         long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   2001         longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
   2002     }
   2003 
   2004     long getLong(int off, int index) {
   2005         long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   2006         return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
   2007     }
   2008 
   2009     static int binarySearch(int[] array, int size, int value) {
   2010         int lo = 0;
   2011         int hi = size - 1;
   2012 
   2013         while (lo <= hi) {
   2014             int mid = (lo + hi) >>> 1;
   2015             int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
   2016 
   2017             if (midVal < value) {
   2018                 lo = mid + 1;
   2019             } else if (midVal > value) {
   2020                 hi = mid - 1;
   2021             } else {
   2022                 return mid;  // value found
   2023             }
   2024         }
   2025         return ~lo;  // value not present
   2026     }
   2027 
   2028     public PackageState getPackageStateLocked(String packageName, int uid, int vers) {
   2029         SparseArray<PackageState> vpkg = mPackages.get(packageName, uid);
   2030         if (vpkg == null) {
   2031             vpkg = new SparseArray<PackageState>();
   2032             mPackages.put(packageName, uid, vpkg);
   2033         }
   2034         PackageState as = vpkg.get(vers);
   2035         if (as != null) {
   2036             return as;
   2037         }
   2038         as = new PackageState(packageName, uid);
   2039         vpkg.put(vers, as);
   2040         return as;
   2041     }
   2042 
   2043     public ProcessState getProcessStateLocked(String packageName, int uid, int vers,
   2044             String processName) {
   2045         final PackageState pkgState = getPackageStateLocked(packageName, uid, vers);
   2046         ProcessState ps = pkgState.mProcesses.get(processName);
   2047         if (ps != null) {
   2048             return ps;
   2049         }
   2050         ProcessState commonProc = mProcesses.get(processName, uid);
   2051         if (commonProc == null) {
   2052             commonProc = new ProcessState(this, packageName, uid, vers, processName);
   2053             mProcesses.put(processName, uid, commonProc);
   2054             if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
   2055         }
   2056         if (!commonProc.mMultiPackage) {
   2057             if (packageName.equals(commonProc.mPackage) && vers == commonProc.mVersion) {
   2058                 // This common process is not in use by multiple packages, and
   2059                 // is for the calling package, so we can just use it directly.
   2060                 ps = commonProc;
   2061                 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
   2062             } else {
   2063                 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
   2064                 // This common process has not been in use by multiple packages,
   2065                 // but it was created for a different package than the caller.
   2066                 // We need to convert it to a multi-package process.
   2067                 commonProc.mMultiPackage = true;
   2068                 // To do this, we need to make two new process states, one a copy
   2069                 // of the current state for the process under the original package
   2070                 // name, and the second a free new process state for it as the
   2071                 // new package name.
   2072                 long now = SystemClock.uptimeMillis();
   2073                 // First let's make a copy of the current process state and put
   2074                 // that under the now unique state for its original package name.
   2075                 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage,
   2076                         uid, commonProc.mVersion);
   2077                 if (commonPkgState != null) {
   2078                     ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
   2079                     if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
   2080                             + ": " + cloned);
   2081                     commonPkgState.mProcesses.put(commonProc.mName, cloned);
   2082                     // If this has active services, we need to update their process pointer
   2083                     // to point to the new package-specific process state.
   2084                     for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
   2085                         ServiceState ss = commonPkgState.mServices.valueAt(i);
   2086                         if (ss.mProc == commonProc) {
   2087                             if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
   2088                                     + ss);
   2089                             ss.mProc = cloned;
   2090                         } else if (DEBUG) {
   2091                             Slog.d(TAG, "GETPROC leaving proc of " + ss);
   2092                         }
   2093                     }
   2094                 } else {
   2095                     Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
   2096                             + "/" + uid + " for proc " + commonProc.mName);
   2097                 }
   2098                 // And now make a fresh new process state for the new package name.
   2099                 ps = new ProcessState(commonProc, packageName, uid, vers, processName, now);
   2100                 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
   2101             }
   2102         } else {
   2103             // The common process is for multiple packages, we need to create a
   2104             // separate object for the per-package data.
   2105             ps = new ProcessState(commonProc, packageName, uid, vers, processName,
   2106                     SystemClock.uptimeMillis());
   2107             if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
   2108         }
   2109         pkgState.mProcesses.put(processName, ps);
   2110         if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
   2111         return ps;
   2112     }
   2113 
   2114     public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid, int vers,
   2115             String processName, String className) {
   2116         final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers);
   2117         ProcessStats.ServiceState ss = as.mServices.get(className);
   2118         if (ss != null) {
   2119             if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
   2120             return ss;
   2121         }
   2122         final ProcessStats.ProcessState ps = processName != null
   2123                 ? getProcessStateLocked(packageName, uid, vers, processName) : null;
   2124         ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
   2125         as.mServices.put(className, ss);
   2126         if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
   2127         return ss;
   2128     }
   2129 
   2130     private void dumpProcessInternalLocked(PrintWriter pw, String prefix, ProcessState proc,
   2131             boolean dumpAll) {
   2132         if (dumpAll) {
   2133             pw.print(prefix); pw.print("myID=");
   2134                     pw.print(Integer.toHexString(System.identityHashCode(proc)));
   2135                     pw.print(" mCommonProcess=");
   2136                     pw.print(Integer.toHexString(System.identityHashCode(proc.mCommonProcess)));
   2137                     pw.print(" mPackage="); pw.println(proc.mPackage);
   2138             if (proc.mMultiPackage) {
   2139                 pw.print(prefix); pw.print("mMultiPackage="); pw.println(proc.mMultiPackage);
   2140             }
   2141             if (proc != proc.mCommonProcess) {
   2142                 pw.print(prefix); pw.print("Common Proc: "); pw.print(proc.mCommonProcess.mName);
   2143                         pw.print("/"); pw.print(proc.mCommonProcess.mUid);
   2144                         pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage);
   2145             }
   2146         }
   2147         if (proc.mActive) {
   2148             pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive);
   2149         }
   2150         if (proc.mDead) {
   2151             pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead);
   2152         }
   2153         if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) {
   2154             pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices);
   2155                     pw.print(" mNumStartedServices=");
   2156                     pw.println(proc.mNumStartedServices);
   2157         }
   2158     }
   2159 
   2160     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
   2161             boolean dumpAll, boolean activeOnly) {
   2162         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
   2163                 mStartTime, now);
   2164         boolean sepNeeded = false;
   2165         if (mSysMemUsageTable != null) {
   2166             pw.println("System memory usage:");
   2167             dumpSysMemUsage(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
   2168             sepNeeded = true;
   2169         }
   2170         ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   2171         boolean printedHeader = false;
   2172         for (int ip=0; ip<pkgMap.size(); ip++) {
   2173             final String pkgName = pkgMap.keyAt(ip);
   2174             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   2175             for (int iu=0; iu<uids.size(); iu++) {
   2176                 final int uid = uids.keyAt(iu);
   2177                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   2178                 for (int iv=0; iv<vpkgs.size(); iv++) {
   2179                     final int vers = vpkgs.keyAt(iv);
   2180                     final PackageState pkgState = vpkgs.valueAt(iv);
   2181                     final int NPROCS = pkgState.mProcesses.size();
   2182                     final int NSRVS = pkgState.mServices.size();
   2183                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
   2184                     if (!pkgMatch) {
   2185                         boolean procMatch = false;
   2186                         for (int iproc=0; iproc<NPROCS; iproc++) {
   2187                             ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2188                             if (reqPackage.equals(proc.mName)) {
   2189                                 procMatch = true;
   2190                                 break;
   2191                             }
   2192                         }
   2193                         if (!procMatch) {
   2194                             continue;
   2195                         }
   2196                     }
   2197                     if (NPROCS > 0 || NSRVS > 0) {
   2198                         if (!printedHeader) {
   2199                             if (sepNeeded) pw.println();
   2200                             pw.println("Per-Package Stats:");
   2201                             printedHeader = true;
   2202                             sepNeeded = true;
   2203                         }
   2204                         pw.print("  * "); pw.print(pkgName); pw.print(" / ");
   2205                                 UserHandle.formatUid(pw, uid); pw.print(" / v");
   2206                                 pw.print(vers); pw.println(":");
   2207                     }
   2208                     if (!dumpSummary || dumpAll) {
   2209                         for (int iproc=0; iproc<NPROCS; iproc++) {
   2210                             ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2211                             if (!pkgMatch && !reqPackage.equals(proc.mName)) {
   2212                                 continue;
   2213                             }
   2214                             if (activeOnly && !proc.isInUse()) {
   2215                                 pw.print("      (Not active: ");
   2216                                         pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
   2217                                 continue;
   2218                             }
   2219                             pw.print("      Process ");
   2220                             pw.print(pkgState.mProcesses.keyAt(iproc));
   2221                             if (proc.mCommonProcess.mMultiPackage) {
   2222                                 pw.print(" (multi, ");
   2223                             } else {
   2224                                 pw.print(" (unique, ");
   2225                             }
   2226                             pw.print(proc.mDurationsTableSize);
   2227                             pw.print(" entries)");
   2228                             pw.println(":");
   2229                             dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2230                                     ALL_PROC_STATES, now);
   2231                             dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2232                                     ALL_PROC_STATES);
   2233                             dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
   2234                         }
   2235                     } else {
   2236                         ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
   2237                         for (int iproc=0; iproc<NPROCS; iproc++) {
   2238                             ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2239                             if (!pkgMatch && !reqPackage.equals(proc.mName)) {
   2240                                 continue;
   2241                             }
   2242                             if (activeOnly && !proc.isInUse()) {
   2243                                 continue;
   2244                             }
   2245                             procs.add(proc);
   2246                         }
   2247                         dumpProcessSummaryLocked(pw, "      ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2248                                 NON_CACHED_PROC_STATES, false, now, totalTime);
   2249                     }
   2250                     for (int isvc=0; isvc<NSRVS; isvc++) {
   2251                         ServiceState svc = pkgState.mServices.valueAt(isvc);
   2252                         if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
   2253                             continue;
   2254                         }
   2255                         if (activeOnly && !svc.isInUse()) {
   2256                             pw.print("      (Not active: ");
   2257                                     pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
   2258                             continue;
   2259                         }
   2260                         if (dumpAll) {
   2261                             pw.print("      Service ");
   2262                         } else {
   2263                             pw.print("      * ");
   2264                         }
   2265                         pw.print(pkgState.mServices.keyAt(isvc));
   2266                         pw.println(":");
   2267                         pw.print("        Process: "); pw.println(svc.mProcessName);
   2268                         dumpServiceStats(pw, "        ", "          ", "    ", "Running", svc,
   2269                                 svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
   2270                                 svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll);
   2271                         dumpServiceStats(pw, "        ", "          ", "    ", "Started", svc,
   2272                                 svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState,
   2273                                 svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll);
   2274                         dumpServiceStats(pw, "        ", "          ", "      ", "Bound", svc,
   2275                                 svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState,
   2276                                 svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll);
   2277                         dumpServiceStats(pw, "        ", "          ", "  ", "Executing", svc,
   2278                                 svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
   2279                                 svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
   2280                         if (dumpAll) {
   2281                             if (svc.mOwner != null) {
   2282                                 pw.print("        mOwner="); pw.println(svc.mOwner);
   2283                             }
   2284                             if (svc.mStarted || svc.mRestarting) {
   2285                                 pw.print("        mStarted="); pw.print(svc.mStarted);
   2286                                 pw.print(" mRestarting="); pw.println(svc.mRestarting);
   2287                             }
   2288                         }
   2289                     }
   2290                 }
   2291             }
   2292         }
   2293 
   2294         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   2295         printedHeader = false;
   2296         int numShownProcs = 0, numTotalProcs = 0;
   2297         for (int ip=0; ip<procMap.size(); ip++) {
   2298             String procName = procMap.keyAt(ip);
   2299             SparseArray<ProcessState> uids = procMap.valueAt(ip);
   2300             for (int iu=0; iu<uids.size(); iu++) {
   2301                 int uid = uids.keyAt(iu);
   2302                 numTotalProcs++;
   2303                 ProcessState proc = uids.valueAt(iu);
   2304                 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
   2305                         && proc.mPssTableSize == 0) {
   2306                     continue;
   2307                 }
   2308                 if (!proc.mMultiPackage) {
   2309                     continue;
   2310                 }
   2311                 if (reqPackage != null && !reqPackage.equals(procName)
   2312                         && !reqPackage.equals(proc.mPackage)) {
   2313                     continue;
   2314                 }
   2315                 numShownProcs++;
   2316                 if (sepNeeded) {
   2317                     pw.println();
   2318                 }
   2319                 sepNeeded = true;
   2320                 if (!printedHeader) {
   2321                     pw.println("Multi-Package Common Processes:");
   2322                     printedHeader = true;
   2323                 }
   2324                 if (activeOnly && !proc.isInUse()) {
   2325                     pw.print("      (Not active: "); pw.print(procName); pw.println(")");
   2326                     continue;
   2327                 }
   2328                 pw.print("  * "); pw.print(procName); pw.print(" / ");
   2329                         UserHandle.formatUid(pw, uid);
   2330                         pw.print(" ("); pw.print(proc.mDurationsTableSize);
   2331                         pw.print(" entries)"); pw.println(":");
   2332                 dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2333                         ALL_PROC_STATES, now);
   2334                 dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2335                         ALL_PROC_STATES);
   2336                 dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
   2337             }
   2338         }
   2339         if (dumpAll) {
   2340             pw.println();
   2341             pw.print("  Total procs: "); pw.print(numShownProcs);
   2342                     pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
   2343         }
   2344 
   2345         if (sepNeeded) {
   2346             pw.println();
   2347         }
   2348         if (dumpSummary) {
   2349             pw.println("Summary:");
   2350             dumpSummaryLocked(pw, reqPackage, now, activeOnly);
   2351         } else {
   2352             dumpTotalsLocked(pw, now);
   2353         }
   2354 
   2355         if (dumpAll) {
   2356             pw.println();
   2357             pw.println("Internal state:");
   2358             pw.print("  Num long arrays: "); pw.println(mLongs.size());
   2359             pw.print("  Next long entry: "); pw.println(mNextLong);
   2360             pw.print("  mRunning="); pw.println(mRunning);
   2361         }
   2362     }
   2363 
   2364     public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
   2365             int serviceType, int curState, long curStartTime, long now) {
   2366         long totalTime = 0;
   2367         int printedScreen = -1;
   2368         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
   2369             int printedMem = -1;
   2370             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
   2371                 int state = imem+iscreen;
   2372                 long time = service.getDuration(serviceType, curState, curStartTime,
   2373                         state, now);
   2374                 String running = "";
   2375                 if (curState == state && pw != null) {
   2376                     running = " (running)";
   2377                 }
   2378                 if (time != 0) {
   2379                     if (pw != null) {
   2380                         pw.print(prefix);
   2381                         printScreenLabel(pw, printedScreen != iscreen
   2382                                 ? iscreen : STATE_NOTHING);
   2383                         printedScreen = iscreen;
   2384                         printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
   2385                         printedMem = imem;
   2386                         pw.print(": ");
   2387                         TimeUtils.formatDuration(time, pw); pw.println(running);
   2388                     }
   2389                     totalTime += time;
   2390                 }
   2391             }
   2392         }
   2393         if (totalTime != 0 && pw != null) {
   2394             pw.print(prefix);
   2395             pw.print("    TOTAL: ");
   2396             TimeUtils.formatDuration(totalTime, pw);
   2397             pw.println();
   2398         }
   2399         return totalTime;
   2400     }
   2401 
   2402     void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner,
   2403             String headerPrefix, String header, ServiceState service,
   2404             int count, int serviceType, int state, long startTime, long now, long totalTime,
   2405             boolean dumpAll) {
   2406         if (count != 0) {
   2407             if (dumpAll) {
   2408                 pw.print(prefix); pw.print(header);
   2409                 pw.print(" op count "); pw.print(count); pw.println(":");
   2410                 dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime,
   2411                         now);
   2412             } else {
   2413                 long myTime = dumpSingleServiceTime(null, null, service, serviceType, state,
   2414                         startTime, now);
   2415                 pw.print(prefix); pw.print(headerPrefix); pw.print(header);
   2416                 pw.print(" count "); pw.print(count);
   2417                 pw.print(" / time ");
   2418                 printPercent(pw, (double)myTime/(double)totalTime);
   2419                 pw.println();
   2420             }
   2421         }
   2422     }
   2423 
   2424     public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
   2425         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
   2426                 mStartTime, now);
   2427         dumpFilteredSummaryLocked(pw, null, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
   2428                 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
   2429         pw.println();
   2430         dumpTotalsLocked(pw, now);
   2431     }
   2432 
   2433     long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight,
   2434             long totalTime, long curTotalMem, int samples) {
   2435         if (memWeight != 0) {
   2436             long mem = (long)(memWeight * 1024 / totalTime);
   2437             pw.print(prefix);
   2438             pw.print(label);
   2439             pw.print(": ");
   2440             printSizeValue(pw, mem);
   2441             pw.print(" (");
   2442             pw.print(samples);
   2443             pw.print(" samples)");
   2444             pw.println();
   2445             return curTotalMem + mem;
   2446         }
   2447         return curTotalMem;
   2448     }
   2449 
   2450     void dumpTotalsLocked(PrintWriter pw, long now) {
   2451         pw.println("Run time Stats:");
   2452         dumpSingleTime(pw, "  ", mMemFactorDurations, mMemFactor, mStartTime, now);
   2453         pw.println();
   2454         pw.println("Memory usage:");
   2455         TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
   2456                 ALL_MEM_ADJ);
   2457         computeTotalMemoryUse(totalMem, now);
   2458         long totalPss = 0;
   2459         totalPss = printMemoryCategory(pw, "  ", "Kernel ", totalMem.sysMemKernelWeight,
   2460                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2461         totalPss = printMemoryCategory(pw, "  ", "Native ", totalMem.sysMemNativeWeight,
   2462                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2463         for (int i=0; i<STATE_COUNT; i++) {
   2464             // Skip restarting service state -- that is not actually a running process.
   2465             if (i != STATE_SERVICE_RESTARTING) {
   2466                 totalPss = printMemoryCategory(pw, "  ", STATE_NAMES[i],
   2467                         totalMem.processStateWeight[i], totalMem.totalTime, totalPss,
   2468                         totalMem.processStateSamples[i]);
   2469             }
   2470         }
   2471         totalPss = printMemoryCategory(pw, "  ", "Cached ", totalMem.sysMemCachedWeight,
   2472                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2473         totalPss = printMemoryCategory(pw, "  ", "Free   ", totalMem.sysMemFreeWeight,
   2474                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2475         totalPss = printMemoryCategory(pw, "  ", "Z-Ram  ", totalMem.sysMemZRamWeight,
   2476                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
   2477         pw.print("  TOTAL  : ");
   2478         printSizeValue(pw, totalPss);
   2479         pw.println();
   2480         printMemoryCategory(pw, "  ", STATE_NAMES[STATE_SERVICE_RESTARTING],
   2481                 totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss,
   2482                 totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
   2483         pw.println();
   2484         pw.print("          Start time: ");
   2485         pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
   2486         pw.println();
   2487         pw.print("  Total elapsed time: ");
   2488         TimeUtils.formatDuration(
   2489                 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
   2490                         - mTimePeriodStartRealtime, pw);
   2491         boolean partial = true;
   2492         if ((mFlags&FLAG_SHUTDOWN) != 0) {
   2493             pw.print(" (shutdown)");
   2494             partial = false;
   2495         }
   2496         if ((mFlags&FLAG_SYSPROPS) != 0) {
   2497             pw.print(" (sysprops)");
   2498             partial = false;
   2499         }
   2500         if ((mFlags&FLAG_COMPLETE) != 0) {
   2501             pw.print(" (complete)");
   2502             partial = false;
   2503         }
   2504         if (partial) {
   2505             pw.print(" (partial)");
   2506         }
   2507         pw.print(' ');
   2508         pw.print(mRuntime);
   2509         pw.println();
   2510     }
   2511 
   2512     void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
   2513             int[] screenStates, int[] memStates, int[] procStates,
   2514             int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
   2515         ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
   2516                 procStates, sortProcStates, now, reqPackage, activeOnly);
   2517         if (procs.size() > 0) {
   2518             if (header != null) {
   2519                 pw.println();
   2520                 pw.println(header);
   2521             }
   2522             dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
   2523                     sortProcStates, true, now, totalTime);
   2524         }
   2525     }
   2526 
   2527     public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
   2528             int[] procStates, int sortProcStates[], long now, String reqPackage,
   2529             boolean activeOnly) {
   2530         final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
   2531         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   2532         for (int ip=0; ip<pkgMap.size(); ip++) {
   2533             final String pkgName = pkgMap.keyAt(ip);
   2534             final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip);
   2535             for (int iu=0; iu<procs.size(); iu++) {
   2536                 final SparseArray<PackageState> vpkgs = procs.valueAt(iu);
   2537                 final int NVERS = vpkgs.size();
   2538                 for (int iv=0; iv<NVERS; iv++) {
   2539                     final PackageState state = vpkgs.valueAt(iv);
   2540                     final int NPROCS = state.mProcesses.size();
   2541                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
   2542                     for (int iproc=0; iproc<NPROCS; iproc++) {
   2543                         final ProcessState proc = state.mProcesses.valueAt(iproc);
   2544                         if (!pkgMatch && !reqPackage.equals(proc.mName)) {
   2545                             continue;
   2546                         }
   2547                         if (activeOnly && !proc.isInUse()) {
   2548                             continue;
   2549                         }
   2550                         foundProcs.add(proc.mCommonProcess);
   2551                     }
   2552                 }
   2553             }
   2554         }
   2555         ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
   2556         for (int i=0; i<foundProcs.size(); i++) {
   2557             ProcessState proc = foundProcs.valueAt(i);
   2558             if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
   2559                 outProcs.add(proc);
   2560                 if (procStates != sortProcStates) {
   2561                     computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
   2562                 }
   2563             }
   2564         }
   2565         Collections.sort(outProcs, new Comparator<ProcessState>() {
   2566             @Override
   2567             public int compare(ProcessState lhs, ProcessState rhs) {
   2568                 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
   2569                     return -1;
   2570                 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
   2571                     return 1;
   2572                 }
   2573                 return 0;
   2574             }
   2575         });
   2576         return outProcs;
   2577     }
   2578 
   2579     String collapseString(String pkgName, String itemName) {
   2580         if (itemName.startsWith(pkgName)) {
   2581             final int ITEMLEN = itemName.length();
   2582             final int PKGLEN = pkgName.length();
   2583             if (ITEMLEN == PKGLEN) {
   2584                 return "";
   2585             } else if (ITEMLEN >= PKGLEN) {
   2586                 if (itemName.charAt(PKGLEN) == '.') {
   2587                     return itemName.substring(PKGLEN);
   2588                 }
   2589             }
   2590         }
   2591         return itemName;
   2592     }
   2593 
   2594     public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
   2595         final long now = SystemClock.uptimeMillis();
   2596         final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
   2597         pw.println("vers,5");
   2598         pw.print("period,"); pw.print(mTimePeriodStartClockStr);
   2599         pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
   2600         pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
   2601         boolean partial = true;
   2602         if ((mFlags&FLAG_SHUTDOWN) != 0) {
   2603             pw.print(",shutdown");
   2604             partial = false;
   2605         }
   2606         if ((mFlags&FLAG_SYSPROPS) != 0) {
   2607             pw.print(",sysprops");
   2608             partial = false;
   2609         }
   2610         if ((mFlags&FLAG_COMPLETE) != 0) {
   2611             pw.print(",complete");
   2612             partial = false;
   2613         }
   2614         if (partial) {
   2615             pw.print(",partial");
   2616         }
   2617         pw.println();
   2618         pw.print("config,"); pw.println(mRuntime);
   2619         for (int ip=0; ip<pkgMap.size(); ip++) {
   2620             final String pkgName = pkgMap.keyAt(ip);
   2621             if (reqPackage != null && !reqPackage.equals(pkgName)) {
   2622                 continue;
   2623             }
   2624             final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
   2625             for (int iu=0; iu<uids.size(); iu++) {
   2626                 final int uid = uids.keyAt(iu);
   2627                 final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
   2628                 for (int iv=0; iv<vpkgs.size(); iv++) {
   2629                     final int vers = vpkgs.keyAt(iv);
   2630                     final PackageState pkgState = vpkgs.valueAt(iv);
   2631                     final int NPROCS = pkgState.mProcesses.size();
   2632                     final int NSRVS = pkgState.mServices.size();
   2633                     for (int iproc=0; iproc<NPROCS; iproc++) {
   2634                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
   2635                         pw.print("pkgproc,");
   2636                         pw.print(pkgName);
   2637                         pw.print(",");
   2638                         pw.print(uid);
   2639                         pw.print(",");
   2640                         pw.print(vers);
   2641                         pw.print(",");
   2642                         pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
   2643                         dumpAllProcessStateCheckin(pw, proc, now);
   2644                         pw.println();
   2645                         if (proc.mPssTableSize > 0) {
   2646                             pw.print("pkgpss,");
   2647                             pw.print(pkgName);
   2648                             pw.print(",");
   2649                             pw.print(uid);
   2650                             pw.print(",");
   2651                             pw.print(vers);
   2652                             pw.print(",");
   2653                             pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
   2654                             dumpAllProcessPssCheckin(pw, proc);
   2655                             pw.println();
   2656                         }
   2657                         if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0
   2658                                 || proc.mNumCachedKill > 0) {
   2659                             pw.print("pkgkills,");
   2660                             pw.print(pkgName);
   2661                             pw.print(",");
   2662                             pw.print(uid);
   2663                             pw.print(",");
   2664                             pw.print(vers);
   2665                             pw.print(",");
   2666                             pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
   2667                             pw.print(",");
   2668                             pw.print(proc.mNumExcessiveWake);
   2669                             pw.print(",");
   2670                             pw.print(proc.mNumExcessiveCpu);
   2671                             pw.print(",");
   2672                             pw.print(proc.mNumCachedKill);
   2673                             pw.print(",");
   2674                             pw.print(proc.mMinCachedKillPss);
   2675                             pw.print(":");
   2676                             pw.print(proc.mAvgCachedKillPss);
   2677                             pw.print(":");
   2678                             pw.print(proc.mMaxCachedKillPss);
   2679                             pw.println();
   2680                         }
   2681                     }
   2682                     for (int isvc=0; isvc<NSRVS; isvc++) {
   2683                         String serviceName = collapseString(pkgName,
   2684                                 pkgState.mServices.keyAt(isvc));
   2685                         ServiceState svc = pkgState.mServices.valueAt(isvc);
   2686                         dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, vers, serviceName,
   2687                                 svc, ServiceState.SERVICE_RUN, svc.mRunCount,
   2688                                 svc.mRunState, svc.mRunStartTime, now);
   2689                         dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName,
   2690                                 svc, ServiceState.SERVICE_STARTED, svc.mStartedCount,
   2691                                 svc.mStartedState, svc.mStartedStartTime, now);
   2692                         dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName,
   2693                                 svc, ServiceState.SERVICE_BOUND, svc.mBoundCount,
   2694                                 svc.mBoundState, svc.mBoundStartTime, now);
   2695                         dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName,
   2696                                 svc, ServiceState.SERVICE_EXEC, svc.mExecCount,
   2697                                 svc.mExecState, svc.mExecStartTime, now);
   2698                     }
   2699                 }
   2700             }
   2701         }
   2702 
   2703         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
   2704         for (int ip=0; ip<procMap.size(); ip++) {
   2705             String procName = procMap.keyAt(ip);
   2706             SparseArray<ProcessState> uids = procMap.valueAt(ip);
   2707             for (int iu=0; iu<uids.size(); iu++) {
   2708                 int uid = uids.keyAt(iu);
   2709                 ProcessState procState = uids.valueAt(iu);
   2710                 if (procState.mDurationsTableSize > 0) {
   2711                     pw.print("proc,");
   2712                     pw.print(procName);
   2713                     pw.print(",");
   2714                     pw.print(uid);
   2715                     dumpAllProcessStateCheckin(pw, procState, now);
   2716                     pw.println();
   2717                 }
   2718                 if (procState.mPssTableSize > 0) {
   2719                     pw.print("pss,");
   2720                     pw.print(procName);
   2721                     pw.print(",");
   2722                     pw.print(uid);
   2723                     dumpAllProcessPssCheckin(pw, procState);
   2724                     pw.println();
   2725                 }
   2726                 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0
   2727                         || procState.mNumCachedKill > 0) {
   2728                     pw.print("kills,");
   2729                     pw.print(procName);
   2730                     pw.print(",");
   2731                     pw.print(uid);
   2732                     pw.print(",");
   2733                     pw.print(procState.mNumExcessiveWake);
   2734                     pw.print(",");
   2735                     pw.print(procState.mNumExcessiveCpu);
   2736                     pw.print(",");
   2737                     pw.print(procState.mNumCachedKill);
   2738                     pw.print(",");
   2739                     pw.print(procState.mMinCachedKillPss);
   2740                     pw.print(":");
   2741                     pw.print(procState.mAvgCachedKillPss);
   2742                     pw.print(":");
   2743                     pw.print(procState.mMaxCachedKillPss);
   2744                     pw.println();
   2745                 }
   2746             }
   2747         }
   2748         pw.print("total");
   2749         dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor,
   2750                 mStartTime, now);
   2751         pw.println();
   2752         if (mSysMemUsageTable != null) {
   2753             pw.print("sysmemusage");
   2754             for (int i=0; i<mSysMemUsageTableSize; i++) {
   2755                 int off = mSysMemUsageTable[i];
   2756                 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2757                 pw.print(",");
   2758                 printProcStateTag(pw, type);
   2759                 for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) {
   2760                     if (j > SYS_MEM_USAGE_CACHED_MINIMUM) {
   2761                         pw.print(":");
   2762                     }
   2763                     pw.print(getLong(off, j));
   2764                 }
   2765             }
   2766         }
   2767         pw.println();
   2768         TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
   2769                 ALL_MEM_ADJ);
   2770         computeTotalMemoryUse(totalMem, now);
   2771         pw.print("weights,");
   2772         pw.print(totalMem.totalTime);
   2773         pw.print(",");
   2774         pw.print(totalMem.sysMemCachedWeight);
   2775         pw.print(":");
   2776         pw.print(totalMem.sysMemSamples);
   2777         pw.print(",");
   2778         pw.print(totalMem.sysMemFreeWeight);
   2779         pw.print(":");
   2780         pw.print(totalMem.sysMemSamples);
   2781         pw.print(",");
   2782         pw.print(totalMem.sysMemZRamWeight);
   2783         pw.print(":");
   2784         pw.print(totalMem.sysMemSamples);
   2785         pw.print(",");
   2786         pw.print(totalMem.sysMemKernelWeight);
   2787         pw.print(":");
   2788         pw.print(totalMem.sysMemSamples);
   2789         pw.print(",");
   2790         pw.print(totalMem.sysMemNativeWeight);
   2791         pw.print(":");
   2792         pw.print(totalMem.sysMemSamples);
   2793         for (int i=0; i<STATE_COUNT; i++) {
   2794             pw.print(",");
   2795             pw.print(totalMem.processStateWeight[i]);
   2796             pw.print(":");
   2797             pw.print(totalMem.processStateSamples[i]);
   2798         }
   2799         pw.println();
   2800     }
   2801 
   2802     public static class DurationsTable {
   2803         public final ProcessStats mStats;
   2804         public final String mName;
   2805         public int[] mDurationsTable;
   2806         public int mDurationsTableSize;
   2807 
   2808         public DurationsTable(ProcessStats stats, String name) {
   2809             mStats = stats;
   2810             mName = name;
   2811         }
   2812 
   2813         void copyDurationsTo(DurationsTable other) {
   2814             if (mDurationsTable != null) {
   2815                 mStats.mAddLongTable = new int[mDurationsTable.length];
   2816                 mStats.mAddLongTableSize = 0;
   2817                 for (int i=0; i<mDurationsTableSize; i++) {
   2818                     int origEnt = mDurationsTable[i];
   2819                     int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2820                     int newOff = mStats.addLongData(i, type, 1);
   2821                     mStats.mAddLongTable[i] = newOff | type;
   2822                     mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0));
   2823                 }
   2824                 other.mDurationsTable = mStats.mAddLongTable;
   2825                 other.mDurationsTableSize = mStats.mAddLongTableSize;
   2826             } else {
   2827                 other.mDurationsTable = null;
   2828                 other.mDurationsTableSize = 0;
   2829             }
   2830         }
   2831 
   2832         void addDurations(DurationsTable other) {
   2833             for (int i=0; i<other.mDurationsTableSize; i++) {
   2834                 int ent = other.mDurationsTable[i];
   2835                 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2836                 if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
   2837                         + other.mStats.getLong(ent, 0));
   2838                 addDuration(state, other.mStats.getLong(ent, 0));
   2839             }
   2840         }
   2841 
   2842         void resetDurationsSafely() {
   2843             mDurationsTable = null;
   2844             mDurationsTableSize = 0;
   2845         }
   2846 
   2847         void writeDurationsToParcel(Parcel out) {
   2848             out.writeInt(mDurationsTableSize);
   2849             for (int i=0; i<mDurationsTableSize; i++) {
   2850                 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
   2851                         + printLongOffset(mDurationsTable[i]));
   2852                 out.writeInt(mDurationsTable[i]);
   2853             }
   2854         }
   2855 
   2856         boolean readDurationsFromParcel(Parcel in) {
   2857             mDurationsTable = mStats.readTableFromParcel(in, mName, "durations");
   2858             if (mDurationsTable == BAD_TABLE) {
   2859                 return false;
   2860             }
   2861             mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
   2862             return true;
   2863         }
   2864 
   2865         void addDuration(int state, long dur) {
   2866             int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
   2867             int off;
   2868             if (idx >= 0) {
   2869                 off = mDurationsTable[idx];
   2870             } else {
   2871                 mStats.mAddLongTable = mDurationsTable;
   2872                 mStats.mAddLongTableSize = mDurationsTableSize;
   2873                 off = mStats.addLongData(~idx, state, 1);
   2874                 mDurationsTable = mStats.mAddLongTable;
   2875                 mDurationsTableSize = mStats.mAddLongTableSize;
   2876             }
   2877             long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   2878             if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
   2879                     + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
   2880             longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
   2881         }
   2882 
   2883         long getDuration(int state, long now) {
   2884             int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
   2885             return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
   2886         }
   2887     }
   2888 
   2889     final public static class ProcessStateHolder {
   2890         public final int appVersion;
   2891         public ProcessStats.ProcessState state;
   2892 
   2893         public ProcessStateHolder(int _appVersion) {
   2894             appVersion = _appVersion;
   2895         }
   2896     }
   2897 
   2898     public static final class ProcessState extends DurationsTable {
   2899         public ProcessState mCommonProcess;
   2900         public final String mPackage;
   2901         public final int mUid;
   2902         public final int mVersion;
   2903 
   2904         //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
   2905         int mCurState = STATE_NOTHING;
   2906         long mStartTime;
   2907 
   2908         int mLastPssState = STATE_NOTHING;
   2909         long mLastPssTime;
   2910         int[] mPssTable;
   2911         int mPssTableSize;
   2912 
   2913         boolean mActive;
   2914         int mNumActiveServices;
   2915         int mNumStartedServices;
   2916 
   2917         int mNumExcessiveWake;
   2918         int mNumExcessiveCpu;
   2919 
   2920         int mNumCachedKill;
   2921         long mMinCachedKillPss;
   2922         long mAvgCachedKillPss;
   2923         long mMaxCachedKillPss;
   2924 
   2925         boolean mMultiPackage;
   2926         boolean mDead;
   2927 
   2928         public long mTmpTotalTime;
   2929         int mTmpNumInUse;
   2930         ProcessState mTmpFoundSubProc;
   2931 
   2932         /**
   2933          * Create a new top-level process state, for the initial case where there is only
   2934          * a single package running in a process.  The initial state is not running.
   2935          */
   2936         public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) {
   2937             super(processStats, name);
   2938             mCommonProcess = this;
   2939             mPackage = pkg;
   2940             mUid = uid;
   2941             mVersion = vers;
   2942         }
   2943 
   2944         /**
   2945          * Create a new per-package process state for an existing top-level process
   2946          * state.  The current running state of the top-level process is also copied,
   2947          * marked as started running at 'now'.
   2948          */
   2949         public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name,
   2950                 long now) {
   2951             super(commonProcess.mStats, name);
   2952             mCommonProcess = commonProcess;
   2953             mPackage = pkg;
   2954             mUid = uid;
   2955             mVersion = vers;
   2956             mCurState = commonProcess.mCurState;
   2957             mStartTime = now;
   2958         }
   2959 
   2960         ProcessState clone(String pkg, long now) {
   2961             ProcessState pnew = new ProcessState(this, pkg, mUid, mVersion, mName, now);
   2962             copyDurationsTo(pnew);
   2963             if (mPssTable != null) {
   2964                 mStats.mAddLongTable = new int[mPssTable.length];
   2965                 mStats.mAddLongTableSize = 0;
   2966                 for (int i=0; i<mPssTableSize; i++) {
   2967                     int origEnt = mPssTable[i];
   2968                     int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2969                     int newOff = mStats.addLongData(i, type, PSS_COUNT);
   2970                     mStats.mAddLongTable[i] = newOff | type;
   2971                     for (int j=0; j<PSS_COUNT; j++) {
   2972                         mStats.setLong(newOff, j, mStats.getLong(origEnt, j));
   2973                     }
   2974                 }
   2975                 pnew.mPssTable = mStats.mAddLongTable;
   2976                 pnew.mPssTableSize = mStats.mAddLongTableSize;
   2977             }
   2978             pnew.mNumExcessiveWake = mNumExcessiveWake;
   2979             pnew.mNumExcessiveCpu = mNumExcessiveCpu;
   2980             pnew.mNumCachedKill = mNumCachedKill;
   2981             pnew.mMinCachedKillPss = mMinCachedKillPss;
   2982             pnew.mAvgCachedKillPss = mAvgCachedKillPss;
   2983             pnew.mMaxCachedKillPss = mMaxCachedKillPss;
   2984             pnew.mActive = mActive;
   2985             pnew.mNumActiveServices = mNumActiveServices;
   2986             pnew.mNumStartedServices = mNumStartedServices;
   2987             return pnew;
   2988         }
   2989 
   2990         void add(ProcessState other) {
   2991             addDurations(other);
   2992             for (int i=0; i<other.mPssTableSize; i++) {
   2993                 int ent = other.mPssTable[i];
   2994                 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
   2995                 addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
   2996                         other.mStats.getLong(ent, PSS_MINIMUM),
   2997                         other.mStats.getLong(ent, PSS_AVERAGE),
   2998                         other.mStats.getLong(ent, PSS_MAXIMUM),
   2999                         other.mStats.getLong(ent, PSS_USS_MINIMUM),
   3000                         other.mStats.getLong(ent, PSS_USS_AVERAGE),
   3001                         other.mStats.getLong(ent, PSS_USS_MAXIMUM));
   3002             }
   3003             mNumExcessiveWake += other.mNumExcessiveWake;
   3004             mNumExcessiveCpu += other.mNumExcessiveCpu;
   3005             if (other.mNumCachedKill > 0) {
   3006                 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
   3007                         other.mAvgCachedKillPss, other.mMaxCachedKillPss);
   3008             }
   3009         }
   3010 
   3011         void resetSafely(long now) {
   3012             resetDurationsSafely();
   3013             mStartTime = now;
   3014             mLastPssState = STATE_NOTHING;
   3015             mLastPssTime = 0;
   3016             mPssTable = null;
   3017             mPssTableSize = 0;
   3018             mNumExcessiveWake = 0;
   3019             mNumExcessiveCpu = 0;
   3020             mNumCachedKill = 0;
   3021             mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
   3022         }
   3023 
   3024         void makeDead() {
   3025             mDead = true;
   3026         }
   3027 
   3028         private void ensureNotDead() {
   3029             if (!mDead) {
   3030                 return;
   3031             }
   3032             Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
   3033                     + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
   3034         }
   3035 
   3036         void writeToParcel(Parcel out, long now) {
   3037             out.writeInt(mMultiPackage ? 1 : 0);
   3038             writeDurationsToParcel(out);
   3039             out.writeInt(mPssTableSize);
   3040             for (int i=0; i<mPssTableSize; i++) {
   3041                 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
   3042                         + printLongOffset(mPssTable[i]));
   3043                 out.writeInt(mPssTable[i]);
   3044             }
   3045             out.writeInt(mNumExcessiveWake);
   3046             out.writeInt(mNumExcessiveCpu);
   3047             out.writeInt(mNumCachedKill);
   3048             if (mNumCachedKill > 0) {
   3049                 out.writeLong(mMinCachedKillPss);
   3050                 out.writeLong(mAvgCachedKillPss);
   3051                 out.writeLong(mMaxCachedKillPss);
   3052             }
   3053         }
   3054 
   3055         boolean readFromParcel(Parcel in, boolean fully) {
   3056             boolean multiPackage = in.readInt() != 0;
   3057             if (fully) {
   3058                 mMultiPackage = multiPackage;
   3059             }
   3060             if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
   3061             if (!readDurationsFromParcel(in)) {
   3062                 return false;
   3063             }
   3064             if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
   3065             mPssTable = mStats.readTableFromParcel(in, mName, "pss");
   3066             if (mPssTable == BAD_TABLE) {
   3067                 return false;
   3068             }
   3069             mPssTableSize = mPssTable != null ? mPssTable.length : 0;
   3070             mNumExcessiveWake = in.readInt();
   3071             mNumExcessiveCpu = in.readInt();
   3072             mNumCachedKill = in.readInt();
   3073             if (mNumCachedKill > 0) {
   3074                 mMinCachedKillPss = in.readLong();
   3075                 mAvgCachedKillPss = in.readLong();
   3076                 mMaxCachedKillPss = in.readLong();
   3077             } else {
   3078                 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
   3079             }
   3080             return true;
   3081         }
   3082 
   3083         public void makeActive() {
   3084             ensureNotDead();
   3085             mActive = true;
   3086         }
   3087 
   3088         public void makeInactive() {
   3089             mActive = false;
   3090         }
   3091 
   3092         public boolean isInUse() {
   3093             return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
   3094                     || mCurState != STATE_NOTHING;
   3095         }
   3096 
   3097         /**
   3098          * Update the current state of the given list of processes.
   3099          *
   3100          * @param state Current ActivityManager.PROCESS_STATE_*
   3101          * @param memFactor Current mem factor constant.
   3102          * @param now Current time.
   3103          * @param pkgList Processes to update.
   3104          */
   3105         public void setState(int state, int memFactor, long now,
   3106                 ArrayMap<String, ProcessStateHolder> pkgList) {
   3107             if (state < 0) {
   3108                 state = mNumStartedServices > 0
   3109                         ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
   3110             } else {
   3111                 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
   3112             }
   3113 
   3114             // First update the common process.
   3115             mCommonProcess.setState(state, now);
   3116 
   3117             // If the common process is not multi-package, there is nothing else to do.
   3118             if (!mCommonProcess.mMultiPackage) {
   3119                 return;
   3120             }
   3121 
   3122             if (pkgList != null) {
   3123                 for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3124                     pullFixedProc(pkgList, ip).setState(state, now);
   3125                 }
   3126             }
   3127         }
   3128 
   3129         void setState(int state, long now) {
   3130             ensureNotDead();
   3131             if (mCurState != state) {
   3132                 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
   3133                 commitStateTime(now);
   3134                 mCurState = state;
   3135             }
   3136         }
   3137 
   3138         void commitStateTime(long now) {
   3139             if (mCurState != STATE_NOTHING) {
   3140                 long dur = now - mStartTime;
   3141                 if (dur > 0) {
   3142                     addDuration(mCurState, dur);
   3143                 }
   3144             }
   3145             mStartTime = now;
   3146         }
   3147 
   3148         void incActiveServices(String serviceName) {
   3149             if (DEBUG && "".equals(mName)) {
   3150                 RuntimeException here = new RuntimeException("here");
   3151                 here.fillInStackTrace();
   3152                 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
   3153                         + " to " + (mNumActiveServices+1), here);
   3154             }
   3155             if (mCommonProcess != this) {
   3156                 mCommonProcess.incActiveServices(serviceName);
   3157             }
   3158             mNumActiveServices++;
   3159         }
   3160 
   3161         void decActiveServices(String serviceName) {
   3162             if (DEBUG && "".equals(mName)) {
   3163                 RuntimeException here = new RuntimeException("here");
   3164                 here.fillInStackTrace();
   3165                 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
   3166                         + " to " + (mNumActiveServices-1), here);
   3167             }
   3168             if (mCommonProcess != this) {
   3169                 mCommonProcess.decActiveServices(serviceName);
   3170             }
   3171             mNumActiveServices--;
   3172             if (mNumActiveServices < 0) {
   3173                 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
   3174                         + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
   3175                 mNumActiveServices = 0;
   3176             }
   3177         }
   3178 
   3179         void incStartedServices(int memFactor, long now, String serviceName) {
   3180             if (false) {
   3181                 RuntimeException here = new RuntimeException("here");
   3182                 here.fillInStackTrace();
   3183                 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
   3184                         + " to " + (mNumStartedServices+1), here);
   3185             }
   3186             if (mCommonProcess != this) {
   3187                 mCommonProcess.incStartedServices(memFactor, now, serviceName);
   3188             }
   3189             mNumStartedServices++;
   3190             if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
   3191                 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
   3192             }
   3193         }
   3194 
   3195         void decStartedServices(int memFactor, long now, String serviceName) {
   3196             if (false) {
   3197                 RuntimeException here = new RuntimeException("here");
   3198                 here.fillInStackTrace();
   3199                 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
   3200                         + " to " + (mNumStartedServices-1), here);
   3201             }
   3202             if (mCommonProcess != this) {
   3203                 mCommonProcess.decStartedServices(memFactor, now, serviceName);
   3204             }
   3205             mNumStartedServices--;
   3206             if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
   3207                 setState(STATE_NOTHING, now);
   3208             } else if (mNumStartedServices < 0) {
   3209                 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
   3210                         + mPackage + " uid=" + mUid + " name=" + mName);
   3211                 mNumStartedServices = 0;
   3212             }
   3213         }
   3214 
   3215         public void addPss(long pss, long uss, boolean always,
   3216                 ArrayMap<String, ProcessStateHolder> pkgList) {
   3217             ensureNotDead();
   3218             if (!always) {
   3219                 if (mLastPssState == mCurState && SystemClock.uptimeMillis()
   3220                         < (mLastPssTime+(30*1000))) {
   3221                     return;
   3222                 }
   3223             }
   3224             mLastPssState = mCurState;
   3225             mLastPssTime = SystemClock.uptimeMillis();
   3226             if (mCurState != STATE_NOTHING) {
   3227                 // First update the common process.
   3228                 mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
   3229 
   3230                 // If the common process is not multi-package, there is nothing else to do.
   3231                 if (!mCommonProcess.mMultiPackage) {
   3232                     return;
   3233                 }
   3234 
   3235                 if (pkgList != null) {
   3236                     for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3237                         pullFixedProc(pkgList, ip).addPss(mCurState, 1,
   3238                                 pss, pss, pss, uss, uss, uss);
   3239                     }
   3240                 }
   3241             }
   3242         }
   3243 
   3244         void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
   3245                 long avgUss, long maxUss) {
   3246             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3247             int off;
   3248             if (idx >= 0) {
   3249                 off = mPssTable[idx];
   3250             } else {
   3251                 mStats.mAddLongTable = mPssTable;
   3252                 mStats.mAddLongTableSize = mPssTableSize;
   3253                 off = mStats.addLongData(~idx, state, PSS_COUNT);
   3254                 mPssTable = mStats.mAddLongTable;
   3255                 mPssTableSize = mStats.mAddLongTableSize;
   3256             }
   3257             long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
   3258             idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
   3259             long count = longs[idx+PSS_SAMPLE_COUNT];
   3260             if (count == 0) {
   3261                 longs[idx+PSS_SAMPLE_COUNT] = inCount;
   3262                 longs[idx+PSS_MINIMUM] = minPss;
   3263                 longs[idx+PSS_AVERAGE] = avgPss;
   3264                 longs[idx+PSS_MAXIMUM] = maxPss;
   3265                 longs[idx+PSS_USS_MINIMUM] = minUss;
   3266                 longs[idx+PSS_USS_AVERAGE] = avgUss;
   3267                 longs[idx+PSS_USS_MAXIMUM] = maxUss;
   3268             } else {
   3269                 longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
   3270                 if (longs[idx+PSS_MINIMUM] > minPss) {
   3271                     longs[idx+PSS_MINIMUM] = minPss;
   3272                 }
   3273                 longs[idx+PSS_AVERAGE] = (long)(
   3274                         ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
   3275                                 / (count+inCount) );
   3276                 if (longs[idx+PSS_MAXIMUM] < maxPss) {
   3277                     longs[idx+PSS_MAXIMUM] = maxPss;
   3278                 }
   3279                 if (longs[idx+PSS_USS_MINIMUM] > minUss) {
   3280                     longs[idx+PSS_USS_MINIMUM] = minUss;
   3281                 }
   3282                 longs[idx+PSS_USS_AVERAGE] = (long)(
   3283                         ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
   3284                                 / (count+inCount) );
   3285                 if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
   3286                     longs[idx+PSS_USS_MAXIMUM] = maxUss;
   3287                 }
   3288             }
   3289         }
   3290 
   3291         public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) {
   3292             ensureNotDead();
   3293             mCommonProcess.mNumExcessiveWake++;
   3294             if (!mCommonProcess.mMultiPackage) {
   3295                 return;
   3296             }
   3297 
   3298             for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3299                 pullFixedProc(pkgList, ip).mNumExcessiveWake++;
   3300             }
   3301         }
   3302 
   3303         public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) {
   3304             ensureNotDead();
   3305             mCommonProcess.mNumExcessiveCpu++;
   3306             if (!mCommonProcess.mMultiPackage) {
   3307                 return;
   3308             }
   3309 
   3310             for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3311                 pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
   3312             }
   3313         }
   3314 
   3315         private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
   3316             if (mNumCachedKill <= 0) {
   3317                 mNumCachedKill = num;
   3318                 mMinCachedKillPss = minPss;
   3319                 mAvgCachedKillPss = avgPss;
   3320                 mMaxCachedKillPss = maxPss;
   3321             } else {
   3322                 if (minPss < mMinCachedKillPss) {
   3323                     mMinCachedKillPss = minPss;
   3324                 }
   3325                 if (maxPss > mMaxCachedKillPss) {
   3326                     mMaxCachedKillPss = maxPss;
   3327                 }
   3328                 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
   3329                         / (mNumCachedKill+num) );
   3330                 mNumCachedKill += num;
   3331             }
   3332         }
   3333 
   3334         public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) {
   3335             ensureNotDead();
   3336             mCommonProcess.addCachedKill(1, pss, pss, pss);
   3337             if (!mCommonProcess.mMultiPackage) {
   3338                 return;
   3339             }
   3340 
   3341             for (int ip=pkgList.size()-1; ip>=0; ip--) {
   3342                 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
   3343             }
   3344         }
   3345 
   3346         ProcessState pullFixedProc(String pkgName) {
   3347             if (mMultiPackage) {
   3348                 // The array map is still pointing to a common process state
   3349                 // that is now shared across packages.  Update it to point to
   3350                 // the new per-package state.
   3351                 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid);
   3352                 if (vpkg == null) {
   3353                     throw new IllegalStateException("Didn't find package " + pkgName
   3354                             + " / " + mUid);
   3355                 }
   3356                 PackageState pkg = vpkg.get(mVersion);
   3357                 if (pkg == null) {
   3358                     throw new IllegalStateException("Didn't find package " + pkgName
   3359                             + " / " + mUid + " vers " + mVersion);
   3360                 }
   3361                 ProcessState proc = pkg.mProcesses.get(mName);
   3362                 if (proc == null) {
   3363                     throw new IllegalStateException("Didn't create per-package process "
   3364                             + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion);
   3365                 }
   3366                 return proc;
   3367             }
   3368             return this;
   3369         }
   3370 
   3371         private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList,
   3372                 int index) {
   3373             ProcessStateHolder holder = pkgList.valueAt(index);
   3374             ProcessState proc = holder.state;
   3375             if (mDead && proc.mCommonProcess != proc) {
   3376                 // Somehow we are contining to use a process state that is dead, because
   3377                 // it was not being told it was active during the last commit.  We can recover
   3378                 // from this by generating a fresh new state, but this is bad because we
   3379                 // are losing whatever data we had in the old process state.
   3380                 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
   3381                         + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
   3382                 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion,
   3383                         proc.mName);
   3384             }
   3385             if (proc.mMultiPackage) {
   3386                 // The array map is still pointing to a common process state
   3387                 // that is now shared across packages.  Update it to point to
   3388                 // the new per-package state.
   3389                 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index),
   3390                         proc.mUid);
   3391                 if (vpkg == null) {
   3392                     throw new IllegalStateException("No existing package "
   3393                             + pkgList.keyAt(index) + "/" + proc.mUid
   3394                             + " for multi-proc " + proc.mName);
   3395                 }
   3396                 PackageState pkg = vpkg.get(proc.mVersion);
   3397                 if (pkg == null) {
   3398                     throw new IllegalStateException("No existing package "
   3399                             + pkgList.keyAt(index) + "/" + proc.mUid
   3400                             + " for multi-proc " + proc.mName + " version " + proc.mVersion);
   3401                 }
   3402                 proc = pkg.mProcesses.get(proc.mName);
   3403                 if (proc == null) {
   3404                     throw new IllegalStateException("Didn't create per-package process "
   3405                             + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
   3406                 }
   3407                 holder.state = proc;
   3408             }
   3409             return proc;
   3410         }
   3411 
   3412         long getDuration(int state, long now) {
   3413             long time = super.getDuration(state, now);
   3414             if (mCurState == state) {
   3415                 time += now - mStartTime;
   3416             }
   3417             return time;
   3418         }
   3419 
   3420         long getPssSampleCount(int state) {
   3421             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3422             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
   3423         }
   3424 
   3425         long getPssMinimum(int state) {
   3426             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3427             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
   3428         }
   3429 
   3430         long getPssAverage(int state) {
   3431             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3432             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
   3433         }
   3434 
   3435         long getPssMaximum(int state) {
   3436             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3437             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
   3438         }
   3439 
   3440         long getPssUssMinimum(int state) {
   3441             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3442             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
   3443         }
   3444 
   3445         long getPssUssAverage(int state) {
   3446             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3447             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
   3448         }
   3449 
   3450         long getPssUssMaximum(int state) {
   3451             int idx = binarySearch(mPssTable, mPssTableSize, state);
   3452             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
   3453         }
   3454 
   3455         public String toString() {
   3456             StringBuilder sb = new StringBuilder(128);
   3457             sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
   3458                     .append(" ").append(mName).append("/").append(mUid)
   3459                     .append(" pkg=").append(mPackage);
   3460             if (mMultiPackage) sb.append(" (multi)");
   3461             if (mCommonProcess != this) sb.append(" (sub)");
   3462             sb.append("}");
   3463             return sb.toString();
   3464         }
   3465     }
   3466 
   3467     public static final class ServiceState extends DurationsTable {
   3468         public final String mPackage;
   3469         public final String mProcessName;
   3470         ProcessState mProc;
   3471 
   3472         Object mOwner;
   3473 
   3474         public static final int SERVICE_RUN = 0;
   3475         public static final int SERVICE_STARTED = 1;
   3476         public static final int SERVICE_BOUND = 2;
   3477         public static final int SERVICE_EXEC = 3;
   3478         static final int SERVICE_COUNT = 4;
   3479 
   3480         int mRunCount;
   3481         public int mRunState = STATE_NOTHING;
   3482         long mRunStartTime;
   3483 
   3484         boolean mStarted;
   3485         boolean mRestarting;
   3486         int mStartedCount;
   3487         public int mStartedState = STATE_NOTHING;
   3488         long mStartedStartTime;
   3489 
   3490         int mBoundCount;
   3491         public int mBoundState = STATE_NOTHING;
   3492         long mBoundStartTime;
   3493 
   3494         int mExecCount;
   3495         public int mExecState = STATE_NOTHING;
   3496         long mExecStartTime;
   3497 
   3498         public ServiceState(ProcessStats processStats, String pkg, String name,
   3499                 String processName, ProcessState proc) {
   3500             super(processStats, name);
   3501             mPackage = pkg;
   3502             mProcessName = processName;
   3503             mProc = proc;
   3504         }
   3505 
   3506         public void applyNewOwner(Object newOwner) {
   3507             if (mOwner != newOwner) {
   3508                 if (mOwner == null) {
   3509                     mOwner = newOwner;
   3510                     mProc.incActiveServices(mName);
   3511                 } else {
   3512                     // There was already an old owner, reset this object for its
   3513                     // new owner.
   3514                     mOwner = newOwner;
   3515                     if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
   3516                         long now = SystemClock.uptimeMillis();
   3517                         if (mStarted) {
   3518                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
   3519                                     + " from " + mOwner + " while started: pkg="
   3520                                     + mPackage + " service=" + mName + " proc=" + mProc);
   3521                             setStarted(false, 0, now);
   3522                         }
   3523                         if (mBoundState != STATE_NOTHING) {
   3524                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
   3525                                     + " from " + mOwner + " while bound: pkg="
   3526                                     + mPackage + " service=" + mName + " proc=" + mProc);
   3527                             setBound(false, 0, now);
   3528                         }
   3529                         if (mExecState != STATE_NOTHING) {
   3530                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
   3531                                     + " from " + mOwner + " while executing: pkg="
   3532                                     + mPackage + " service=" + mName + " proc=" + mProc);
   3533                             setExecuting(false, 0, now);
   3534                         }
   3535                     }
   3536                 }
   3537             }
   3538         }
   3539 
   3540         public void clearCurrentOwner(Object owner, boolean silently) {
   3541             if (mOwner == owner) {
   3542                 mProc.decActiveServices(mName);
   3543                 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
   3544                     long now = SystemClock.uptimeMillis();
   3545                     if (mStarted) {
   3546                         if (!silently) {
   3547                             Slog.wtfStack(TAG, "Service owner " + owner
   3548                                     + " cleared while started: pkg=" + mPackage + " service="
   3549                                     + mName + " proc=" + mProc);
   3550                         }
   3551                         setStarted(false, 0, now);
   3552                     }
   3553                     if (mBoundState != STATE_NOTHING) {
   3554                         if (!silently) {
   3555                             Slog.wtfStack(TAG, "Service owner " + owner
   3556                                     + " cleared while bound: pkg=" + mPackage + " service="
   3557                                     + mName + " proc=" + mProc);
   3558                         }
   3559                         setBound(false, 0, now);
   3560                     }
   3561                     if (mExecState != STATE_NOTHING) {
   3562                         if (!silently) {
   3563                             Slog.wtfStack(TAG, "Service owner " + owner
   3564                                     + " cleared while exec: pkg=" + mPackage + " service="
   3565                                     + mName + " proc=" + mProc);
   3566                         }
   3567                         setExecuting(false, 0, now);
   3568                     }
   3569                 }
   3570                 mOwner = null;
   3571             }
   3572         }
   3573 
   3574         public boolean isInUse() {
   3575             return mOwner != null || mRestarting;
   3576         }
   3577 
   3578         public boolean isRestarting() {
   3579             return mRestarting;
   3580         }
   3581 
   3582         void add(ServiceState other) {
   3583             addDurations(other);
   3584             mRunCount += other.mRunCount;
   3585             mStartedCount += other.mStartedCount;
   3586             mBoundCount += other.mBoundCount;
   3587             mExecCount += other.mExecCount;
   3588         }
   3589 
   3590         void resetSafely(long now) {
   3591             resetDurationsSafely();
   3592             mRunCount = mRunState != STATE_NOTHING ? 1 : 0;
   3593             mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
   3594             mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
   3595             mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
   3596             mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now;
   3597         }
   3598 
   3599         void writeToParcel(Parcel out, long now) {
   3600             writeDurationsToParcel(out);
   3601             out.writeInt(mRunCount);
   3602             out.writeInt(mStartedCount);
   3603             out.writeInt(mBoundCount);
   3604             out.writeInt(mExecCount);
   3605         }
   3606 
   3607         boolean readFromParcel(Parcel in) {
   3608             if (!readDurationsFromParcel(in)) {
   3609                 return false;
   3610             }
   3611             mRunCount = in.readInt();
   3612             mStartedCount = in.readInt();
   3613             mBoundCount = in.readInt();
   3614             mExecCount = in.readInt();
   3615             return true;
   3616         }
   3617 
   3618         void commitStateTime(long now) {
   3619             if (mRunState != STATE_NOTHING) {
   3620                 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime);
   3621                 mRunStartTime = now;
   3622             }
   3623             if (mStartedState != STATE_NOTHING) {
   3624                 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
   3625                         now - mStartedStartTime);
   3626                 mStartedStartTime = now;
   3627             }
   3628             if (mBoundState != STATE_NOTHING) {
   3629                 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
   3630                 mBoundStartTime = now;
   3631             }
   3632             if (mExecState != STATE_NOTHING) {
   3633                 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
   3634                 mExecStartTime = now;
   3635             }
   3636         }
   3637 
   3638         private void updateRunning(int memFactor, long now) {
   3639             final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
   3640                     || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
   3641             if (mRunState != state) {
   3642                 if (mRunState != STATE_NOTHING) {
   3643                     addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT),
   3644                             now - mRunStartTime);
   3645                 } else if (state != STATE_NOTHING) {
   3646                     mRunCount++;
   3647                 }
   3648                 mRunState = state;
   3649                 mRunStartTime = now;
   3650             }
   3651         }
   3652 
   3653         public void setStarted(boolean started, int memFactor, long now) {
   3654             if (mOwner == null) {
   3655                 Slog.wtf(TAG, "Starting service " + this + " without owner");
   3656             }
   3657             mStarted = started;
   3658             updateStartedState(memFactor, now);
   3659         }
   3660 
   3661         public void setRestarting(boolean restarting, int memFactor, long now) {
   3662             mRestarting = restarting;
   3663             updateStartedState(memFactor, now);
   3664         }
   3665 
   3666         void updateStartedState(int memFactor, long now) {
   3667             final boolean wasStarted = mStartedState != STATE_NOTHING;
   3668             final boolean started = mStarted || mRestarting;
   3669             final int state = started ? memFactor : STATE_NOTHING;
   3670             if (mStartedState != state) {
   3671                 if (mStartedState != STATE_NOTHING) {
   3672                     addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
   3673                             now - mStartedStartTime);
   3674                 } else if (started) {
   3675                     mStartedCount++;
   3676                 }
   3677                 mStartedState = state;
   3678                 mStartedStartTime = now;
   3679                 mProc = mProc.pullFixedProc(mPackage);
   3680                 if (wasStarted != started) {
   3681                     if (started) {
   3682                         mProc.incStartedServices(memFactor, now, mName);
   3683                     } else {
   3684                         mProc.decStartedServices(memFactor, now, mName);
   3685                     }
   3686                 }
   3687                 updateRunning(memFactor, now);
   3688             }
   3689         }
   3690 
   3691         public void setBound(boolean bound, int memFactor, long now) {
   3692             if (mOwner == null) {
   3693                 Slog.wtf(TAG, "Binding service " + this + " without owner");
   3694             }
   3695             final int state = bound ? memFactor : STATE_NOTHING;
   3696             if (mBoundState != state) {
   3697                 if (mBoundState != STATE_NOTHING) {
   3698                     addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
   3699                             now - mBoundStartTime);
   3700                 } else if (bound) {
   3701                     mBoundCount++;
   3702                 }
   3703                 mBoundState = state;
   3704                 mBoundStartTime = now;
   3705                 updateRunning(memFactor, now);
   3706             }
   3707         }
   3708 
   3709         public void setExecuting(boolean executing, int memFactor, long now) {
   3710             if (mOwner == null) {
   3711                 Slog.wtf(TAG, "Executing service " + this + " without owner");
   3712             }
   3713             final int state = executing ? memFactor : STATE_NOTHING;
   3714             if (mExecState != state) {
   3715                 if (mExecState != STATE_NOTHING) {
   3716                     addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
   3717                 } else if (executing) {
   3718                     mExecCount++;
   3719                 }
   3720                 mExecState = state;
   3721                 mExecStartTime = now;
   3722                 updateRunning(memFactor, now);
   3723             }
   3724         }
   3725 
   3726         private long getDuration(int opType, int curState, long startTime, int memFactor,
   3727                 long now) {
   3728             int state = opType + (memFactor*SERVICE_COUNT);
   3729             long time = getDuration(state, now);
   3730             if (curState == memFactor) {
   3731                 time += now - startTime;
   3732             }
   3733             return time;
   3734         }
   3735 
   3736         public String toString() {
   3737             return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
   3738                     + " " + mName + " pkg=" + mPackage + " proc="
   3739                     + Integer.toHexString(System.identityHashCode(this)) + "}";
   3740         }
   3741     }
   3742 
   3743     public static final class PackageState {
   3744         public final ArrayMap<String, ProcessState> mProcesses
   3745                 = new ArrayMap<String, ProcessState>();
   3746         public final ArrayMap<String, ServiceState> mServices
   3747                 = new ArrayMap<String, ServiceState>();
   3748         public final String mPackageName;
   3749         public final int mUid;
   3750 
   3751         public PackageState(String packageName, int uid) {
   3752             mUid = uid;
   3753             mPackageName = packageName;
   3754         }
   3755     }
   3756 
   3757     public static final class ProcessDataCollection {
   3758         final int[] screenStates;
   3759         final int[] memStates;
   3760         final int[] procStates;
   3761 
   3762         public long totalTime;
   3763         public long numPss;
   3764         public long minPss;
   3765         public long avgPss;
   3766         public long maxPss;
   3767         public long minUss;
   3768         public long avgUss;
   3769         public long maxUss;
   3770 
   3771         public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
   3772             screenStates = _screenStates;
   3773             memStates = _memStates;
   3774             procStates = _procStates;
   3775         }
   3776 
   3777         void print(PrintWriter pw, long overallTime, boolean full) {
   3778             if (totalTime > overallTime) {
   3779                 pw.print("*");
   3780             }
   3781             printPercent(pw, (double) totalTime / (double) overallTime);
   3782             if (numPss > 0) {
   3783                 pw.print(" (");
   3784                 printSizeValue(pw, minPss * 1024);
   3785                 pw.print("-");
   3786                 printSizeValue(pw, avgPss * 1024);
   3787                 pw.print("-");
   3788                 printSizeValue(pw, maxPss * 1024);
   3789                 pw.print("/");
   3790                 printSizeValue(pw, minUss * 1024);
   3791                 pw.print("-");
   3792                 printSizeValue(pw, avgUss * 1024);
   3793                 pw.print("-");
   3794                 printSizeValue(pw, maxUss * 1024);
   3795                 if (full) {
   3796                     pw.print(" over ");
   3797                     pw.print(numPss);
   3798                 }
   3799                 pw.print(")");
   3800             }
   3801         }
   3802     }
   3803 
   3804     public static class TotalMemoryUseCollection {
   3805         final int[] screenStates;
   3806         final int[] memStates;
   3807 
   3808         public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) {
   3809             screenStates = _screenStates;
   3810             memStates = _memStates;
   3811         }
   3812 
   3813         public long totalTime;
   3814         public long[] processStatePss = new long[STATE_COUNT];
   3815         public double[] processStateWeight = new double[STATE_COUNT];
   3816         public long[] processStateTime = new long[STATE_COUNT];
   3817         public int[] processStateSamples = new int[STATE_COUNT];
   3818         public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT];
   3819         public double sysMemCachedWeight;
   3820         public double sysMemFreeWeight;
   3821         public double sysMemZRamWeight;
   3822         public double sysMemKernelWeight;
   3823         public double sysMemNativeWeight;
   3824         public int sysMemSamples;
   3825     }
   3826 }
   3827