ProcessStats.java revision 25e1ecaabbde4741663c8e5a777d9df9b939572c
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        if (mSysMemUsageTable != null) {
2163            pw.println("System memory usage:");
2164            dumpSysMemUsage(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
2165        }
2166        ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
2167        boolean printedHeader = false;
2168        boolean sepNeeded = false;
2169        for (int ip=0; ip<pkgMap.size(); ip++) {
2170            final String pkgName = pkgMap.keyAt(ip);
2171            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
2172            for (int iu=0; iu<uids.size(); iu++) {
2173                final int uid = uids.keyAt(iu);
2174                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
2175                for (int iv=0; iv<vpkgs.size(); iv++) {
2176                    final int vers = vpkgs.keyAt(iv);
2177                    final PackageState pkgState = vpkgs.valueAt(iv);
2178                    final int NPROCS = pkgState.mProcesses.size();
2179                    final int NSRVS = pkgState.mServices.size();
2180                    final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
2181                    if (!pkgMatch) {
2182                        boolean procMatch = false;
2183                        for (int iproc=0; iproc<NPROCS; iproc++) {
2184                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2185                            if (reqPackage.equals(proc.mName)) {
2186                                procMatch = true;
2187                                break;
2188                            }
2189                        }
2190                        if (!procMatch) {
2191                            continue;
2192                        }
2193                    }
2194                    if (NPROCS > 0 || NSRVS > 0) {
2195                        if (!printedHeader) {
2196                            pw.println("Per-Package Stats:");
2197                            printedHeader = true;
2198                            sepNeeded = true;
2199                        }
2200                        pw.print("  * "); pw.print(pkgName); pw.print(" / ");
2201                                UserHandle.formatUid(pw, uid); pw.print(" / v");
2202                                pw.print(vers); pw.println(":");
2203                    }
2204                    if (!dumpSummary || dumpAll) {
2205                        for (int iproc=0; iproc<NPROCS; iproc++) {
2206                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2207                            if (!pkgMatch && !reqPackage.equals(proc.mName)) {
2208                                continue;
2209                            }
2210                            if (activeOnly && !proc.isInUse()) {
2211                                pw.print("      (Not active: ");
2212                                        pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
2213                                continue;
2214                            }
2215                            pw.print("      Process ");
2216                            pw.print(pkgState.mProcesses.keyAt(iproc));
2217                            if (proc.mCommonProcess.mMultiPackage) {
2218                                pw.print(" (multi, ");
2219                            } else {
2220                                pw.print(" (unique, ");
2221                            }
2222                            pw.print(proc.mDurationsTableSize);
2223                            pw.print(" entries)");
2224                            pw.println(":");
2225                            dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2226                                    ALL_PROC_STATES, now);
2227                            dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2228                                    ALL_PROC_STATES);
2229                            dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
2230                        }
2231                    } else {
2232                        ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
2233                        for (int iproc=0; iproc<NPROCS; iproc++) {
2234                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2235                            if (!pkgMatch && !reqPackage.equals(proc.mName)) {
2236                                continue;
2237                            }
2238                            if (activeOnly && !proc.isInUse()) {
2239                                continue;
2240                            }
2241                            procs.add(proc);
2242                        }
2243                        dumpProcessSummaryLocked(pw, "      ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2244                                NON_CACHED_PROC_STATES, false, now, totalTime);
2245                    }
2246                    for (int isvc=0; isvc<NSRVS; isvc++) {
2247                        ServiceState svc = pkgState.mServices.valueAt(isvc);
2248                        if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
2249                            continue;
2250                        }
2251                        if (activeOnly && !svc.isInUse()) {
2252                            pw.print("      (Not active: ");
2253                                    pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
2254                            continue;
2255                        }
2256                        if (dumpAll) {
2257                            pw.print("      Service ");
2258                        } else {
2259                            pw.print("      * ");
2260                        }
2261                        pw.print(pkgState.mServices.keyAt(isvc));
2262                        pw.println(":");
2263                        pw.print("        Process: "); pw.println(svc.mProcessName);
2264                        dumpServiceStats(pw, "        ", "          ", "    ", "Running", svc,
2265                                svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
2266                                svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll);
2267                        dumpServiceStats(pw, "        ", "          ", "    ", "Started", svc,
2268                                svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState,
2269                                svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll);
2270                        dumpServiceStats(pw, "        ", "          ", "      ", "Bound", svc,
2271                                svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState,
2272                                svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll);
2273                        dumpServiceStats(pw, "        ", "          ", "  ", "Executing", svc,
2274                                svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
2275                                svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
2276                        if (dumpAll) {
2277                            if (svc.mOwner != null) {
2278                                pw.print("        mOwner="); pw.println(svc.mOwner);
2279                            }
2280                            if (svc.mStarted || svc.mRestarting) {
2281                                pw.print("        mStarted="); pw.print(svc.mStarted);
2282                                pw.print(" mRestarting="); pw.println(svc.mRestarting);
2283                            }
2284                        }
2285                    }
2286                }
2287            }
2288        }
2289
2290        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2291        printedHeader = false;
2292        int numShownProcs = 0, numTotalProcs = 0;
2293        for (int ip=0; ip<procMap.size(); ip++) {
2294            String procName = procMap.keyAt(ip);
2295            SparseArray<ProcessState> uids = procMap.valueAt(ip);
2296            for (int iu=0; iu<uids.size(); iu++) {
2297                int uid = uids.keyAt(iu);
2298                numTotalProcs++;
2299                ProcessState proc = uids.valueAt(iu);
2300                if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
2301                        && proc.mPssTableSize == 0) {
2302                    continue;
2303                }
2304                if (!proc.mMultiPackage) {
2305                    continue;
2306                }
2307                if (reqPackage != null && !reqPackage.equals(procName)
2308                        && !reqPackage.equals(proc.mPackage)) {
2309                    continue;
2310                }
2311                numShownProcs++;
2312                if (sepNeeded) {
2313                    pw.println();
2314                }
2315                sepNeeded = true;
2316                if (!printedHeader) {
2317                    pw.println("Multi-Package Common Processes:");
2318                    printedHeader = true;
2319                }
2320                if (activeOnly && !proc.isInUse()) {
2321                    pw.print("      (Not active: "); pw.print(procName); pw.println(")");
2322                    continue;
2323                }
2324                pw.print("  * "); pw.print(procName); pw.print(" / ");
2325                        UserHandle.formatUid(pw, uid);
2326                        pw.print(" ("); pw.print(proc.mDurationsTableSize);
2327                        pw.print(" entries)"); pw.println(":");
2328                dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2329                        ALL_PROC_STATES, now);
2330                dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2331                        ALL_PROC_STATES);
2332                dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
2333            }
2334        }
2335        if (dumpAll) {
2336            pw.println();
2337            pw.print("  Total procs: "); pw.print(numShownProcs);
2338                    pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
2339        }
2340
2341        if (sepNeeded) {
2342            pw.println();
2343        }
2344        if (dumpSummary) {
2345            pw.println("Summary:");
2346            dumpSummaryLocked(pw, reqPackage, now, activeOnly);
2347        } else {
2348            dumpTotalsLocked(pw, now);
2349        }
2350
2351        if (dumpAll) {
2352            pw.println();
2353            pw.println("Internal state:");
2354            pw.print("  Num long arrays: "); pw.println(mLongs.size());
2355            pw.print("  Next long entry: "); pw.println(mNextLong);
2356            pw.print("  mRunning="); pw.println(mRunning);
2357        }
2358    }
2359
2360    public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
2361            int serviceType, int curState, long curStartTime, long now) {
2362        long totalTime = 0;
2363        int printedScreen = -1;
2364        for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
2365            int printedMem = -1;
2366            for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
2367                int state = imem+iscreen;
2368                long time = service.getDuration(serviceType, curState, curStartTime,
2369                        state, now);
2370                String running = "";
2371                if (curState == state && pw != null) {
2372                    running = " (running)";
2373                }
2374                if (time != 0) {
2375                    if (pw != null) {
2376                        pw.print(prefix);
2377                        printScreenLabel(pw, printedScreen != iscreen
2378                                ? iscreen : STATE_NOTHING);
2379                        printedScreen = iscreen;
2380                        printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
2381                        printedMem = imem;
2382                        pw.print(": ");
2383                        TimeUtils.formatDuration(time, pw); pw.println(running);
2384                    }
2385                    totalTime += time;
2386                }
2387            }
2388        }
2389        if (totalTime != 0 && pw != null) {
2390            pw.print(prefix);
2391            pw.print("    TOTAL: ");
2392            TimeUtils.formatDuration(totalTime, pw);
2393            pw.println();
2394        }
2395        return totalTime;
2396    }
2397
2398    void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner,
2399            String headerPrefix, String header, ServiceState service,
2400            int count, int serviceType, int state, long startTime, long now, long totalTime,
2401            boolean dumpAll) {
2402        if (count != 0) {
2403            if (dumpAll) {
2404                pw.print(prefix); pw.print(header);
2405                pw.print(" op count "); pw.print(count); pw.println(":");
2406                dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime,
2407                        now);
2408            } else {
2409                long myTime = dumpSingleServiceTime(null, null, service, serviceType, state,
2410                        startTime, now);
2411                pw.print(prefix); pw.print(headerPrefix); pw.print(header);
2412                pw.print(" count "); pw.print(count);
2413                pw.print(" / time ");
2414                printPercent(pw, (double)myTime/(double)totalTime);
2415                pw.println();
2416            }
2417        }
2418    }
2419
2420    public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
2421        long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
2422                mStartTime, now);
2423        dumpFilteredSummaryLocked(pw, null, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
2424                ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
2425        pw.println();
2426        dumpTotalsLocked(pw, now);
2427    }
2428
2429    long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight,
2430            long totalTime, long curTotalMem, int samples) {
2431        if (memWeight != 0) {
2432            long mem = (long)(memWeight * 1024 / totalTime);
2433            pw.print(prefix);
2434            pw.print(label);
2435            pw.print(": ");
2436            printSizeValue(pw, mem);
2437            pw.print(" (");
2438            pw.print(samples);
2439            pw.print(" samples)");
2440            pw.println();
2441            return curTotalMem + mem;
2442        }
2443        return curTotalMem;
2444    }
2445
2446    void dumpTotalsLocked(PrintWriter pw, long now) {
2447        pw.println("Run time Stats:");
2448        dumpSingleTime(pw, "  ", mMemFactorDurations, mMemFactor, mStartTime, now);
2449        pw.println();
2450        pw.println("Memory usage:");
2451        TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
2452                ALL_MEM_ADJ);
2453        computeTotalMemoryUse(totalMem, now);
2454        long totalPss = 0;
2455        totalPss = printMemoryCategory(pw, "  ", "Kernel ", totalMem.sysMemKernelWeight,
2456                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
2457        totalPss = printMemoryCategory(pw, "  ", "Native ", totalMem.sysMemNativeWeight,
2458                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
2459        for (int i=0; i<STATE_COUNT; i++) {
2460            // Skip restarting service state -- that is not actually a running process.
2461            if (i != STATE_SERVICE_RESTARTING) {
2462                totalPss = printMemoryCategory(pw, "  ", STATE_NAMES[i],
2463                        totalMem.processStateWeight[i], totalMem.totalTime, totalPss,
2464                        totalMem.processStateSamples[i]);
2465            }
2466        }
2467        totalPss = printMemoryCategory(pw, "  ", "Cached ", totalMem.sysMemCachedWeight,
2468                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
2469        totalPss = printMemoryCategory(pw, "  ", "Free   ", totalMem.sysMemFreeWeight,
2470                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
2471        totalPss = printMemoryCategory(pw, "  ", "Z-Ram   ", totalMem.sysMemZRamWeight,
2472                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
2473        pw.print("  TOTAL  : ");
2474        printSizeValue(pw, totalPss);
2475        pw.println();
2476        printMemoryCategory(pw, "  ", STATE_NAMES[STATE_SERVICE_RESTARTING],
2477                totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss,
2478                totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
2479        pw.println();
2480        pw.print("          Start time: ");
2481        pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
2482        pw.println();
2483        pw.print("  Total elapsed time: ");
2484        TimeUtils.formatDuration(
2485                (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
2486                        - mTimePeriodStartRealtime, pw);
2487        boolean partial = true;
2488        if ((mFlags&FLAG_SHUTDOWN) != 0) {
2489            pw.print(" (shutdown)");
2490            partial = false;
2491        }
2492        if ((mFlags&FLAG_SYSPROPS) != 0) {
2493            pw.print(" (sysprops)");
2494            partial = false;
2495        }
2496        if ((mFlags&FLAG_COMPLETE) != 0) {
2497            pw.print(" (complete)");
2498            partial = false;
2499        }
2500        if (partial) {
2501            pw.print(" (partial)");
2502        }
2503        pw.print(' ');
2504        pw.print(mRuntime);
2505        pw.println();
2506    }
2507
2508    void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
2509            int[] screenStates, int[] memStates, int[] procStates,
2510            int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
2511        ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
2512                procStates, sortProcStates, now, reqPackage, activeOnly);
2513        if (procs.size() > 0) {
2514            if (header != null) {
2515                pw.println();
2516                pw.println(header);
2517            }
2518            dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
2519                    sortProcStates, true, now, totalTime);
2520        }
2521    }
2522
2523    public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
2524            int[] procStates, int sortProcStates[], long now, String reqPackage,
2525            boolean activeOnly) {
2526        final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
2527        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
2528        for (int ip=0; ip<pkgMap.size(); ip++) {
2529            final String pkgName = pkgMap.keyAt(ip);
2530            final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip);
2531            for (int iu=0; iu<procs.size(); iu++) {
2532                final SparseArray<PackageState> vpkgs = procs.valueAt(iu);
2533                final int NVERS = vpkgs.size();
2534                for (int iv=0; iv<NVERS; iv++) {
2535                    final PackageState state = vpkgs.valueAt(iv);
2536                    final int NPROCS = state.mProcesses.size();
2537                    final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
2538                    for (int iproc=0; iproc<NPROCS; iproc++) {
2539                        final ProcessState proc = state.mProcesses.valueAt(iproc);
2540                        if (!pkgMatch && !reqPackage.equals(proc.mName)) {
2541                            continue;
2542                        }
2543                        if (activeOnly && !proc.isInUse()) {
2544                            continue;
2545                        }
2546                        foundProcs.add(proc.mCommonProcess);
2547                    }
2548                }
2549            }
2550        }
2551        ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
2552        for (int i=0; i<foundProcs.size(); i++) {
2553            ProcessState proc = foundProcs.valueAt(i);
2554            if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
2555                outProcs.add(proc);
2556                if (procStates != sortProcStates) {
2557                    computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
2558                }
2559            }
2560        }
2561        Collections.sort(outProcs, new Comparator<ProcessState>() {
2562            @Override
2563            public int compare(ProcessState lhs, ProcessState rhs) {
2564                if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
2565                    return -1;
2566                } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
2567                    return 1;
2568                }
2569                return 0;
2570            }
2571        });
2572        return outProcs;
2573    }
2574
2575    String collapseString(String pkgName, String itemName) {
2576        if (itemName.startsWith(pkgName)) {
2577            final int ITEMLEN = itemName.length();
2578            final int PKGLEN = pkgName.length();
2579            if (ITEMLEN == PKGLEN) {
2580                return "";
2581            } else if (ITEMLEN >= PKGLEN) {
2582                if (itemName.charAt(PKGLEN) == '.') {
2583                    return itemName.substring(PKGLEN);
2584                }
2585            }
2586        }
2587        return itemName;
2588    }
2589
2590    public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
2591        final long now = SystemClock.uptimeMillis();
2592        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
2593        pw.println("vers,5");
2594        pw.print("period,"); pw.print(mTimePeriodStartClockStr);
2595        pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
2596        pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
2597        boolean partial = true;
2598        if ((mFlags&FLAG_SHUTDOWN) != 0) {
2599            pw.print(",shutdown");
2600            partial = false;
2601        }
2602        if ((mFlags&FLAG_SYSPROPS) != 0) {
2603            pw.print(",sysprops");
2604            partial = false;
2605        }
2606        if ((mFlags&FLAG_COMPLETE) != 0) {
2607            pw.print(",complete");
2608            partial = false;
2609        }
2610        if (partial) {
2611            pw.print(",partial");
2612        }
2613        pw.println();
2614        pw.print("config,"); pw.println(mRuntime);
2615        for (int ip=0; ip<pkgMap.size(); ip++) {
2616            final String pkgName = pkgMap.keyAt(ip);
2617            if (reqPackage != null && !reqPackage.equals(pkgName)) {
2618                continue;
2619            }
2620            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
2621            for (int iu=0; iu<uids.size(); iu++) {
2622                final int uid = uids.keyAt(iu);
2623                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
2624                for (int iv=0; iv<vpkgs.size(); iv++) {
2625                    final int vers = vpkgs.keyAt(iv);
2626                    final PackageState pkgState = vpkgs.valueAt(iv);
2627                    final int NPROCS = pkgState.mProcesses.size();
2628                    final int NSRVS = pkgState.mServices.size();
2629                    for (int iproc=0; iproc<NPROCS; iproc++) {
2630                        ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2631                        pw.print("pkgproc,");
2632                        pw.print(pkgName);
2633                        pw.print(",");
2634                        pw.print(uid);
2635                        pw.print(",");
2636                        pw.print(vers);
2637                        pw.print(",");
2638                        pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2639                        dumpAllProcessStateCheckin(pw, proc, now);
2640                        pw.println();
2641                        if (proc.mPssTableSize > 0) {
2642                            pw.print("pkgpss,");
2643                            pw.print(pkgName);
2644                            pw.print(",");
2645                            pw.print(uid);
2646                            pw.print(",");
2647                            pw.print(vers);
2648                            pw.print(",");
2649                            pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2650                            dumpAllProcessPssCheckin(pw, proc);
2651                            pw.println();
2652                        }
2653                        if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0
2654                                || proc.mNumCachedKill > 0) {
2655                            pw.print("pkgkills,");
2656                            pw.print(pkgName);
2657                            pw.print(",");
2658                            pw.print(uid);
2659                            pw.print(",");
2660                            pw.print(vers);
2661                            pw.print(",");
2662                            pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc)));
2663                            pw.print(",");
2664                            pw.print(proc.mNumExcessiveWake);
2665                            pw.print(",");
2666                            pw.print(proc.mNumExcessiveCpu);
2667                            pw.print(",");
2668                            pw.print(proc.mNumCachedKill);
2669                            pw.print(",");
2670                            pw.print(proc.mMinCachedKillPss);
2671                            pw.print(":");
2672                            pw.print(proc.mAvgCachedKillPss);
2673                            pw.print(":");
2674                            pw.print(proc.mMaxCachedKillPss);
2675                            pw.println();
2676                        }
2677                    }
2678                    for (int isvc=0; isvc<NSRVS; isvc++) {
2679                        String serviceName = collapseString(pkgName,
2680                                pkgState.mServices.keyAt(isvc));
2681                        ServiceState svc = pkgState.mServices.valueAt(isvc);
2682                        dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, vers, serviceName,
2683                                svc, ServiceState.SERVICE_RUN, svc.mRunCount,
2684                                svc.mRunState, svc.mRunStartTime, now);
2685                        dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName,
2686                                svc, ServiceState.SERVICE_STARTED, svc.mStartedCount,
2687                                svc.mStartedState, svc.mStartedStartTime, now);
2688                        dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName,
2689                                svc, ServiceState.SERVICE_BOUND, svc.mBoundCount,
2690                                svc.mBoundState, svc.mBoundStartTime, now);
2691                        dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName,
2692                                svc, ServiceState.SERVICE_EXEC, svc.mExecCount,
2693                                svc.mExecState, svc.mExecStartTime, now);
2694                    }
2695                }
2696            }
2697        }
2698
2699        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2700        for (int ip=0; ip<procMap.size(); ip++) {
2701            String procName = procMap.keyAt(ip);
2702            SparseArray<ProcessState> uids = procMap.valueAt(ip);
2703            for (int iu=0; iu<uids.size(); iu++) {
2704                int uid = uids.keyAt(iu);
2705                ProcessState procState = uids.valueAt(iu);
2706                if (procState.mDurationsTableSize > 0) {
2707                    pw.print("proc,");
2708                    pw.print(procName);
2709                    pw.print(",");
2710                    pw.print(uid);
2711                    dumpAllProcessStateCheckin(pw, procState, now);
2712                    pw.println();
2713                }
2714                if (procState.mPssTableSize > 0) {
2715                    pw.print("pss,");
2716                    pw.print(procName);
2717                    pw.print(",");
2718                    pw.print(uid);
2719                    dumpAllProcessPssCheckin(pw, procState);
2720                    pw.println();
2721                }
2722                if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0
2723                        || procState.mNumCachedKill > 0) {
2724                    pw.print("kills,");
2725                    pw.print(procName);
2726                    pw.print(",");
2727                    pw.print(uid);
2728                    pw.print(",");
2729                    pw.print(procState.mNumExcessiveWake);
2730                    pw.print(",");
2731                    pw.print(procState.mNumExcessiveCpu);
2732                    pw.print(",");
2733                    pw.print(procState.mNumCachedKill);
2734                    pw.print(",");
2735                    pw.print(procState.mMinCachedKillPss);
2736                    pw.print(":");
2737                    pw.print(procState.mAvgCachedKillPss);
2738                    pw.print(":");
2739                    pw.print(procState.mMaxCachedKillPss);
2740                    pw.println();
2741                }
2742            }
2743        }
2744        pw.print("total");
2745        dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor,
2746                mStartTime, now);
2747        if (mSysMemUsageTable != null) {
2748            pw.print("sysmemusage");
2749            for (int i=0; i<mSysMemUsageTableSize; i++) {
2750                int off = mSysMemUsageTable[i];
2751                int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2752                pw.print(",");
2753                printProcStateTag(pw, type);
2754                for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) {
2755                    if (j > SYS_MEM_USAGE_CACHED_MINIMUM) {
2756                        pw.print(":");
2757                    }
2758                    pw.print(getLong(off, j));
2759                }
2760            }
2761        }
2762        pw.println();
2763        TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
2764                ALL_MEM_ADJ);
2765        computeTotalMemoryUse(totalMem, now);
2766        pw.print("weights,");
2767        pw.print(totalMem.totalTime);
2768        pw.print(",");
2769        pw.print(totalMem.sysMemCachedWeight);
2770        pw.print(":");
2771        pw.print(totalMem.sysMemSamples);
2772        pw.print(",");
2773        pw.print(totalMem.sysMemFreeWeight);
2774        pw.print(":");
2775        pw.print(totalMem.sysMemSamples);
2776        pw.print(",");
2777        pw.print(totalMem.sysMemZRamWeight);
2778        pw.print(":");
2779        pw.print(totalMem.sysMemSamples);
2780        pw.print(",");
2781        pw.print(totalMem.sysMemKernelWeight);
2782        pw.print(":");
2783        pw.print(totalMem.sysMemSamples);
2784        pw.print(",");
2785        pw.print(totalMem.sysMemNativeWeight);
2786        pw.print(":");
2787        pw.print(totalMem.sysMemSamples);
2788        for (int i=0; i<STATE_COUNT; i++) {
2789            pw.print(",");
2790            pw.print(totalMem.processStateWeight[i]);
2791            pw.print(":");
2792            pw.print(totalMem.processStateSamples[i]);
2793        }
2794        pw.println();
2795    }
2796
2797    public static class DurationsTable {
2798        public final ProcessStats mStats;
2799        public final String mName;
2800        public int[] mDurationsTable;
2801        public int mDurationsTableSize;
2802
2803        public DurationsTable(ProcessStats stats, String name) {
2804            mStats = stats;
2805            mName = name;
2806        }
2807
2808        void copyDurationsTo(DurationsTable other) {
2809            if (mDurationsTable != null) {
2810                mStats.mAddLongTable = new int[mDurationsTable.length];
2811                mStats.mAddLongTableSize = 0;
2812                for (int i=0; i<mDurationsTableSize; i++) {
2813                    int origEnt = mDurationsTable[i];
2814                    int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2815                    int newOff = mStats.addLongData(i, type, 1);
2816                    mStats.mAddLongTable[i] = newOff | type;
2817                    mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0));
2818                }
2819                other.mDurationsTable = mStats.mAddLongTable;
2820                other.mDurationsTableSize = mStats.mAddLongTableSize;
2821            } else {
2822                other.mDurationsTable = null;
2823                other.mDurationsTableSize = 0;
2824            }
2825        }
2826
2827        void addDurations(DurationsTable other) {
2828            for (int i=0; i<other.mDurationsTableSize; i++) {
2829                int ent = other.mDurationsTable[i];
2830                int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2831                if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
2832                        + other.mStats.getLong(ent, 0));
2833                addDuration(state, other.mStats.getLong(ent, 0));
2834            }
2835        }
2836
2837        void resetDurationsSafely() {
2838            mDurationsTable = null;
2839            mDurationsTableSize = 0;
2840        }
2841
2842        void writeDurationsToParcel(Parcel out) {
2843            out.writeInt(mDurationsTableSize);
2844            for (int i=0; i<mDurationsTableSize; i++) {
2845                if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
2846                        + printLongOffset(mDurationsTable[i]));
2847                out.writeInt(mDurationsTable[i]);
2848            }
2849        }
2850
2851        boolean readDurationsFromParcel(Parcel in) {
2852            mDurationsTable = mStats.readTableFromParcel(in, mName, "durations");
2853            if (mDurationsTable == BAD_TABLE) {
2854                return false;
2855            }
2856            mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
2857            return true;
2858        }
2859
2860        void addDuration(int state, long dur) {
2861            int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
2862            int off;
2863            if (idx >= 0) {
2864                off = mDurationsTable[idx];
2865            } else {
2866                mStats.mAddLongTable = mDurationsTable;
2867                mStats.mAddLongTableSize = mDurationsTableSize;
2868                off = mStats.addLongData(~idx, state, 1);
2869                mDurationsTable = mStats.mAddLongTable;
2870                mDurationsTableSize = mStats.mAddLongTableSize;
2871            }
2872            long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
2873            if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
2874                    + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
2875            longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
2876        }
2877
2878        long getDuration(int state, long now) {
2879            int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
2880            return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
2881        }
2882    }
2883
2884    final public static class ProcessStateHolder {
2885        public final int appVersion;
2886        public ProcessStats.ProcessState state;
2887
2888        public ProcessStateHolder(int _appVersion) {
2889            appVersion = _appVersion;
2890        }
2891    }
2892
2893    public static final class ProcessState extends DurationsTable {
2894        public ProcessState mCommonProcess;
2895        public final String mPackage;
2896        public final int mUid;
2897        public final int mVersion;
2898
2899        //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
2900        int mCurState = STATE_NOTHING;
2901        long mStartTime;
2902
2903        int mLastPssState = STATE_NOTHING;
2904        long mLastPssTime;
2905        int[] mPssTable;
2906        int mPssTableSize;
2907
2908        boolean mActive;
2909        int mNumActiveServices;
2910        int mNumStartedServices;
2911
2912        int mNumExcessiveWake;
2913        int mNumExcessiveCpu;
2914
2915        int mNumCachedKill;
2916        long mMinCachedKillPss;
2917        long mAvgCachedKillPss;
2918        long mMaxCachedKillPss;
2919
2920        boolean mMultiPackage;
2921        boolean mDead;
2922
2923        public long mTmpTotalTime;
2924        int mTmpNumInUse;
2925        ProcessState mTmpFoundSubProc;
2926
2927        /**
2928         * Create a new top-level process state, for the initial case where there is only
2929         * a single package running in a process.  The initial state is not running.
2930         */
2931        public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) {
2932            super(processStats, name);
2933            mCommonProcess = this;
2934            mPackage = pkg;
2935            mUid = uid;
2936            mVersion = vers;
2937        }
2938
2939        /**
2940         * Create a new per-package process state for an existing top-level process
2941         * state.  The current running state of the top-level process is also copied,
2942         * marked as started running at 'now'.
2943         */
2944        public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name,
2945                long now) {
2946            super(commonProcess.mStats, name);
2947            mCommonProcess = commonProcess;
2948            mPackage = pkg;
2949            mUid = uid;
2950            mVersion = vers;
2951            mCurState = commonProcess.mCurState;
2952            mStartTime = now;
2953        }
2954
2955        ProcessState clone(String pkg, long now) {
2956            ProcessState pnew = new ProcessState(this, pkg, mUid, mVersion, mName, now);
2957            copyDurationsTo(pnew);
2958            if (mPssTable != null) {
2959                mStats.mAddLongTable = new int[mPssTable.length];
2960                mStats.mAddLongTableSize = 0;
2961                for (int i=0; i<mPssTableSize; i++) {
2962                    int origEnt = mPssTable[i];
2963                    int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2964                    int newOff = mStats.addLongData(i, type, PSS_COUNT);
2965                    mStats.mAddLongTable[i] = newOff | type;
2966                    for (int j=0; j<PSS_COUNT; j++) {
2967                        mStats.setLong(newOff, j, mStats.getLong(origEnt, j));
2968                    }
2969                }
2970                pnew.mPssTable = mStats.mAddLongTable;
2971                pnew.mPssTableSize = mStats.mAddLongTableSize;
2972            }
2973            pnew.mNumExcessiveWake = mNumExcessiveWake;
2974            pnew.mNumExcessiveCpu = mNumExcessiveCpu;
2975            pnew.mNumCachedKill = mNumCachedKill;
2976            pnew.mMinCachedKillPss = mMinCachedKillPss;
2977            pnew.mAvgCachedKillPss = mAvgCachedKillPss;
2978            pnew.mMaxCachedKillPss = mMaxCachedKillPss;
2979            pnew.mActive = mActive;
2980            pnew.mNumActiveServices = mNumActiveServices;
2981            pnew.mNumStartedServices = mNumStartedServices;
2982            return pnew;
2983        }
2984
2985        void add(ProcessState other) {
2986            addDurations(other);
2987            for (int i=0; i<other.mPssTableSize; i++) {
2988                int ent = other.mPssTable[i];
2989                int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
2990                addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
2991                        other.mStats.getLong(ent, PSS_MINIMUM),
2992                        other.mStats.getLong(ent, PSS_AVERAGE),
2993                        other.mStats.getLong(ent, PSS_MAXIMUM),
2994                        other.mStats.getLong(ent, PSS_USS_MINIMUM),
2995                        other.mStats.getLong(ent, PSS_USS_AVERAGE),
2996                        other.mStats.getLong(ent, PSS_USS_MAXIMUM));
2997            }
2998            mNumExcessiveWake += other.mNumExcessiveWake;
2999            mNumExcessiveCpu += other.mNumExcessiveCpu;
3000            if (other.mNumCachedKill > 0) {
3001                addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
3002                        other.mAvgCachedKillPss, other.mMaxCachedKillPss);
3003            }
3004        }
3005
3006        void resetSafely(long now) {
3007            resetDurationsSafely();
3008            mStartTime = now;
3009            mLastPssState = STATE_NOTHING;
3010            mLastPssTime = 0;
3011            mPssTable = null;
3012            mPssTableSize = 0;
3013            mNumExcessiveWake = 0;
3014            mNumExcessiveCpu = 0;
3015            mNumCachedKill = 0;
3016            mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
3017        }
3018
3019        void makeDead() {
3020            mDead = true;
3021        }
3022
3023        private void ensureNotDead() {
3024            if (!mDead) {
3025                return;
3026            }
3027            Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
3028                    + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
3029        }
3030
3031        void writeToParcel(Parcel out, long now) {
3032            out.writeInt(mMultiPackage ? 1 : 0);
3033            writeDurationsToParcel(out);
3034            out.writeInt(mPssTableSize);
3035            for (int i=0; i<mPssTableSize; i++) {
3036                if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
3037                        + printLongOffset(mPssTable[i]));
3038                out.writeInt(mPssTable[i]);
3039            }
3040            out.writeInt(mNumExcessiveWake);
3041            out.writeInt(mNumExcessiveCpu);
3042            out.writeInt(mNumCachedKill);
3043            if (mNumCachedKill > 0) {
3044                out.writeLong(mMinCachedKillPss);
3045                out.writeLong(mAvgCachedKillPss);
3046                out.writeLong(mMaxCachedKillPss);
3047            }
3048        }
3049
3050        boolean readFromParcel(Parcel in, boolean fully) {
3051            boolean multiPackage = in.readInt() != 0;
3052            if (fully) {
3053                mMultiPackage = multiPackage;
3054            }
3055            if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
3056            if (!readDurationsFromParcel(in)) {
3057                return false;
3058            }
3059            if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
3060            mPssTable = mStats.readTableFromParcel(in, mName, "pss");
3061            if (mPssTable == BAD_TABLE) {
3062                return false;
3063            }
3064            mPssTableSize = mPssTable != null ? mPssTable.length : 0;
3065            mNumExcessiveWake = in.readInt();
3066            mNumExcessiveCpu = in.readInt();
3067            mNumCachedKill = in.readInt();
3068            if (mNumCachedKill > 0) {
3069                mMinCachedKillPss = in.readLong();
3070                mAvgCachedKillPss = in.readLong();
3071                mMaxCachedKillPss = in.readLong();
3072            } else {
3073                mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
3074            }
3075            return true;
3076        }
3077
3078        public void makeActive() {
3079            ensureNotDead();
3080            mActive = true;
3081        }
3082
3083        public void makeInactive() {
3084            mActive = false;
3085        }
3086
3087        public boolean isInUse() {
3088            return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
3089                    || mCurState != STATE_NOTHING;
3090        }
3091
3092        /**
3093         * Update the current state of the given list of processes.
3094         *
3095         * @param state Current ActivityManager.PROCESS_STATE_*
3096         * @param memFactor Current mem factor constant.
3097         * @param now Current time.
3098         * @param pkgList Processes to update.
3099         */
3100        public void setState(int state, int memFactor, long now,
3101                ArrayMap<String, ProcessStateHolder> pkgList) {
3102            if (state < 0) {
3103                state = mNumStartedServices > 0
3104                        ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING;
3105            } else {
3106                state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT);
3107            }
3108
3109            // First update the common process.
3110            mCommonProcess.setState(state, now);
3111
3112            // If the common process is not multi-package, there is nothing else to do.
3113            if (!mCommonProcess.mMultiPackage) {
3114                return;
3115            }
3116
3117            if (pkgList != null) {
3118                for (int ip=pkgList.size()-1; ip>=0; ip--) {
3119                    pullFixedProc(pkgList, ip).setState(state, now);
3120                }
3121            }
3122        }
3123
3124        void setState(int state, long now) {
3125            ensureNotDead();
3126            if (mCurState != state) {
3127                //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
3128                commitStateTime(now);
3129                mCurState = state;
3130            }
3131        }
3132
3133        void commitStateTime(long now) {
3134            if (mCurState != STATE_NOTHING) {
3135                long dur = now - mStartTime;
3136                if (dur > 0) {
3137                    addDuration(mCurState, dur);
3138                }
3139            }
3140            mStartTime = now;
3141        }
3142
3143        void incActiveServices(String serviceName) {
3144            if (DEBUG && "".equals(mName)) {
3145                RuntimeException here = new RuntimeException("here");
3146                here.fillInStackTrace();
3147                Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
3148                        + " to " + (mNumActiveServices+1), here);
3149            }
3150            if (mCommonProcess != this) {
3151                mCommonProcess.incActiveServices(serviceName);
3152            }
3153            mNumActiveServices++;
3154        }
3155
3156        void decActiveServices(String serviceName) {
3157            if (DEBUG && "".equals(mName)) {
3158                RuntimeException here = new RuntimeException("here");
3159                here.fillInStackTrace();
3160                Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
3161                        + " to " + (mNumActiveServices-1), here);
3162            }
3163            if (mCommonProcess != this) {
3164                mCommonProcess.decActiveServices(serviceName);
3165            }
3166            mNumActiveServices--;
3167            if (mNumActiveServices < 0) {
3168                Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
3169                        + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
3170                mNumActiveServices = 0;
3171            }
3172        }
3173
3174        void incStartedServices(int memFactor, long now, String serviceName) {
3175            if (false) {
3176                RuntimeException here = new RuntimeException("here");
3177                here.fillInStackTrace();
3178                Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
3179                        + " to " + (mNumStartedServices+1), here);
3180            }
3181            if (mCommonProcess != this) {
3182                mCommonProcess.incStartedServices(memFactor, now, serviceName);
3183            }
3184            mNumStartedServices++;
3185            if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
3186                setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
3187            }
3188        }
3189
3190        void decStartedServices(int memFactor, long now, String serviceName) {
3191            if (false) {
3192                RuntimeException here = new RuntimeException("here");
3193                here.fillInStackTrace();
3194                Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
3195                        + " to " + (mNumStartedServices-1), here);
3196            }
3197            if (mCommonProcess != this) {
3198                mCommonProcess.decStartedServices(memFactor, now, serviceName);
3199            }
3200            mNumStartedServices--;
3201            if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
3202                setState(STATE_NOTHING, now);
3203            } else if (mNumStartedServices < 0) {
3204                Slog.wtfStack(TAG, "Proc started services underrun: pkg="
3205                        + mPackage + " uid=" + mUid + " name=" + mName);
3206                mNumStartedServices = 0;
3207            }
3208        }
3209
3210        public void addPss(long pss, long uss, boolean always,
3211                ArrayMap<String, ProcessStateHolder> pkgList) {
3212            ensureNotDead();
3213            if (!always) {
3214                if (mLastPssState == mCurState && SystemClock.uptimeMillis()
3215                        < (mLastPssTime+(30*1000))) {
3216                    return;
3217                }
3218            }
3219            mLastPssState = mCurState;
3220            mLastPssTime = SystemClock.uptimeMillis();
3221            if (mCurState != STATE_NOTHING) {
3222                // First update the common process.
3223                mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
3224
3225                // If the common process is not multi-package, there is nothing else to do.
3226                if (!mCommonProcess.mMultiPackage) {
3227                    return;
3228                }
3229
3230                if (pkgList != null) {
3231                    for (int ip=pkgList.size()-1; ip>=0; ip--) {
3232                        pullFixedProc(pkgList, ip).addPss(mCurState, 1,
3233                                pss, pss, pss, uss, uss, uss);
3234                    }
3235                }
3236            }
3237        }
3238
3239        void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
3240                long avgUss, long maxUss) {
3241            int idx = binarySearch(mPssTable, mPssTableSize, state);
3242            int off;
3243            if (idx >= 0) {
3244                off = mPssTable[idx];
3245            } else {
3246                mStats.mAddLongTable = mPssTable;
3247                mStats.mAddLongTableSize = mPssTableSize;
3248                off = mStats.addLongData(~idx, state, PSS_COUNT);
3249                mPssTable = mStats.mAddLongTable;
3250                mPssTableSize = mStats.mAddLongTableSize;
3251            }
3252            long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
3253            idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
3254            long count = longs[idx+PSS_SAMPLE_COUNT];
3255            if (count == 0) {
3256                longs[idx+PSS_SAMPLE_COUNT] = inCount;
3257                longs[idx+PSS_MINIMUM] = minPss;
3258                longs[idx+PSS_AVERAGE] = avgPss;
3259                longs[idx+PSS_MAXIMUM] = maxPss;
3260                longs[idx+PSS_USS_MINIMUM] = minUss;
3261                longs[idx+PSS_USS_AVERAGE] = avgUss;
3262                longs[idx+PSS_USS_MAXIMUM] = maxUss;
3263            } else {
3264                longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
3265                if (longs[idx+PSS_MINIMUM] > minPss) {
3266                    longs[idx+PSS_MINIMUM] = minPss;
3267                }
3268                longs[idx+PSS_AVERAGE] = (long)(
3269                        ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
3270                                / (count+inCount) );
3271                if (longs[idx+PSS_MAXIMUM] < maxPss) {
3272                    longs[idx+PSS_MAXIMUM] = maxPss;
3273                }
3274                if (longs[idx+PSS_USS_MINIMUM] > minUss) {
3275                    longs[idx+PSS_USS_MINIMUM] = minUss;
3276                }
3277                longs[idx+PSS_USS_AVERAGE] = (long)(
3278                        ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
3279                                / (count+inCount) );
3280                if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
3281                    longs[idx+PSS_USS_MAXIMUM] = maxUss;
3282                }
3283            }
3284        }
3285
3286        public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) {
3287            ensureNotDead();
3288            mCommonProcess.mNumExcessiveWake++;
3289            if (!mCommonProcess.mMultiPackage) {
3290                return;
3291            }
3292
3293            for (int ip=pkgList.size()-1; ip>=0; ip--) {
3294                pullFixedProc(pkgList, ip).mNumExcessiveWake++;
3295            }
3296        }
3297
3298        public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) {
3299            ensureNotDead();
3300            mCommonProcess.mNumExcessiveCpu++;
3301            if (!mCommonProcess.mMultiPackage) {
3302                return;
3303            }
3304
3305            for (int ip=pkgList.size()-1; ip>=0; ip--) {
3306                pullFixedProc(pkgList, ip).mNumExcessiveCpu++;
3307            }
3308        }
3309
3310        private void addCachedKill(int num, long minPss, long avgPss, long maxPss) {
3311            if (mNumCachedKill <= 0) {
3312                mNumCachedKill = num;
3313                mMinCachedKillPss = minPss;
3314                mAvgCachedKillPss = avgPss;
3315                mMaxCachedKillPss = maxPss;
3316            } else {
3317                if (minPss < mMinCachedKillPss) {
3318                    mMinCachedKillPss = minPss;
3319                }
3320                if (maxPss > mMaxCachedKillPss) {
3321                    mMaxCachedKillPss = maxPss;
3322                }
3323                mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss)
3324                        / (mNumCachedKill+num) );
3325                mNumCachedKill += num;
3326            }
3327        }
3328
3329        public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) {
3330            ensureNotDead();
3331            mCommonProcess.addCachedKill(1, pss, pss, pss);
3332            if (!mCommonProcess.mMultiPackage) {
3333                return;
3334            }
3335
3336            for (int ip=pkgList.size()-1; ip>=0; ip--) {
3337                pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss);
3338            }
3339        }
3340
3341        ProcessState pullFixedProc(String pkgName) {
3342            if (mMultiPackage) {
3343                // The array map is still pointing to a common process state
3344                // that is now shared across packages.  Update it to point to
3345                // the new per-package state.
3346                SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid);
3347                if (vpkg == null) {
3348                    throw new IllegalStateException("Didn't find package " + pkgName
3349                            + " / " + mUid);
3350                }
3351                PackageState pkg = vpkg.get(mVersion);
3352                if (pkg == null) {
3353                    throw new IllegalStateException("Didn't find package " + pkgName
3354                            + " / " + mUid + " vers " + mVersion);
3355                }
3356                ProcessState proc = pkg.mProcesses.get(mName);
3357                if (proc == null) {
3358                    throw new IllegalStateException("Didn't create per-package process "
3359                            + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion);
3360                }
3361                return proc;
3362            }
3363            return this;
3364        }
3365
3366        private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList,
3367                int index) {
3368            ProcessStateHolder holder = pkgList.valueAt(index);
3369            ProcessState proc = holder.state;
3370            if (mDead && proc.mCommonProcess != proc) {
3371                // Somehow we are contining to use a process state that is dead, because
3372                // it was not being told it was active during the last commit.  We can recover
3373                // from this by generating a fresh new state, but this is bad because we
3374                // are losing whatever data we had in the old process state.
3375                Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage
3376                        + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
3377                proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion,
3378                        proc.mName);
3379            }
3380            if (proc.mMultiPackage) {
3381                // The array map is still pointing to a common process state
3382                // that is now shared across packages.  Update it to point to
3383                // the new per-package state.
3384                SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index),
3385                        proc.mUid);
3386                if (vpkg == null) {
3387                    throw new IllegalStateException("No existing package "
3388                            + pkgList.keyAt(index) + "/" + proc.mUid
3389                            + " for multi-proc " + proc.mName);
3390                }
3391                PackageState pkg = vpkg.get(proc.mVersion);
3392                if (pkg == null) {
3393                    throw new IllegalStateException("No existing package "
3394                            + pkgList.keyAt(index) + "/" + proc.mUid
3395                            + " for multi-proc " + proc.mName + " version " + proc.mVersion);
3396                }
3397                proc = pkg.mProcesses.get(proc.mName);
3398                if (proc == null) {
3399                    throw new IllegalStateException("Didn't create per-package process "
3400                            + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
3401                }
3402                holder.state = proc;
3403            }
3404            return proc;
3405        }
3406
3407        long getDuration(int state, long now) {
3408            long time = super.getDuration(state, now);
3409            if (mCurState == state) {
3410                time += now - mStartTime;
3411            }
3412            return time;
3413        }
3414
3415        long getPssSampleCount(int state) {
3416            int idx = binarySearch(mPssTable, mPssTableSize, state);
3417            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
3418        }
3419
3420        long getPssMinimum(int state) {
3421            int idx = binarySearch(mPssTable, mPssTableSize, state);
3422            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
3423        }
3424
3425        long getPssAverage(int state) {
3426            int idx = binarySearch(mPssTable, mPssTableSize, state);
3427            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
3428        }
3429
3430        long getPssMaximum(int state) {
3431            int idx = binarySearch(mPssTable, mPssTableSize, state);
3432            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
3433        }
3434
3435        long getPssUssMinimum(int state) {
3436            int idx = binarySearch(mPssTable, mPssTableSize, state);
3437            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
3438        }
3439
3440        long getPssUssAverage(int state) {
3441            int idx = binarySearch(mPssTable, mPssTableSize, state);
3442            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
3443        }
3444
3445        long getPssUssMaximum(int state) {
3446            int idx = binarySearch(mPssTable, mPssTableSize, state);
3447            return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
3448        }
3449
3450        public String toString() {
3451            StringBuilder sb = new StringBuilder(128);
3452            sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
3453                    .append(" ").append(mName).append("/").append(mUid)
3454                    .append(" pkg=").append(mPackage);
3455            if (mMultiPackage) sb.append(" (multi)");
3456            if (mCommonProcess != this) sb.append(" (sub)");
3457            sb.append("}");
3458            return sb.toString();
3459        }
3460    }
3461
3462    public static final class ServiceState extends DurationsTable {
3463        public final String mPackage;
3464        public final String mProcessName;
3465        ProcessState mProc;
3466
3467        Object mOwner;
3468
3469        public static final int SERVICE_RUN = 0;
3470        public static final int SERVICE_STARTED = 1;
3471        public static final int SERVICE_BOUND = 2;
3472        public static final int SERVICE_EXEC = 3;
3473        static final int SERVICE_COUNT = 4;
3474
3475        int mRunCount;
3476        public int mRunState = STATE_NOTHING;
3477        long mRunStartTime;
3478
3479        boolean mStarted;
3480        boolean mRestarting;
3481        int mStartedCount;
3482        public int mStartedState = STATE_NOTHING;
3483        long mStartedStartTime;
3484
3485        int mBoundCount;
3486        public int mBoundState = STATE_NOTHING;
3487        long mBoundStartTime;
3488
3489        int mExecCount;
3490        public int mExecState = STATE_NOTHING;
3491        long mExecStartTime;
3492
3493        public ServiceState(ProcessStats processStats, String pkg, String name,
3494                String processName, ProcessState proc) {
3495            super(processStats, name);
3496            mPackage = pkg;
3497            mProcessName = processName;
3498            mProc = proc;
3499        }
3500
3501        public void applyNewOwner(Object newOwner) {
3502            if (mOwner != newOwner) {
3503                if (mOwner == null) {
3504                    mOwner = newOwner;
3505                    mProc.incActiveServices(mName);
3506                } else {
3507                    // There was already an old owner, reset this object for its
3508                    // new owner.
3509                    mOwner = newOwner;
3510                    if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
3511                        long now = SystemClock.uptimeMillis();
3512                        if (mStarted) {
3513                            if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
3514                                    + " from " + mOwner + " while started: pkg="
3515                                    + mPackage + " service=" + mName + " proc=" + mProc);
3516                            setStarted(false, 0, now);
3517                        }
3518                        if (mBoundState != STATE_NOTHING) {
3519                            if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
3520                                    + " from " + mOwner + " while bound: pkg="
3521                                    + mPackage + " service=" + mName + " proc=" + mProc);
3522                            setBound(false, 0, now);
3523                        }
3524                        if (mExecState != STATE_NOTHING) {
3525                            if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
3526                                    + " from " + mOwner + " while executing: pkg="
3527                                    + mPackage + " service=" + mName + " proc=" + mProc);
3528                            setExecuting(false, 0, now);
3529                        }
3530                    }
3531                }
3532            }
3533        }
3534
3535        public void clearCurrentOwner(Object owner, boolean silently) {
3536            if (mOwner == owner) {
3537                mProc.decActiveServices(mName);
3538                if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
3539                    long now = SystemClock.uptimeMillis();
3540                    if (mStarted) {
3541                        if (!silently) {
3542                            Slog.wtfStack(TAG, "Service owner " + owner
3543                                    + " cleared while started: pkg=" + mPackage + " service="
3544                                    + mName + " proc=" + mProc);
3545                        }
3546                        setStarted(false, 0, now);
3547                    }
3548                    if (mBoundState != STATE_NOTHING) {
3549                        if (!silently) {
3550                            Slog.wtfStack(TAG, "Service owner " + owner
3551                                    + " cleared while bound: pkg=" + mPackage + " service="
3552                                    + mName + " proc=" + mProc);
3553                        }
3554                        setBound(false, 0, now);
3555                    }
3556                    if (mExecState != STATE_NOTHING) {
3557                        if (!silently) {
3558                            Slog.wtfStack(TAG, "Service owner " + owner
3559                                    + " cleared while exec: pkg=" + mPackage + " service="
3560                                    + mName + " proc=" + mProc);
3561                        }
3562                        setExecuting(false, 0, now);
3563                    }
3564                }
3565                mOwner = null;
3566            }
3567        }
3568
3569        public boolean isInUse() {
3570            return mOwner != null || mRestarting;
3571        }
3572
3573        public boolean isRestarting() {
3574            return mRestarting;
3575        }
3576
3577        void add(ServiceState other) {
3578            addDurations(other);
3579            mRunCount += other.mRunCount;
3580            mStartedCount += other.mStartedCount;
3581            mBoundCount += other.mBoundCount;
3582            mExecCount += other.mExecCount;
3583        }
3584
3585        void resetSafely(long now) {
3586            resetDurationsSafely();
3587            mRunCount = mRunState != STATE_NOTHING ? 1 : 0;
3588            mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
3589            mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
3590            mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
3591            mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now;
3592        }
3593
3594        void writeToParcel(Parcel out, long now) {
3595            writeDurationsToParcel(out);
3596            out.writeInt(mRunCount);
3597            out.writeInt(mStartedCount);
3598            out.writeInt(mBoundCount);
3599            out.writeInt(mExecCount);
3600        }
3601
3602        boolean readFromParcel(Parcel in) {
3603            if (!readDurationsFromParcel(in)) {
3604                return false;
3605            }
3606            mRunCount = in.readInt();
3607            mStartedCount = in.readInt();
3608            mBoundCount = in.readInt();
3609            mExecCount = in.readInt();
3610            return true;
3611        }
3612
3613        void commitStateTime(long now) {
3614            if (mRunState != STATE_NOTHING) {
3615                addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime);
3616                mRunStartTime = now;
3617            }
3618            if (mStartedState != STATE_NOTHING) {
3619                addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
3620                        now - mStartedStartTime);
3621                mStartedStartTime = now;
3622            }
3623            if (mBoundState != STATE_NOTHING) {
3624                addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
3625                mBoundStartTime = now;
3626            }
3627            if (mExecState != STATE_NOTHING) {
3628                addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
3629                mExecStartTime = now;
3630            }
3631        }
3632
3633        private void updateRunning(int memFactor, long now) {
3634            final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
3635                    || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
3636            if (mRunState != state) {
3637                if (mRunState != STATE_NOTHING) {
3638                    addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT),
3639                            now - mRunStartTime);
3640                } else if (state != STATE_NOTHING) {
3641                    mRunCount++;
3642                }
3643                mRunState = state;
3644                mRunStartTime = now;
3645            }
3646        }
3647
3648        public void setStarted(boolean started, int memFactor, long now) {
3649            if (mOwner == null) {
3650                Slog.wtf(TAG, "Starting service " + this + " without owner");
3651            }
3652            mStarted = started;
3653            updateStartedState(memFactor, now);
3654        }
3655
3656        public void setRestarting(boolean restarting, int memFactor, long now) {
3657            mRestarting = restarting;
3658            updateStartedState(memFactor, now);
3659        }
3660
3661        void updateStartedState(int memFactor, long now) {
3662            final boolean wasStarted = mStartedState != STATE_NOTHING;
3663            final boolean started = mStarted || mRestarting;
3664            final int state = started ? memFactor : STATE_NOTHING;
3665            if (mStartedState != state) {
3666                if (mStartedState != STATE_NOTHING) {
3667                    addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
3668                            now - mStartedStartTime);
3669                } else if (started) {
3670                    mStartedCount++;
3671                }
3672                mStartedState = state;
3673                mStartedStartTime = now;
3674                mProc = mProc.pullFixedProc(mPackage);
3675                if (wasStarted != started) {
3676                    if (started) {
3677                        mProc.incStartedServices(memFactor, now, mName);
3678                    } else {
3679                        mProc.decStartedServices(memFactor, now, mName);
3680                    }
3681                }
3682                updateRunning(memFactor, now);
3683            }
3684        }
3685
3686        public void setBound(boolean bound, int memFactor, long now) {
3687            if (mOwner == null) {
3688                Slog.wtf(TAG, "Binding service " + this + " without owner");
3689            }
3690            final int state = bound ? memFactor : STATE_NOTHING;
3691            if (mBoundState != state) {
3692                if (mBoundState != STATE_NOTHING) {
3693                    addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
3694                            now - mBoundStartTime);
3695                } else if (bound) {
3696                    mBoundCount++;
3697                }
3698                mBoundState = state;
3699                mBoundStartTime = now;
3700                updateRunning(memFactor, now);
3701            }
3702        }
3703
3704        public void setExecuting(boolean executing, int memFactor, long now) {
3705            if (mOwner == null) {
3706                Slog.wtf(TAG, "Executing service " + this + " without owner");
3707            }
3708            final int state = executing ? memFactor : STATE_NOTHING;
3709            if (mExecState != state) {
3710                if (mExecState != STATE_NOTHING) {
3711                    addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
3712                } else if (executing) {
3713                    mExecCount++;
3714                }
3715                mExecState = state;
3716                mExecStartTime = now;
3717                updateRunning(memFactor, now);
3718            }
3719        }
3720
3721        private long getDuration(int opType, int curState, long startTime, int memFactor,
3722                long now) {
3723            int state = opType + (memFactor*SERVICE_COUNT);
3724            long time = getDuration(state, now);
3725            if (curState == memFactor) {
3726                time += now - startTime;
3727            }
3728            return time;
3729        }
3730
3731        public String toString() {
3732            return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
3733                    + " " + mName + " pkg=" + mPackage + " proc="
3734                    + Integer.toHexString(System.identityHashCode(this)) + "}";
3735        }
3736    }
3737
3738    public static final class PackageState {
3739        public final ArrayMap<String, ProcessState> mProcesses
3740                = new ArrayMap<String, ProcessState>();
3741        public final ArrayMap<String, ServiceState> mServices
3742                = new ArrayMap<String, ServiceState>();
3743        public final String mPackageName;
3744        public final int mUid;
3745
3746        public PackageState(String packageName, int uid) {
3747            mUid = uid;
3748            mPackageName = packageName;
3749        }
3750    }
3751
3752    public static final class ProcessDataCollection {
3753        final int[] screenStates;
3754        final int[] memStates;
3755        final int[] procStates;
3756
3757        public long totalTime;
3758        public long numPss;
3759        public long minPss;
3760        public long avgPss;
3761        public long maxPss;
3762        public long minUss;
3763        public long avgUss;
3764        public long maxUss;
3765
3766        public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
3767            screenStates = _screenStates;
3768            memStates = _memStates;
3769            procStates = _procStates;
3770        }
3771
3772        void print(PrintWriter pw, long overallTime, boolean full) {
3773            if (totalTime > overallTime) {
3774                pw.print("*");
3775            }
3776            printPercent(pw, (double) totalTime / (double) overallTime);
3777            if (numPss > 0) {
3778                pw.print(" (");
3779                printSizeValue(pw, minPss * 1024);
3780                pw.print("-");
3781                printSizeValue(pw, avgPss * 1024);
3782                pw.print("-");
3783                printSizeValue(pw, maxPss * 1024);
3784                pw.print("/");
3785                printSizeValue(pw, minUss * 1024);
3786                pw.print("-");
3787                printSizeValue(pw, avgUss * 1024);
3788                pw.print("-");
3789                printSizeValue(pw, maxUss * 1024);
3790                if (full) {
3791                    pw.print(" over ");
3792                    pw.print(numPss);
3793                }
3794                pw.print(")");
3795            }
3796        }
3797    }
3798
3799    public static class TotalMemoryUseCollection {
3800        final int[] screenStates;
3801        final int[] memStates;
3802
3803        public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) {
3804            screenStates = _screenStates;
3805            memStates = _memStates;
3806        }
3807
3808        public long totalTime;
3809        public long[] processStatePss = new long[STATE_COUNT];
3810        public double[] processStateWeight = new double[STATE_COUNT];
3811        public long[] processStateTime = new long[STATE_COUNT];
3812        public int[] processStateSamples = new int[STATE_COUNT];
3813        public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT];
3814        public double sysMemCachedWeight;
3815        public double sysMemFreeWeight;
3816        public double sysMemZRamWeight;
3817        public double sysMemKernelWeight;
3818        public double sysMemNativeWeight;
3819        public int sysMemSamples;
3820    }
3821}
3822