ProcessStats.java revision 4eb64fdbcf899a81d0a6a04dc3658d03d9df8247
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.procstats;
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.DebugUtils;
28import android.util.Log;
29import android.util.Slog;
30import android.util.SparseArray;
31import android.util.TimeUtils;
32
33import com.android.internal.app.ProcessMap;
34import com.android.internal.app.procstats.DurationsTable;
35import com.android.internal.app.procstats.ProcessState;
36import com.android.internal.app.procstats.PssTable;
37import com.android.internal.app.procstats.ServiceState;
38import com.android.internal.app.procstats.SparseMappingTable;
39import com.android.internal.app.procstats.SysMemUsageTable;
40import com.android.internal.app.procstats.DumpUtils.*;
41
42import dalvik.system.VMRuntime;
43import libcore.util.EmptyArray;
44
45import java.io.IOException;
46import java.io.InputStream;
47import java.io.PrintWriter;
48import java.util.ArrayList;
49import java.util.Arrays;
50import java.util.Collections;
51import java.util.Comparator;
52import java.util.Objects;
53
54public final class ProcessStats implements Parcelable {
55    public static final String TAG = "ProcessStats";
56    static final boolean DEBUG = false;
57    static final boolean DEBUG_PARCEL = false;
58
59    public static final String SERVICE_NAME = "procstats";
60
61    // How often the service commits its data, giving the minimum batching
62    // that is done.
63    public static long COMMIT_PERIOD = 3*60*60*1000;  // Commit current stats every 3 hours
64
65    // Minimum uptime period before committing.  If the COMMIT_PERIOD has elapsed but
66    // the total uptime has not exceeded this amount, then the commit will be held until
67    // it is reached.
68    public static long COMMIT_UPTIME_PERIOD = 60*60*1000;  // Must have at least 1 hour elapsed
69
70    public static final int STATE_NOTHING = -1;
71    public static final int STATE_PERSISTENT = 0;
72    public static final int STATE_TOP = 1;
73    public static final int STATE_IMPORTANT_FOREGROUND = 2;
74    public static final int STATE_IMPORTANT_BACKGROUND = 3;
75    public static final int STATE_BACKUP = 4;
76    public static final int STATE_HEAVY_WEIGHT = 5;
77    public static final int STATE_SERVICE = 6;
78    public static final int STATE_SERVICE_RESTARTING = 7;
79    public static final int STATE_RECEIVER = 8;
80    public static final int STATE_HOME = 9;
81    public static final int STATE_LAST_ACTIVITY = 10;
82    public static final int STATE_CACHED_ACTIVITY = 11;
83    public static final int STATE_CACHED_ACTIVITY_CLIENT = 12;
84    public static final int STATE_CACHED_EMPTY = 13;
85    public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
86
87    public static final int PSS_SAMPLE_COUNT = 0;
88    public static final int PSS_MINIMUM = 1;
89    public static final int PSS_AVERAGE = 2;
90    public static final int PSS_MAXIMUM = 3;
91    public static final int PSS_USS_MINIMUM = 4;
92    public static final int PSS_USS_AVERAGE = 5;
93    public static final int PSS_USS_MAXIMUM = 6;
94    public static final int PSS_COUNT = PSS_USS_MAXIMUM+1;
95
96    public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0;
97    public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1;
98    public static final int SYS_MEM_USAGE_CACHED_AVERAGE = 2;
99    public static final int SYS_MEM_USAGE_CACHED_MAXIMUM = 3;
100    public static final int SYS_MEM_USAGE_FREE_MINIMUM = 4;
101    public static final int SYS_MEM_USAGE_FREE_AVERAGE = 5;
102    public static final int SYS_MEM_USAGE_FREE_MAXIMUM = 6;
103    public static final int SYS_MEM_USAGE_ZRAM_MINIMUM = 7;
104    public static final int SYS_MEM_USAGE_ZRAM_AVERAGE = 8;
105    public static final int SYS_MEM_USAGE_ZRAM_MAXIMUM = 9;
106    public static final int SYS_MEM_USAGE_KERNEL_MINIMUM = 10;
107    public static final int SYS_MEM_USAGE_KERNEL_AVERAGE = 11;
108    public static final int SYS_MEM_USAGE_KERNEL_MAXIMUM = 12;
109    public static final int SYS_MEM_USAGE_NATIVE_MINIMUM = 13;
110    public static final int SYS_MEM_USAGE_NATIVE_AVERAGE = 14;
111    public static final int SYS_MEM_USAGE_NATIVE_MAXIMUM = 15;
112    public static final int SYS_MEM_USAGE_COUNT = SYS_MEM_USAGE_NATIVE_MAXIMUM+1;
113
114    public static final int ADJ_NOTHING = -1;
115    public static final int ADJ_MEM_FACTOR_NORMAL = 0;
116    public static final int ADJ_MEM_FACTOR_MODERATE = 1;
117    public static final int ADJ_MEM_FACTOR_LOW = 2;
118    public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
119    public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
120    public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
121    public static final int ADJ_SCREEN_OFF = 0;
122    public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
123    public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
124
125    public static final int FLAG_COMPLETE = 1<<0;
126    public static final int FLAG_SHUTDOWN = 1<<1;
127    public static final int FLAG_SYSPROPS = 1<<2;
128
129    public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
130            ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
131
132    public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
133
134    public static final int[] NON_CACHED_PROC_STATES = new int[] {
135            STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
136            STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT,
137            STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
138    };
139
140    public static final int[] BACKGROUND_PROC_STATES = new int[] {
141            STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
142            STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
143    };
144
145    public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
146            STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
147            STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER,
148            STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
149            STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
150    };
151
152    // Current version of the parcel format.
153    private static final int PARCEL_VERSION = 19;
154    // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
155    private static final int MAGIC = 0x50535454;
156
157    public String mReadError;
158    public String mTimePeriodStartClockStr;
159    public int mFlags;
160
161    public final ProcessMap<SparseArray<PackageState>> mPackages
162            = new ProcessMap<SparseArray<PackageState>>();
163    public final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
164
165    public final long[] mMemFactorDurations = new long[ADJ_COUNT];
166    public int mMemFactor = STATE_NOTHING;
167    public long mStartTime;
168
169    public long mTimePeriodStartClock;
170    public long mTimePeriodStartRealtime;
171    public long mTimePeriodEndRealtime;
172    public long mTimePeriodStartUptime;
173    public long mTimePeriodEndUptime;
174    String mRuntime;
175    boolean mRunning;
176
177    public final SparseMappingTable mTableData = new SparseMappingTable();
178
179    int[] mAddLongTable;
180    int mAddLongTableSize;
181
182    public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT];
183    public final SysMemUsageTable mSysMemUsage = new SysMemUsageTable(mTableData);
184
185    // For writing parcels.
186    ArrayMap<String, Integer> mCommonStringToIndex;
187
188    // For reading parcels.
189    ArrayList<String> mIndexToCommonString;
190
191    public ProcessStats(boolean running) {
192        mRunning = running;
193        reset();
194    }
195
196    public ProcessStats(Parcel in) {
197        reset();
198        readFromParcel(in);
199    }
200
201    public void add(ProcessStats other) {
202        ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = other.mPackages.getMap();
203        for (int ip=0; ip<pkgMap.size(); ip++) {
204            final String pkgName = pkgMap.keyAt(ip);
205            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
206            for (int iu=0; iu<uids.size(); iu++) {
207                final int uid = uids.keyAt(iu);
208                final SparseArray<PackageState> versions = uids.valueAt(iu);
209                for (int iv=0; iv<versions.size(); iv++) {
210                    final int vers = versions.keyAt(iv);
211                    final PackageState otherState = versions.valueAt(iv);
212                    final int NPROCS = otherState.mProcesses.size();
213                    final int NSRVS = otherState.mServices.size();
214                    for (int iproc=0; iproc<NPROCS; iproc++) {
215                        ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
216                        if (otherProc.getCommonProcess() != otherProc) {
217                            if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
218                                    + " vers " + vers + " proc " + otherProc.getName());
219                            ProcessState thisProc = getProcessStateLocked(pkgName, uid, vers,
220                                    otherProc.getName());
221                            if (thisProc.getCommonProcess() == thisProc) {
222                                if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
223                                thisProc.setMultiPackage(true);
224                                long now = SystemClock.uptimeMillis();
225                                final PackageState pkgState = getPackageStateLocked(pkgName, uid,
226                                        vers);
227                                thisProc = thisProc.clone(now);
228                                pkgState.mProcesses.put(thisProc.getName(), thisProc);
229                            }
230                            thisProc.add(otherProc);
231                        }
232                    }
233                    for (int isvc=0; isvc<NSRVS; isvc++) {
234                        ServiceState otherSvc = otherState.mServices.valueAt(isvc);
235                        if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
236                                + " service " + otherSvc.getName());
237                        ServiceState thisSvc = getServiceStateLocked(pkgName, uid, vers,
238                                otherSvc.getProcessName(), otherSvc.getName());
239                        thisSvc.add(otherSvc);
240                    }
241                }
242            }
243        }
244
245        ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
246        for (int ip=0; ip<procMap.size(); ip++) {
247            SparseArray<ProcessState> uids = procMap.valueAt(ip);
248            for (int iu=0; iu<uids.size(); iu++) {
249                int uid = uids.keyAt(iu);
250                ProcessState otherProc = uids.valueAt(iu);
251                final String name = otherProc.getName();
252                final String pkg = otherProc.getPackage();
253                final int vers = otherProc.getVersion();
254                ProcessState thisProc = mProcesses.get(name, uid);
255                if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + name);
256                if (thisProc == null) {
257                    if (DEBUG) Slog.d(TAG, "Creating new process!");
258                    thisProc = new ProcessState(this, pkg, uid, vers, name);
259                    mProcesses.put(name, uid, thisProc);
260                    PackageState thisState = getPackageStateLocked(pkg, uid, vers);
261                    if (!thisState.mProcesses.containsKey(name)) {
262                        thisState.mProcesses.put(name, thisProc);
263                    }
264                }
265                thisProc.add(otherProc);
266            }
267        }
268
269        for (int i=0; i<ADJ_COUNT; i++) {
270            if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
271                    + other.mMemFactorDurations[i] + " from "
272                    + mMemFactorDurations[i]);
273            mMemFactorDurations[i] += other.mMemFactorDurations[i];
274        }
275
276        mSysMemUsage.mergeStats(other.mSysMemUsage);
277
278        if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
279            mTimePeriodStartClock = other.mTimePeriodStartClock;
280            mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
281        }
282        mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
283        mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime;
284    }
285
286    public void addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem,
287            long nativeMem) {
288        if (mMemFactor != STATE_NOTHING) {
289            int state = mMemFactor * STATE_COUNT;
290            mSysMemUsageArgs[SYS_MEM_USAGE_SAMPLE_COUNT] = 1;
291            for (int i=0; i<3; i++) {
292                mSysMemUsageArgs[SYS_MEM_USAGE_CACHED_MINIMUM + i] = cachedMem;
293                mSysMemUsageArgs[SYS_MEM_USAGE_FREE_MINIMUM + i] = freeMem;
294                mSysMemUsageArgs[SYS_MEM_USAGE_ZRAM_MINIMUM + i] = zramMem;
295                mSysMemUsageArgs[SYS_MEM_USAGE_KERNEL_MINIMUM + i] = kernelMem;
296                mSysMemUsageArgs[SYS_MEM_USAGE_NATIVE_MINIMUM + i] = nativeMem;
297            }
298            mSysMemUsage.mergeStats(state, mSysMemUsageArgs, 0);
299        }
300    }
301
302    public static final Parcelable.Creator<ProcessStats> CREATOR
303            = new Parcelable.Creator<ProcessStats>() {
304        public ProcessStats createFromParcel(Parcel in) {
305            return new ProcessStats(in);
306        }
307
308        public ProcessStats[] newArray(int size) {
309            return new ProcessStats[size];
310        }
311    };
312
313    public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) {
314        data.totalTime = 0;
315        for (int i=0; i<STATE_COUNT; i++) {
316            data.processStateWeight[i] = 0;
317            data.processStatePss[i] = 0;
318            data.processStateTime[i] = 0;
319            data.processStateSamples[i] = 0;
320        }
321        for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) {
322            data.sysMemUsage[i] = 0;
323        }
324        data.sysMemCachedWeight = 0;
325        data.sysMemFreeWeight = 0;
326        data.sysMemZRamWeight = 0;
327        data.sysMemKernelWeight = 0;
328        data.sysMemNativeWeight = 0;
329        data.sysMemSamples = 0;
330        final long[] totalMemUsage = mSysMemUsage.getTotalMemUsage();
331        for (int is=0; is<data.screenStates.length; is++) {
332            for (int im=0; im<data.memStates.length; im++) {
333                int memBucket = data.screenStates[is] + data.memStates[im];
334                int stateBucket = memBucket * STATE_COUNT;
335                long memTime = mMemFactorDurations[memBucket];
336                if (mMemFactor == memBucket) {
337                    memTime += now - mStartTime;
338                }
339                data.totalTime += memTime;
340                final int sysKey = mSysMemUsage.getKey((byte)stateBucket);
341                long[] longs = totalMemUsage;
342                int idx = 0;
343                if (sysKey != SparseMappingTable.INVALID_KEY) {
344                    final long[] tmpLongs = mSysMemUsage.getArrayForKey(sysKey);
345                    final int tmpIndex = SparseMappingTable.getIndexFromKey(sysKey);
346                    if (tmpLongs[tmpIndex+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) {
347                        SysMemUsageTable.mergeSysMemUsage(data.sysMemUsage, 0, longs, idx);
348                        longs = tmpLongs;
349                        idx = tmpIndex;
350                    }
351                }
352                data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE]
353                        * (double)memTime;
354                data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE]
355                        * (double)memTime;
356                data.sysMemZRamWeight += longs[idx+SYS_MEM_USAGE_ZRAM_AVERAGE]
357                        * (double)memTime;
358                data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE]
359                        * (double)memTime;
360                data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE]
361                        * (double)memTime;
362                data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT];
363             }
364        }
365        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
366        for (int iproc=0; iproc<procMap.size(); iproc++) {
367            SparseArray<ProcessState> uids = procMap.valueAt(iproc);
368            for (int iu=0; iu<uids.size(); iu++) {
369                final ProcessState proc = uids.valueAt(iu);
370                proc.aggregatePss(data, now);
371            }
372        }
373    }
374
375    public void reset() {
376        if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr);
377        resetCommon();
378        mPackages.getMap().clear();
379        mProcesses.getMap().clear();
380        mMemFactor = STATE_NOTHING;
381        mStartTime = 0;
382        if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
383    }
384
385    public void resetSafely() {
386        if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
387        resetCommon();
388
389        // First initialize use count of all common processes.
390        final long now = SystemClock.uptimeMillis();
391        final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
392        for (int ip=procMap.size()-1; ip>=0; ip--) {
393            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
394            for (int iu=uids.size()-1; iu>=0; iu--) {
395                uids.valueAt(iu).tmpNumInUse = 0;
396           }
397        }
398
399        // Next reset or prune all per-package processes, and for the ones that are reset
400        // track this back to the common processes.
401        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
402        for (int ip=pkgMap.size()-1; ip>=0; ip--) {
403            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
404            for (int iu=uids.size()-1; iu>=0; iu--) {
405                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
406                for (int iv=vpkgs.size()-1; iv>=0; iv--) {
407                    final PackageState pkgState = vpkgs.valueAt(iv);
408                    for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
409                        final ProcessState ps = pkgState.mProcesses.valueAt(iproc);
410                        if (ps.isInUse()) {
411                            ps.resetSafely(now);
412                            ps.getCommonProcess().tmpNumInUse++;
413                            ps.getCommonProcess().tmpFoundSubProc = ps;
414                        } else {
415                            pkgState.mProcesses.valueAt(iproc).makeDead();
416                            pkgState.mProcesses.removeAt(iproc);
417                        }
418                    }
419                    for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
420                        final ServiceState ss = pkgState.mServices.valueAt(isvc);
421                        if (ss.isInUse()) {
422                            ss.resetSafely(now);
423                        } else {
424                            pkgState.mServices.removeAt(isvc);
425                        }
426                    }
427                    if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
428                        vpkgs.removeAt(iv);
429                    }
430                }
431                if (vpkgs.size() <= 0) {
432                    uids.removeAt(iu);
433                }
434            }
435            if (uids.size() <= 0) {
436                pkgMap.removeAt(ip);
437            }
438        }
439
440        // Finally prune out any common processes that are no longer in use.
441        for (int ip=procMap.size()-1; ip>=0; ip--) {
442            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
443            for (int iu=uids.size()-1; iu>=0; iu--) {
444                ProcessState ps = uids.valueAt(iu);
445                if (ps.isInUse() || ps.tmpNumInUse > 0) {
446                    // If this is a process for multiple packages, we could at this point
447                    // be back down to one package.  In that case, we want to revert back
448                    // to a single shared ProcessState.  We can do this by converting the
449                    // current package-specific ProcessState up to the shared ProcessState,
450                    // throwing away the current one we have here (because nobody else is
451                    // using it).
452                    if (!ps.isActive() && ps.isMultiPackage() && ps.tmpNumInUse == 1) {
453                        // Here we go...
454                        ps = ps.tmpFoundSubProc;
455                        ps.makeStandalone();
456                        uids.setValueAt(iu, ps);
457                    } else {
458                        ps.resetSafely(now);
459                    }
460                } else {
461                    ps.makeDead();
462                    uids.removeAt(iu);
463                }
464            }
465            if (uids.size() <= 0) {
466                procMap.removeAt(ip);
467            }
468        }
469
470        mStartTime = now;
471        if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
472    }
473
474    private void resetCommon() {
475        mTimePeriodStartClock = System.currentTimeMillis();
476        buildTimePeriodStartClockStr();
477        mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
478        mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis();
479        mTableData.reset();
480        Arrays.fill(mMemFactorDurations, 0);
481        mSysMemUsage.resetTable();
482        mStartTime = 0;
483        mReadError = null;
484        mFlags = 0;
485        evaluateSystemProperties(true);
486    }
487
488    public boolean evaluateSystemProperties(boolean update) {
489        boolean changed = false;
490        String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2",
491                VMRuntime.getRuntime().vmLibrary());
492        if (!Objects.equals(runtime, mRuntime)) {
493            changed = true;
494            if (update) {
495                mRuntime = runtime;
496            }
497        }
498        return changed;
499    }
500
501    private void buildTimePeriodStartClockStr() {
502        mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
503                mTimePeriodStartClock).toString();
504    }
505
506    static final int[] BAD_TABLE = new int[0];
507
508    private void writeCompactedLongArray(Parcel out, long[] array, int num) {
509        for (int i=0; i<num; i++) {
510            long val = array[i];
511            if (val < 0) {
512                Slog.w(TAG, "Time val negative: " + val);
513                val = 0;
514            }
515            if (val <= Integer.MAX_VALUE) {
516                out.writeInt((int)val);
517            } else {
518                int top = ~((int)((val>>32)&0x7fffffff));
519                int bottom = (int)(val&0xfffffff);
520                out.writeInt(top);
521                out.writeInt(bottom);
522            }
523        }
524    }
525
526    private void readCompactedLongArray(Parcel in, int version, long[] array, int num) {
527        if (version <= 10) {
528            in.readLongArray(array);
529            return;
530        }
531        final int alen = array.length;
532        if (num > alen) {
533            throw new RuntimeException("bad array lengths: got " + num + " array is " + alen);
534        }
535        int i;
536        for (i=0; i<num; i++) {
537            int val = in.readInt();
538            if (val >= 0) {
539                array[i] = val;
540            } else {
541                int bottom = in.readInt();
542                array[i] = (((long)~val)<<32) | bottom;
543            }
544        }
545        while (i < alen) {
546            array[i] = 0;
547            i++;
548        }
549    }
550
551    private void writeCommonString(Parcel out, String name) {
552        Integer index = mCommonStringToIndex.get(name);
553        if (index != null) {
554            out.writeInt(index);
555            return;
556        }
557        index = mCommonStringToIndex.size();
558        mCommonStringToIndex.put(name, index);
559        out.writeInt(~index);
560        out.writeString(name);
561    }
562
563    private String readCommonString(Parcel in, int version) {
564        if (version <= 9) {
565            return in.readString();
566        }
567        int index = in.readInt();
568        if (index >= 0) {
569            return mIndexToCommonString.get(index);
570        }
571        index = ~index;
572        String name = in.readString();
573        while (mIndexToCommonString.size() <= index) {
574            mIndexToCommonString.add(null);
575        }
576        mIndexToCommonString.set(index, name);
577        return name;
578    }
579
580    @Override
581    public int describeContents() {
582        return 0;
583    }
584
585    @Override
586    public void writeToParcel(Parcel out, int flags) {
587        writeToParcel(out, SystemClock.uptimeMillis(), flags);
588    }
589
590    /** @hide */
591    public void writeToParcel(Parcel out, long now, int flags) {
592        out.writeInt(MAGIC);
593        out.writeInt(PARCEL_VERSION);
594        out.writeInt(STATE_COUNT);
595        out.writeInt(ADJ_COUNT);
596        out.writeInt(PSS_COUNT);
597        out.writeInt(SYS_MEM_USAGE_COUNT);
598        out.writeInt(SparseMappingTable.ARRAY_SIZE);
599
600        mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.size());
601
602        // First commit all running times.
603        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
604        final int NPROC = procMap.size();
605        for (int ip=0; ip<NPROC; ip++) {
606            SparseArray<ProcessState> uids = procMap.valueAt(ip);
607            final int NUID = uids.size();
608            for (int iu=0; iu<NUID; iu++) {
609                uids.valueAt(iu).commitStateTime(now);
610            }
611        }
612        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
613        final int NPKG = pkgMap.size();
614        for (int ip=0; ip<NPKG; ip++) {
615            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
616            final int NUID = uids.size();
617            for (int iu=0; iu<NUID; iu++) {
618                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
619                final int NVERS = vpkgs.size();
620                for (int iv=0; iv<NVERS; iv++) {
621                    PackageState pkgState = vpkgs.valueAt(iv);
622                    final int NPROCS = pkgState.mProcesses.size();
623                    for (int iproc=0; iproc<NPROCS; iproc++) {
624                        ProcessState proc = pkgState.mProcesses.valueAt(iproc);
625                        if (proc.getCommonProcess() != proc) {
626                            proc.commitStateTime(now);
627                        }
628                    }
629                    final int NSRVS = pkgState.mServices.size();
630                    for (int isvc=0; isvc<NSRVS; isvc++) {
631                        pkgState.mServices.valueAt(isvc).commitStateTime(now);
632                    }
633                }
634            }
635        }
636
637        out.writeLong(mTimePeriodStartClock);
638        out.writeLong(mTimePeriodStartRealtime);
639        out.writeLong(mTimePeriodEndRealtime);
640        out.writeLong(mTimePeriodStartUptime);
641        out.writeLong(mTimePeriodEndUptime);
642        out.writeString(mRuntime);
643        out.writeInt(mFlags);
644
645        mTableData.writeToParcel(out);
646
647        if (mMemFactor != STATE_NOTHING) {
648            mMemFactorDurations[mMemFactor] += now - mStartTime;
649            mStartTime = now;
650        }
651        writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length);
652
653        mSysMemUsage.writeToParcel(out);
654
655        out.writeInt(NPROC);
656        for (int ip=0; ip<NPROC; ip++) {
657            writeCommonString(out, procMap.keyAt(ip));
658            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
659            final int NUID = uids.size();
660            out.writeInt(NUID);
661            for (int iu=0; iu<NUID; iu++) {
662                out.writeInt(uids.keyAt(iu));
663                final ProcessState proc = uids.valueAt(iu);
664                writeCommonString(out, proc.getPackage());
665                out.writeInt(proc.getVersion());
666                proc.writeToParcel(out, now);
667            }
668        }
669        out.writeInt(NPKG);
670        for (int ip=0; ip<NPKG; ip++) {
671            writeCommonString(out, pkgMap.keyAt(ip));
672            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
673            final int NUID = uids.size();
674            out.writeInt(NUID);
675            for (int iu=0; iu<NUID; iu++) {
676                out.writeInt(uids.keyAt(iu));
677                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
678                final int NVERS = vpkgs.size();
679                out.writeInt(NVERS);
680                for (int iv=0; iv<NVERS; iv++) {
681                    out.writeInt(vpkgs.keyAt(iv));
682                    final PackageState pkgState = vpkgs.valueAt(iv);
683                    final int NPROCS = pkgState.mProcesses.size();
684                    out.writeInt(NPROCS);
685                    for (int iproc=0; iproc<NPROCS; iproc++) {
686                        writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
687                        final ProcessState proc = pkgState.mProcesses.valueAt(iproc);
688                        if (proc.getCommonProcess() == proc) {
689                            // This is the same as the common process we wrote above.
690                            out.writeInt(0);
691                        } else {
692                            // There is separate data for this package's process.
693                            out.writeInt(1);
694                            proc.writeToParcel(out, now);
695                        }
696                    }
697                    final int NSRVS = pkgState.mServices.size();
698                    out.writeInt(NSRVS);
699                    for (int isvc=0; isvc<NSRVS; isvc++) {
700                        out.writeString(pkgState.mServices.keyAt(isvc));
701                        final ServiceState svc = pkgState.mServices.valueAt(isvc);
702                        writeCommonString(out, svc.getProcessName());
703                        svc.writeToParcel(out, now);
704                    }
705                }
706            }
707        }
708
709        mCommonStringToIndex = null;
710    }
711
712    private boolean readCheckedInt(Parcel in, int val, String what) {
713        int got;
714        if ((got=in.readInt()) != val) {
715            mReadError = "bad " + what + ": " + got;
716            return false;
717        }
718        return true;
719    }
720
721    static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
722        int pos = 0;
723        final int initialAvail = stream.available();
724        byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
725        while (true) {
726            int amt = stream.read(data, pos, data.length-pos);
727            if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
728                    + " of avail " + data.length);
729            if (amt < 0) {
730                if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
731                        + " len=" + data.length);
732                outLen[0] = pos;
733                return data;
734            }
735            pos += amt;
736            if (pos >= data.length) {
737                byte[] newData = new byte[pos+16384];
738                if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
739                        + newData.length);
740                System.arraycopy(data, 0, newData, 0, pos);
741                data = newData;
742            }
743        }
744    }
745
746    public void read(InputStream stream) {
747        try {
748            int[] len = new int[1];
749            byte[] raw = readFully(stream, len);
750            Parcel in = Parcel.obtain();
751            in.unmarshall(raw, 0, len[0]);
752            in.setDataPosition(0);
753            stream.close();
754
755            readFromParcel(in);
756        } catch (IOException e) {
757            mReadError = "caught exception: " + e;
758        }
759    }
760
761    public void readFromParcel(Parcel in) {
762        final boolean hadData = mPackages.getMap().size() > 0
763                || mProcesses.getMap().size() > 0;
764        if (hadData) {
765            resetSafely();
766        }
767
768        if (!readCheckedInt(in, MAGIC, "magic number")) {
769            return;
770        }
771        int version = in.readInt();
772        if (version != PARCEL_VERSION) {
773            mReadError = "bad version: " + version;
774            return;
775        }
776        if (!readCheckedInt(in, STATE_COUNT, "state count")) {
777            return;
778        }
779        if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
780            return;
781        }
782        if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
783            return;
784        }
785        if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) {
786            return;
787        }
788        if (!readCheckedInt(in, SparseMappingTable.ARRAY_SIZE, "longs size")) {
789            return;
790        }
791
792        mIndexToCommonString = new ArrayList<String>();
793
794        mTimePeriodStartClock = in.readLong();
795        buildTimePeriodStartClockStr();
796        mTimePeriodStartRealtime = in.readLong();
797        mTimePeriodEndRealtime = in.readLong();
798        mTimePeriodStartUptime = in.readLong();
799        mTimePeriodEndUptime = in.readLong();
800        mRuntime = in.readString();
801        mFlags = in.readInt();
802        mTableData.readFromParcel(in);
803        readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length);
804        if (!mSysMemUsage.readFromParcel(in)) {
805            return;
806        }
807
808        int NPROC = in.readInt();
809        if (NPROC < 0) {
810            mReadError = "bad process count: " + NPROC;
811            return;
812        }
813        while (NPROC > 0) {
814            NPROC--;
815            final String procName = readCommonString(in, version);
816            if (procName == null) {
817                mReadError = "bad process name";
818                return;
819            }
820            int NUID = in.readInt();
821            if (NUID < 0) {
822                mReadError = "bad uid count: " + NUID;
823                return;
824            }
825            while (NUID > 0) {
826                NUID--;
827                final int uid = in.readInt();
828                if (uid < 0) {
829                    mReadError = "bad uid: " + uid;
830                    return;
831                }
832                final String pkgName = readCommonString(in, version);
833                if (pkgName == null) {
834                    mReadError = "bad process package name";
835                    return;
836                }
837                final int vers = in.readInt();
838                ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
839                if (proc != null) {
840                    if (!proc.readFromParcel(in, false)) {
841                        return;
842                    }
843                } else {
844                    proc = new ProcessState(this, pkgName, uid, vers, procName);
845                    if (!proc.readFromParcel(in, true)) {
846                        return;
847                    }
848                }
849                if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
850                        + " " + proc);
851                mProcesses.put(procName, uid, proc);
852            }
853        }
854
855        if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
856
857        int NPKG = in.readInt();
858        if (NPKG < 0) {
859            mReadError = "bad package count: " + NPKG;
860            return;
861        }
862        while (NPKG > 0) {
863            NPKG--;
864            final String pkgName = readCommonString(in, version);
865            if (pkgName == null) {
866                mReadError = "bad package name";
867                return;
868            }
869            int NUID = in.readInt();
870            if (NUID < 0) {
871                mReadError = "bad uid count: " + NUID;
872                return;
873            }
874            while (NUID > 0) {
875                NUID--;
876                final int uid = in.readInt();
877                if (uid < 0) {
878                    mReadError = "bad uid: " + uid;
879                    return;
880                }
881                int NVERS = in.readInt();
882                if (NVERS < 0) {
883                    mReadError = "bad versions count: " + NVERS;
884                    return;
885                }
886                while (NVERS > 0) {
887                    NVERS--;
888                    final int vers = in.readInt();
889                    PackageState pkgState = new PackageState(pkgName, uid);
890                    SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid);
891                    if (vpkg == null) {
892                        vpkg = new SparseArray<PackageState>();
893                        mPackages.put(pkgName, uid, vpkg);
894                    }
895                    vpkg.put(vers, pkgState);
896                    int NPROCS = in.readInt();
897                    if (NPROCS < 0) {
898                        mReadError = "bad package process count: " + NPROCS;
899                        return;
900                    }
901                    while (NPROCS > 0) {
902                        NPROCS--;
903                        String procName = readCommonString(in, version);
904                        if (procName == null) {
905                            mReadError = "bad package process name";
906                            return;
907                        }
908                        int hasProc = in.readInt();
909                        if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
910                                + " process " + procName + " hasProc=" + hasProc);
911                        ProcessState commonProc = mProcesses.get(procName, uid);
912                        if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
913                                + ": " + commonProc);
914                        if (commonProc == null) {
915                            mReadError = "no common proc: " + procName;
916                            return;
917                        }
918                        if (hasProc != 0) {
919                            // The process for this package is unique to the package; we
920                            // need to load it.  We don't need to do anything about it if
921                            // it is not unique because if someone later looks for it
922                            // they will find and use it from the global procs.
923                            ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
924                            if (proc != null) {
925                                if (!proc.readFromParcel(in, false)) {
926                                    return;
927                                }
928                            } else {
929                                proc = new ProcessState(commonProc, pkgName, uid, vers, procName,
930                                        0);
931                                if (!proc.readFromParcel(in, true)) {
932                                    return;
933                                }
934                            }
935                            if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
936                                    + procName + " " + uid + " " + proc);
937                            pkgState.mProcesses.put(procName, proc);
938                        } else {
939                            if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
940                                    + procName + " " + uid + " " + commonProc);
941                            pkgState.mProcesses.put(procName, commonProc);
942                        }
943                    }
944                    int NSRVS = in.readInt();
945                    if (NSRVS < 0) {
946                        mReadError = "bad package service count: " + NSRVS;
947                        return;
948                    }
949                    while (NSRVS > 0) {
950                        NSRVS--;
951                        String serviceName = in.readString();
952                        if (serviceName == null) {
953                            mReadError = "bad package service name";
954                            return;
955                        }
956                        String processName = version > 9 ? readCommonString(in, version) : null;
957                        ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
958                        if (serv == null) {
959                            serv = new ServiceState(this, pkgName, serviceName, processName, null);
960                        }
961                        if (!serv.readFromParcel(in)) {
962                            return;
963                        }
964                        if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
965                                + serviceName + " " + uid + " " + serv);
966                        pkgState.mServices.put(serviceName, serv);
967                    }
968                }
969            }
970        }
971
972        mIndexToCommonString = null;
973
974        if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
975    }
976
977    public PackageState getPackageStateLocked(String packageName, int uid, int vers) {
978        SparseArray<PackageState> vpkg = mPackages.get(packageName, uid);
979        if (vpkg == null) {
980            vpkg = new SparseArray<PackageState>();
981            mPackages.put(packageName, uid, vpkg);
982        }
983        PackageState as = vpkg.get(vers);
984        if (as != null) {
985            return as;
986        }
987        as = new PackageState(packageName, uid);
988        vpkg.put(vers, as);
989        return as;
990    }
991
992    public ProcessState getProcessStateLocked(String packageName, int uid, int vers,
993            String processName) {
994        final PackageState pkgState = getPackageStateLocked(packageName, uid, vers);
995        ProcessState ps = pkgState.mProcesses.get(processName);
996        if (ps != null) {
997            return ps;
998        }
999        ProcessState commonProc = mProcesses.get(processName, uid);
1000        if (commonProc == null) {
1001            commonProc = new ProcessState(this, packageName, uid, vers, processName);
1002            mProcesses.put(processName, uid, commonProc);
1003            if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
1004        }
1005        if (!commonProc.isMultiPackage()) {
1006            if (packageName.equals(commonProc.getPackage()) && vers == commonProc.getVersion()) {
1007                // This common process is not in use by multiple packages, and
1008                // is for the calling package, so we can just use it directly.
1009                ps = commonProc;
1010                if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
1011            } else {
1012                if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
1013                // This common process has not been in use by multiple packages,
1014                // but it was created for a different package than the caller.
1015                // We need to convert it to a multi-package process.
1016                commonProc.setMultiPackage(true);
1017                // To do this, we need to make two new process states, one a copy
1018                // of the current state for the process under the original package
1019                // name, and the second a free new process state for it as the
1020                // new package name.
1021                long now = SystemClock.uptimeMillis();
1022                // First let's make a copy of the current process state and put
1023                // that under the now unique state for its original package name.
1024                final PackageState commonPkgState = getPackageStateLocked(commonProc.getPackage(),
1025                        uid, commonProc.getVersion());
1026                if (commonPkgState != null) {
1027                    ProcessState cloned = commonProc.clone(now);
1028                    if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.getPackage()
1029                            + ": " + cloned);
1030                    commonPkgState.mProcesses.put(commonProc.getName(), cloned);
1031                    // If this has active services, we need to update their process pointer
1032                    // to point to the new package-specific process state.
1033                    for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
1034                        ServiceState ss = commonPkgState.mServices.valueAt(i);
1035                        if (ss.getProcess() == commonProc) {
1036                            if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: " + ss);
1037                            ss.setProcess(cloned);
1038                        } else if (DEBUG) {
1039                            Slog.d(TAG, "GETPROC leaving proc of " + ss);
1040                        }
1041                    }
1042                } else {
1043                    Slog.w(TAG, "Cloning proc state: no package state " + commonProc.getPackage()
1044                            + "/" + uid + " for proc " + commonProc.getName());
1045                }
1046                // And now make a fresh new process state for the new package name.
1047                ps = new ProcessState(commonProc, packageName, uid, vers, processName, now);
1048                if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
1049            }
1050        } else {
1051            // The common process is for multiple packages, we need to create a
1052            // separate object for the per-package data.
1053            ps = new ProcessState(commonProc, packageName, uid, vers, processName,
1054                    SystemClock.uptimeMillis());
1055            if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
1056        }
1057        pkgState.mProcesses.put(processName, ps);
1058        if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
1059        return ps;
1060    }
1061
1062    public ServiceState getServiceStateLocked(String packageName, int uid, int vers,
1063            String processName, String className) {
1064        final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers);
1065        ServiceState ss = as.mServices.get(className);
1066        if (ss != null) {
1067            if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
1068            return ss;
1069        }
1070        final ProcessState ps = processName != null
1071                ? getProcessStateLocked(packageName, uid, vers, processName) : null;
1072        ss = new ServiceState(this, packageName, className, processName, ps);
1073        as.mServices.put(className, ss);
1074        if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
1075        return ss;
1076    }
1077
1078    public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
1079            boolean dumpAll, boolean activeOnly) {
1080        long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
1081                mStartTime, now);
1082        boolean sepNeeded = false;
1083        if (mSysMemUsage.getKeyCount() > 0) {
1084            pw.println("System memory usage:");
1085            mSysMemUsage.dump(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
1086            sepNeeded = true;
1087        }
1088        ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
1089        boolean printedHeader = false;
1090        for (int ip=0; ip<pkgMap.size(); ip++) {
1091            final String pkgName = pkgMap.keyAt(ip);
1092            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
1093            for (int iu=0; iu<uids.size(); iu++) {
1094                final int uid = uids.keyAt(iu);
1095                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
1096                for (int iv=0; iv<vpkgs.size(); iv++) {
1097                    final int vers = vpkgs.keyAt(iv);
1098                    final PackageState pkgState = vpkgs.valueAt(iv);
1099                    final int NPROCS = pkgState.mProcesses.size();
1100                    final int NSRVS = pkgState.mServices.size();
1101                    final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
1102                    if (!pkgMatch) {
1103                        boolean procMatch = false;
1104                        for (int iproc=0; iproc<NPROCS; iproc++) {
1105                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1106                            if (reqPackage.equals(proc.getName())) {
1107                                procMatch = true;
1108                                break;
1109                            }
1110                        }
1111                        if (!procMatch) {
1112                            continue;
1113                        }
1114                    }
1115                    if (NPROCS > 0 || NSRVS > 0) {
1116                        if (!printedHeader) {
1117                            if (sepNeeded) pw.println();
1118                            pw.println("Per-Package Stats:");
1119                            printedHeader = true;
1120                            sepNeeded = true;
1121                        }
1122                        pw.print("  * "); pw.print(pkgName); pw.print(" / ");
1123                                UserHandle.formatUid(pw, uid); pw.print(" / v");
1124                                pw.print(vers); pw.println(":");
1125                    }
1126                    if (!dumpSummary || dumpAll) {
1127                        for (int iproc=0; iproc<NPROCS; iproc++) {
1128                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1129                            if (!pkgMatch && !reqPackage.equals(proc.getName())) {
1130                                continue;
1131                            }
1132                            if (activeOnly && !proc.isInUse()) {
1133                                pw.print("      (Not active: ");
1134                                        pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
1135                                continue;
1136                            }
1137                            pw.print("      Process ");
1138                            pw.print(pkgState.mProcesses.keyAt(iproc));
1139                            if (proc.getCommonProcess().isMultiPackage()) {
1140                                pw.print(" (multi, ");
1141                            } else {
1142                                pw.print(" (unique, ");
1143                            }
1144                            pw.print(proc.getDurationsBucketCount());
1145                            pw.print(" entries)");
1146                            pw.println(":");
1147                            proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1148                                    ALL_PROC_STATES, now);
1149                            proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1150                                    ALL_PROC_STATES);
1151                            proc.dumpInternalLocked(pw, "        ", dumpAll);
1152                        }
1153                    } else {
1154                        ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
1155                        for (int iproc=0; iproc<NPROCS; iproc++) {
1156                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1157                            if (!pkgMatch && !reqPackage.equals(proc.getName())) {
1158                                continue;
1159                            }
1160                            if (activeOnly && !proc.isInUse()) {
1161                                continue;
1162                            }
1163                            procs.add(proc);
1164                        }
1165                        DumpUtils.dumpProcessSummaryLocked(pw, "      ", procs,
1166                                ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES,
1167                                now, totalTime);
1168                    }
1169                    for (int isvc=0; isvc<NSRVS; isvc++) {
1170                        ServiceState svc = pkgState.mServices.valueAt(isvc);
1171                        if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) {
1172                            continue;
1173                        }
1174                        if (activeOnly && !svc.isInUse()) {
1175                            pw.print("      (Not active: ");
1176                                    pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
1177                            continue;
1178                        }
1179                        if (dumpAll) {
1180                            pw.print("      Service ");
1181                        } else {
1182                            pw.print("      * ");
1183                        }
1184                        pw.print(pkgState.mServices.keyAt(isvc));
1185                        pw.println(":");
1186                        pw.print("        Process: "); pw.println(svc.getProcessName());
1187                        svc.dumpStats(pw, "        ", "          ", "    ",
1188                                now, totalTime, dumpSummary, dumpAll);
1189                    }
1190                }
1191            }
1192        }
1193
1194        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1195        printedHeader = false;
1196        int numShownProcs = 0, numTotalProcs = 0;
1197        for (int ip=0; ip<procMap.size(); ip++) {
1198            String procName = procMap.keyAt(ip);
1199            SparseArray<ProcessState> uids = procMap.valueAt(ip);
1200            for (int iu=0; iu<uids.size(); iu++) {
1201                int uid = uids.keyAt(iu);
1202                numTotalProcs++;
1203                final ProcessState proc = uids.valueAt(iu);
1204                if (proc.hasAnyData()) {
1205                    continue;
1206                }
1207                if (!proc.isMultiPackage()) {
1208                    continue;
1209                }
1210                if (reqPackage != null && !reqPackage.equals(procName)
1211                        && !reqPackage.equals(proc.getPackage())) {
1212                    continue;
1213                }
1214                numShownProcs++;
1215                if (sepNeeded) {
1216                    pw.println();
1217                }
1218                sepNeeded = true;
1219                if (!printedHeader) {
1220                    pw.println("Multi-Package Common Processes:");
1221                    printedHeader = true;
1222                }
1223                if (activeOnly && !proc.isInUse()) {
1224                    pw.print("      (Not active: "); pw.print(procName); pw.println(")");
1225                    continue;
1226                }
1227                pw.print("  * "); pw.print(procName); pw.print(" / ");
1228                        UserHandle.formatUid(pw, uid);
1229                        pw.print(" ("); pw.print(proc.getDurationsBucketCount());
1230                        pw.print(" entries)"); pw.println(":");
1231                proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1232                        ALL_PROC_STATES, now);
1233                proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES);
1234                proc.dumpInternalLocked(pw, "        ", dumpAll);
1235            }
1236        }
1237        if (dumpAll) {
1238            pw.println();
1239            pw.print("  Total procs: "); pw.print(numShownProcs);
1240                    pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
1241        }
1242
1243        if (sepNeeded) {
1244            pw.println();
1245        }
1246        if (dumpSummary) {
1247            pw.println("Summary:");
1248            dumpSummaryLocked(pw, reqPackage, now, activeOnly);
1249        } else {
1250            dumpTotalsLocked(pw, now);
1251        }
1252
1253        if (dumpAll) {
1254            pw.println();
1255            pw.println("Internal state:");
1256            /*
1257            pw.print("  Num long arrays: "); pw.println(mLongs.size());
1258            pw.print("  Next long entry: "); pw.println(mNextLong);
1259            */
1260            pw.print("  mRunning="); pw.println(mRunning);
1261        }
1262    }
1263
1264    public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
1265        long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
1266                mStartTime, now);
1267        dumpFilteredSummaryLocked(pw, null, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1268                ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
1269        pw.println();
1270        dumpTotalsLocked(pw, now);
1271    }
1272
1273    long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight,
1274            long totalTime, long curTotalMem, int samples) {
1275        if (memWeight != 0) {
1276            long mem = (long)(memWeight * 1024 / totalTime);
1277            pw.print(prefix);
1278            pw.print(label);
1279            pw.print(": ");
1280            DebugUtils.printSizeValue(pw, mem);
1281            pw.print(" (");
1282            pw.print(samples);
1283            pw.print(" samples)");
1284            pw.println();
1285            return curTotalMem + mem;
1286        }
1287        return curTotalMem;
1288    }
1289
1290    void dumpTotalsLocked(PrintWriter pw, long now) {
1291        pw.println("Run time Stats:");
1292        DumpUtils.dumpSingleTime(pw, "  ", mMemFactorDurations, mMemFactor, mStartTime, now);
1293        pw.println();
1294        pw.println("Memory usage:");
1295        TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
1296                ALL_MEM_ADJ);
1297        computeTotalMemoryUse(totalMem, now);
1298        long totalPss = 0;
1299        totalPss = printMemoryCategory(pw, "  ", "Kernel ", totalMem.sysMemKernelWeight,
1300                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1301        totalPss = printMemoryCategory(pw, "  ", "Native ", totalMem.sysMemNativeWeight,
1302                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1303        for (int i=0; i<STATE_COUNT; i++) {
1304            // Skip restarting service state -- that is not actually a running process.
1305            if (i != STATE_SERVICE_RESTARTING) {
1306                totalPss = printMemoryCategory(pw, "  ", DumpUtils.STATE_NAMES[i],
1307                        totalMem.processStateWeight[i], totalMem.totalTime, totalPss,
1308                        totalMem.processStateSamples[i]);
1309            }
1310        }
1311        totalPss = printMemoryCategory(pw, "  ", "Cached ", totalMem.sysMemCachedWeight,
1312                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1313        totalPss = printMemoryCategory(pw, "  ", "Free   ", totalMem.sysMemFreeWeight,
1314                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1315        totalPss = printMemoryCategory(pw, "  ", "Z-Ram  ", totalMem.sysMemZRamWeight,
1316                totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1317        pw.print("  TOTAL  : ");
1318        DebugUtils.printSizeValue(pw, totalPss);
1319        pw.println();
1320        printMemoryCategory(pw, "  ", DumpUtils.STATE_NAMES[STATE_SERVICE_RESTARTING],
1321                totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss,
1322                totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
1323        pw.println();
1324        pw.print("          Start time: ");
1325        pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
1326        pw.println();
1327        pw.print("  Total elapsed time: ");
1328        TimeUtils.formatDuration(
1329                (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
1330                        - mTimePeriodStartRealtime, pw);
1331        boolean partial = true;
1332        if ((mFlags&FLAG_SHUTDOWN) != 0) {
1333            pw.print(" (shutdown)");
1334            partial = false;
1335        }
1336        if ((mFlags&FLAG_SYSPROPS) != 0) {
1337            pw.print(" (sysprops)");
1338            partial = false;
1339        }
1340        if ((mFlags&FLAG_COMPLETE) != 0) {
1341            pw.print(" (complete)");
1342            partial = false;
1343        }
1344        if (partial) {
1345            pw.print(" (partial)");
1346        }
1347        pw.print(' ');
1348        pw.print(mRuntime);
1349        pw.println();
1350    }
1351
1352    void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
1353            int[] screenStates, int[] memStates, int[] procStates,
1354            int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
1355        ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
1356                procStates, sortProcStates, now, reqPackage, activeOnly);
1357        if (procs.size() > 0) {
1358            if (header != null) {
1359                pw.println();
1360                pw.println(header);
1361            }
1362            DumpUtils.dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
1363                    sortProcStates, now, totalTime);
1364        }
1365    }
1366
1367    public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
1368            int[] procStates, int sortProcStates[], long now, String reqPackage,
1369            boolean activeOnly) {
1370        final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
1371        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
1372        for (int ip=0; ip<pkgMap.size(); ip++) {
1373            final String pkgName = pkgMap.keyAt(ip);
1374            final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip);
1375            for (int iu=0; iu<procs.size(); iu++) {
1376                final SparseArray<PackageState> vpkgs = procs.valueAt(iu);
1377                final int NVERS = vpkgs.size();
1378                for (int iv=0; iv<NVERS; iv++) {
1379                    final PackageState state = vpkgs.valueAt(iv);
1380                    final int NPROCS = state.mProcesses.size();
1381                    final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
1382                    for (int iproc=0; iproc<NPROCS; iproc++) {
1383                        final ProcessState proc = state.mProcesses.valueAt(iproc);
1384                        if (!pkgMatch && !reqPackage.equals(proc.getName())) {
1385                            continue;
1386                        }
1387                        if (activeOnly && !proc.isInUse()) {
1388                            continue;
1389                        }
1390                        foundProcs.add(proc.getCommonProcess());
1391                    }
1392                }
1393            }
1394        }
1395        ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
1396        for (int i=0; i<foundProcs.size(); i++) {
1397            ProcessState proc = foundProcs.valueAt(i);
1398            if (proc.computeProcessTimeLocked(screenStates, memStates, procStates, now) > 0) {
1399                outProcs.add(proc);
1400                if (procStates != sortProcStates) {
1401                    proc.computeProcessTimeLocked(screenStates, memStates, sortProcStates, now);
1402                }
1403            }
1404        }
1405        Collections.sort(outProcs, ProcessState.COMPARATOR);
1406        return outProcs;
1407    }
1408
1409    public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
1410        final long now = SystemClock.uptimeMillis();
1411        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
1412        pw.println("vers,5");
1413        pw.print("period,"); pw.print(mTimePeriodStartClockStr);
1414        pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
1415        pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
1416        boolean partial = true;
1417        if ((mFlags&FLAG_SHUTDOWN) != 0) {
1418            pw.print(",shutdown");
1419            partial = false;
1420        }
1421        if ((mFlags&FLAG_SYSPROPS) != 0) {
1422            pw.print(",sysprops");
1423            partial = false;
1424        }
1425        if ((mFlags&FLAG_COMPLETE) != 0) {
1426            pw.print(",complete");
1427            partial = false;
1428        }
1429        if (partial) {
1430            pw.print(",partial");
1431        }
1432        pw.println();
1433        pw.print("config,"); pw.println(mRuntime);
1434        for (int ip=0; ip<pkgMap.size(); ip++) {
1435            final String pkgName = pkgMap.keyAt(ip);
1436            if (reqPackage != null && !reqPackage.equals(pkgName)) {
1437                continue;
1438            }
1439            final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
1440            for (int iu=0; iu<uids.size(); iu++) {
1441                final int uid = uids.keyAt(iu);
1442                final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
1443                for (int iv=0; iv<vpkgs.size(); iv++) {
1444                    final int vers = vpkgs.keyAt(iv);
1445                    final PackageState pkgState = vpkgs.valueAt(iv);
1446                    final int NPROCS = pkgState.mProcesses.size();
1447                    final int NSRVS = pkgState.mServices.size();
1448                    for (int iproc=0; iproc<NPROCS; iproc++) {
1449                        ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1450                        proc.dumpPackageProcCheckin(pw, pkgName, uid, vers,
1451                                pkgState.mProcesses.keyAt(iproc), now);
1452                    }
1453                    for (int isvc=0; isvc<NSRVS; isvc++) {
1454                        final String serviceName = DumpUtils.collapseString(pkgName,
1455                                pkgState.mServices.keyAt(isvc));
1456                        final ServiceState svc = pkgState.mServices.valueAt(isvc);
1457                        svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now);
1458                    }
1459                }
1460            }
1461        }
1462
1463        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1464        for (int ip=0; ip<procMap.size(); ip++) {
1465            String procName = procMap.keyAt(ip);
1466            SparseArray<ProcessState> uids = procMap.valueAt(ip);
1467            for (int iu=0; iu<uids.size(); iu++) {
1468                final int uid = uids.keyAt(iu);
1469                final ProcessState procState = uids.valueAt(iu);
1470                procState.dumpProcCheckin(pw, procName, uid, now);
1471            }
1472        }
1473        pw.print("total");
1474        DumpUtils.dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor, mStartTime, now);
1475        pw.println();
1476        final int sysMemUsageCount = mSysMemUsage.getKeyCount();
1477        if (sysMemUsageCount > 0) {
1478            pw.print("sysmemusage");
1479            for (int i=0; i<sysMemUsageCount; i++) {
1480                final int key = mSysMemUsage.getKeyAt(i);
1481                final int type = SparseMappingTable.getIdFromKey(key);
1482                pw.print(",");
1483                DumpUtils.printProcStateTag(pw, type);
1484                for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) {
1485                    if (j > SYS_MEM_USAGE_CACHED_MINIMUM) {
1486                        pw.print(":");
1487                    }
1488                    pw.print(mSysMemUsage.getValue(key, j));
1489                }
1490            }
1491        }
1492        pw.println();
1493        TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
1494                ALL_MEM_ADJ);
1495        computeTotalMemoryUse(totalMem, now);
1496        pw.print("weights,");
1497        pw.print(totalMem.totalTime);
1498        pw.print(",");
1499        pw.print(totalMem.sysMemCachedWeight);
1500        pw.print(":");
1501        pw.print(totalMem.sysMemSamples);
1502        pw.print(",");
1503        pw.print(totalMem.sysMemFreeWeight);
1504        pw.print(":");
1505        pw.print(totalMem.sysMemSamples);
1506        pw.print(",");
1507        pw.print(totalMem.sysMemZRamWeight);
1508        pw.print(":");
1509        pw.print(totalMem.sysMemSamples);
1510        pw.print(",");
1511        pw.print(totalMem.sysMemKernelWeight);
1512        pw.print(":");
1513        pw.print(totalMem.sysMemSamples);
1514        pw.print(",");
1515        pw.print(totalMem.sysMemNativeWeight);
1516        pw.print(":");
1517        pw.print(totalMem.sysMemSamples);
1518        for (int i=0; i<STATE_COUNT; i++) {
1519            pw.print(",");
1520            pw.print(totalMem.processStateWeight[i]);
1521            pw.print(":");
1522            pw.print(totalMem.processStateSamples[i]);
1523        }
1524        pw.println();
1525    }
1526
1527
1528    final public static class ProcessStateHolder {
1529        public final int appVersion;
1530        public ProcessState state;
1531
1532        public ProcessStateHolder(int _appVersion) {
1533            appVersion = _appVersion;
1534        }
1535    }
1536
1537    public static final class PackageState {
1538        public final ArrayMap<String, ProcessState> mProcesses
1539                = new ArrayMap<String, ProcessState>();
1540        public final ArrayMap<String, ServiceState> mServices
1541                = new ArrayMap<String, ServiceState>();
1542        public final String mPackageName;
1543        public final int mUid;
1544
1545        public PackageState(String packageName, int uid) {
1546            mUid = uid;
1547            mPackageName = packageName;
1548        }
1549    }
1550
1551    public static final class ProcessDataCollection {
1552        final int[] screenStates;
1553        final int[] memStates;
1554        final int[] procStates;
1555
1556        public long totalTime;
1557        public long numPss;
1558        public long minPss;
1559        public long avgPss;
1560        public long maxPss;
1561        public long minUss;
1562        public long avgUss;
1563        public long maxUss;
1564
1565        public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
1566            screenStates = _screenStates;
1567            memStates = _memStates;
1568            procStates = _procStates;
1569        }
1570
1571        void print(PrintWriter pw, long overallTime, boolean full) {
1572            if (totalTime > overallTime) {
1573                pw.print("*");
1574            }
1575            DumpUtils.printPercent(pw, (double) totalTime / (double) overallTime);
1576            if (numPss > 0) {
1577                pw.print(" (");
1578                DebugUtils.printSizeValue(pw, minPss * 1024);
1579                pw.print("-");
1580                DebugUtils.printSizeValue(pw, avgPss * 1024);
1581                pw.print("-");
1582                DebugUtils.printSizeValue(pw, maxPss * 1024);
1583                pw.print("/");
1584                DebugUtils.printSizeValue(pw, minUss * 1024);
1585                pw.print("-");
1586                DebugUtils.printSizeValue(pw, avgUss * 1024);
1587                pw.print("-");
1588                DebugUtils.printSizeValue(pw, maxUss * 1024);
1589                if (full) {
1590                    pw.print(" over ");
1591                    pw.print(numPss);
1592                }
1593                pw.print(")");
1594            }
1595        }
1596    }
1597
1598    public static class TotalMemoryUseCollection {
1599        final int[] screenStates;
1600        final int[] memStates;
1601
1602        public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) {
1603            screenStates = _screenStates;
1604            memStates = _memStates;
1605        }
1606
1607        public long totalTime;
1608        public long[] processStatePss = new long[STATE_COUNT];
1609        public double[] processStateWeight = new double[STATE_COUNT];
1610        public long[] processStateTime = new long[STATE_COUNT];
1611        public int[] processStateSamples = new int[STATE_COUNT];
1612        public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT];
1613        public double sysMemCachedWeight;
1614        public double sysMemFreeWeight;
1615        public double sysMemZRamWeight;
1616        public double sysMemKernelWeight;
1617        public double sysMemNativeWeight;
1618        public int sysMemSamples;
1619    }
1620
1621}
1622