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