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 
17 package com.android.internal.app.procstats;
18 
19 import android.os.Debug;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.os.SystemClock;
23 import android.os.SystemProperties;
24 import android.os.UserHandle;
25 import android.text.format.DateFormat;
26 import android.util.ArrayMap;
27 import android.util.ArraySet;
28 import android.util.DebugUtils;
29 import android.util.Log;
30 import android.util.Slog;
31 import android.util.SparseArray;
32 import android.util.TimeUtils;
33 
34 import com.android.internal.app.ProcessMap;
35 import com.android.internal.app.procstats.DurationsTable;
36 import com.android.internal.app.procstats.ProcessState;
37 import com.android.internal.app.procstats.PssTable;
38 import com.android.internal.app.procstats.ServiceState;
39 import com.android.internal.app.procstats.SparseMappingTable;
40 import com.android.internal.app.procstats.SysMemUsageTable;
41 import com.android.internal.app.procstats.DumpUtils.*;
42 
43 import dalvik.system.VMRuntime;
44 import libcore.util.EmptyArray;
45 
46 import java.io.BufferedReader;
47 import java.io.FileReader;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.PrintWriter;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.Comparator;
55 import java.util.Objects;
56 import java.util.regex.Pattern;
57 import java.util.regex.Matcher;
58 
59 public 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 
ProcessStats(boolean running)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 
ProcessStats(Parcel in)213     public ProcessStats(Parcel in) {
214         reset();
215         readFromParcel(in);
216     }
217 
add(ProcessStats other)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 
addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem, long nativeMem)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 
computeTotalMemoryUse(TotalMemoryUseCollection data, long now)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 
reset()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 
resetSafely()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 
resetCommon()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 
evaluateSystemProperties(boolean update)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 
buildTimePeriodStartClockStr()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      */
updateFragmentation()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      */
splitAndParseNumbers(String s)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 
writeCompactedLongArray(Parcel out, long[] array, int num)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 
readCompactedLongArray(Parcel in, int version, long[] array, int num)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 
writeCommonString(Parcel out, String name)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 
readCommonString(Parcel in, int version)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
describeContents()697     public int describeContents() {
698         return 0;
699     }
700 
701     @Override
writeToParcel(Parcel out, int flags)702     public void writeToParcel(Parcel out, int flags) {
703         writeToParcel(out, SystemClock.uptimeMillis(), flags);
704     }
705 
706     /** @hide */
writeToParcel(Parcel out, long now, int flags)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 
readCheckedInt(Parcel in, int val, String what)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 
readFully(InputStream stream, int[] outLen)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 
read(InputStream stream)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 
readFromParcel(Parcel in)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 
getPackageStateLocked(String packageName, int uid, int vers)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 
getProcessStateLocked(String packageName, int uid, int vers, String processName)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 
getServiceStateLocked(String packageName, int uid, int vers, String processName, String className)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 
dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, boolean dumpAll, boolean activeOnly)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 
dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly)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 
dumpFragmentationLocked(PrintWriter pw)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 
printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, long totalTime, long curTotalMem, int samples)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 
dumpTotalsLocked(PrintWriter pw, long now)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 
dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, int[] screenStates, int[] memStates, int[] procStates, int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly)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 
collectProcessesLocked(int[] screenStates, int[] memStates, int[] procStates, int sortProcStates[], long now, String reqPackage, boolean activeOnly)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 
dumpCheckinLocked(PrintWriter pw, String reqPackage)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 
ProcessStateHolder(int _appVersion)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 
PackageState(String packageName, int uid)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 
ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates)1747         public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
1748             screenStates = _screenStates;
1749             memStates = _memStates;
1750             procStates = _procStates;
1751         }
1752 
print(PrintWriter pw, long overallTime, boolean full)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 
TotalMemoryUseCollection(int[] _screenStates, int[] _memStates)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