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