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