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