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