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