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