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