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.content.ComponentName;
20 import android.os.Debug;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 import android.os.SystemClock;
26 import android.os.SystemProperties;
27 import android.os.UserHandle;
28 import android.service.procstats.ProcessStatsAssociationProto;
29 import android.service.procstats.ProcessStatsAvailablePagesProto;
30 import android.service.procstats.ProcessStatsPackageProto;
31 import android.service.procstats.ProcessStatsSectionProto;
32 import android.text.TextUtils;
33 import android.text.format.DateFormat;
34 import android.util.ArrayMap;
35 import android.util.ArraySet;
36 import android.util.DebugUtils;
37 import android.util.LongSparseArray;
38 import android.util.Pair;
39 import android.util.Slog;
40 import android.util.SparseArray;
41 import android.util.TimeUtils;
42 import android.util.proto.ProtoOutputStream;
43 
44 import com.android.internal.app.ProcessMap;
45 import com.android.internal.app.procstats.AssociationState.SourceKey;
46 import com.android.internal.app.procstats.AssociationState.SourceState;
47 
48 import dalvik.system.VMRuntime;
49 
50 import java.io.BufferedReader;
51 import java.io.FileReader;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Collections;
58 import java.util.Comparator;
59 import java.util.Objects;
60 import java.util.regex.Matcher;
61 import java.util.regex.Pattern;
62 
63 public final class ProcessStats implements Parcelable {
64     public static final String TAG = "ProcessStats";
65     static final boolean DEBUG = false;
66     static final boolean DEBUG_PARCEL = false;
67 
68     public static final String SERVICE_NAME = "procstats";
69 
70     // How often the service commits its data, giving the minimum batching
71     // that is done.
72     public static long COMMIT_PERIOD = 3*60*60*1000;  // Commit current stats every 3 hours
73 
74     // Minimum uptime period before committing.  If the COMMIT_PERIOD has elapsed but
75     // the total uptime has not exceeded this amount, then the commit will be held until
76     // it is reached.
77     public static long COMMIT_UPTIME_PERIOD = 60*60*1000;  // Must have at least 1 hour elapsed
78 
79     public static final int STATE_NOTHING = -1;
80     public static final int STATE_PERSISTENT = 0;
81     public static final int STATE_TOP = 1;
82     public static final int STATE_IMPORTANT_FOREGROUND = 2;
83     public static final int STATE_IMPORTANT_BACKGROUND = 3;
84     public static final int STATE_BACKUP = 4;
85     public static final int STATE_SERVICE = 5;
86     public static final int STATE_SERVICE_RESTARTING = 6;
87     public static final int STATE_RECEIVER = 7;
88     public static final int STATE_HEAVY_WEIGHT = 8;
89     public static final int STATE_HOME = 9;
90     public static final int STATE_LAST_ACTIVITY = 10;
91     public static final int STATE_CACHED_ACTIVITY = 11;
92     public static final int STATE_CACHED_ACTIVITY_CLIENT = 12;
93     public static final int STATE_CACHED_EMPTY = 13;
94     public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
95 
96     public static final int PSS_SAMPLE_COUNT = 0;
97     public static final int PSS_MINIMUM = 1;
98     public static final int PSS_AVERAGE = 2;
99     public static final int PSS_MAXIMUM = 3;
100     public static final int PSS_USS_MINIMUM = 4;
101     public static final int PSS_USS_AVERAGE = 5;
102     public static final int PSS_USS_MAXIMUM = 6;
103     public static final int PSS_RSS_MINIMUM = 7;
104     public static final int PSS_RSS_AVERAGE = 8;
105     public static final int PSS_RSS_MAXIMUM = 9;
106     public static final int PSS_COUNT = PSS_RSS_MAXIMUM+1;
107 
108     public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0;
109     public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1;
110     public static final int SYS_MEM_USAGE_CACHED_AVERAGE = 2;
111     public static final int SYS_MEM_USAGE_CACHED_MAXIMUM = 3;
112     public static final int SYS_MEM_USAGE_FREE_MINIMUM = 4;
113     public static final int SYS_MEM_USAGE_FREE_AVERAGE = 5;
114     public static final int SYS_MEM_USAGE_FREE_MAXIMUM = 6;
115     public static final int SYS_MEM_USAGE_ZRAM_MINIMUM = 7;
116     public static final int SYS_MEM_USAGE_ZRAM_AVERAGE = 8;
117     public static final int SYS_MEM_USAGE_ZRAM_MAXIMUM = 9;
118     public static final int SYS_MEM_USAGE_KERNEL_MINIMUM = 10;
119     public static final int SYS_MEM_USAGE_KERNEL_AVERAGE = 11;
120     public static final int SYS_MEM_USAGE_KERNEL_MAXIMUM = 12;
121     public static final int SYS_MEM_USAGE_NATIVE_MINIMUM = 13;
122     public static final int SYS_MEM_USAGE_NATIVE_AVERAGE = 14;
123     public static final int SYS_MEM_USAGE_NATIVE_MAXIMUM = 15;
124     public static final int SYS_MEM_USAGE_COUNT = SYS_MEM_USAGE_NATIVE_MAXIMUM+1;
125 
126     public static final int ADJ_NOTHING = -1;
127     public static final int ADJ_MEM_FACTOR_NORMAL = 0;
128     public static final int ADJ_MEM_FACTOR_MODERATE = 1;
129     public static final int ADJ_MEM_FACTOR_LOW = 2;
130     public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
131     public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
132     public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
133     public static final int ADJ_SCREEN_OFF = 0;
134     public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
135     public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
136 
137     public static final int FLAG_COMPLETE = 1<<0;
138     public static final int FLAG_SHUTDOWN = 1<<1;
139     public static final int FLAG_SYSPROPS = 1<<2;
140 
141     public static final int ADD_PSS_INTERNAL_SINGLE = 0;
142     public static final int ADD_PSS_INTERNAL_ALL_MEM = 1;
143     public static final int ADD_PSS_INTERNAL_ALL_POLL = 2;
144     public static final int ADD_PSS_EXTERNAL = 3;
145     public static final int ADD_PSS_EXTERNAL_SLOW = 4;
146 
147     public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
148             ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
149 
150     public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
151 
152     public static final int[] NON_CACHED_PROC_STATES = new int[] {
153             STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
154             STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
155             STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER, STATE_HEAVY_WEIGHT
156     };
157 
158     public static final int[] BACKGROUND_PROC_STATES = new int[] {
159             STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
160             STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
161     };
162 
163     public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
164             STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
165             STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER,
166             STATE_HEAVY_WEIGHT, STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
167             STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
168     };
169 
170     // Should report process stats.
171     public static final int REPORT_PROC_STATS = 0x01;
172     // Should report package process stats.
173     public static final int REPORT_PKG_PROC_STATS = 0x02;
174     // Should report package service stats.
175     public static final int REPORT_PKG_SVC_STATS = 0x04;
176     // Should report package association stats.
177     public static final int REPORT_PKG_ASC_STATS = 0x08;
178     // Should report package stats.
179     public static final int REPORT_PKG_STATS = 0x0E;
180     // Should report all stats.
181     public static final int REPORT_ALL = 0x0F;
182 
183     public static final int[] OPTIONS =
184             {REPORT_PROC_STATS, REPORT_PKG_PROC_STATS, REPORT_PKG_SVC_STATS, REPORT_PKG_ASC_STATS,
185                     REPORT_PKG_STATS, REPORT_ALL};
186     public static final String[] OPTIONS_STR =
187             {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
188 
189     // Current version of the parcel format.
190     private static final int PARCEL_VERSION = 38;
191     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
192     private static final int MAGIC = 0x50535454;
193 
194     public String mReadError;
195     public String mTimePeriodStartClockStr;
196     public int mFlags;
197 
198     public final ProcessMap<LongSparseArray<PackageState>> mPackages = new ProcessMap<>();
199     public final ProcessMap<ProcessState> mProcesses = new ProcessMap<>();
200 
201     public final ArrayList<AssociationState.SourceState> mTrackingAssociations = new ArrayList<>();
202 
203     public final long[] mMemFactorDurations = new long[ADJ_COUNT];
204     public int mMemFactor = STATE_NOTHING;
205     public long mStartTime;
206 
207     // Number of individual stats that have been aggregated to create this one.
208     public int mNumAggregated = 1;
209 
210     public long mTimePeriodStartClock;
211     public long mTimePeriodStartRealtime;
212     public long mTimePeriodEndRealtime;
213     public long mTimePeriodStartUptime;
214     public long mTimePeriodEndUptime;
215     String mRuntime;
216     boolean mRunning;
217 
218     boolean mHasSwappedOutPss;
219 
220     // Count and total time expended doing "quick" single pss computations for internal use.
221     public long mInternalSinglePssCount;
222     public long mInternalSinglePssTime;
223 
224     // Count and total time expended doing "quick" all mem pss computations for internal use.
225     public long mInternalAllMemPssCount;
226     public long mInternalAllMemPssTime;
227 
228     // Count and total time expended doing "quick" all poll pss computations for internal use.
229     public long mInternalAllPollPssCount;
230     public long mInternalAllPollPssTime;
231 
232     // Count and total time expended doing "quick" pss computations due to external requests.
233     public long mExternalPssCount;
234     public long mExternalPssTime;
235 
236     // Count and total time expended doing full/slow pss computations due to external requests.
237     public long mExternalSlowPssCount;
238     public long mExternalSlowPssTime;
239 
240     public final SparseMappingTable mTableData = new SparseMappingTable();
241 
242     public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT];
243     public final SysMemUsageTable mSysMemUsage = new SysMemUsageTable(mTableData);
244 
245     // For writing parcels.
246     ArrayMap<String, Integer> mCommonStringToIndex;
247 
248     // For reading parcels.
249     ArrayList<String> mIndexToCommonString;
250 
251     private static final Pattern sPageTypeRegex = Pattern.compile(
252             "^Node\\s+(\\d+),.* zone\\s+(\\w+),.* type\\s+(\\w+)\\s+([\\s\\d]+?)\\s*$");
253     private final ArrayList<Integer> mPageTypeNodes = new ArrayList<>();
254     private final ArrayList<String> mPageTypeZones = new ArrayList<>();
255     private final ArrayList<String> mPageTypeLabels = new ArrayList<>();
256     private final ArrayList<int[]> mPageTypeSizes = new ArrayList<>();
257 
ProcessStats(boolean running)258     public ProcessStats(boolean running) {
259         mRunning = running;
260         reset();
261         if (running) {
262             // If we are actively running, we need to determine whether the system is
263             // collecting swap pss data.
264             Debug.MemoryInfo info = new Debug.MemoryInfo();
265             Debug.getMemoryInfo(android.os.Process.myPid(), info);
266             mHasSwappedOutPss = info.hasSwappedOutPss();
267         }
268     }
269 
ProcessStats(Parcel in)270     public ProcessStats(Parcel in) {
271         reset();
272         readFromParcel(in);
273     }
274 
275     /**
276      * No-arg constructor is for use in AIDL-derived stubs.
277      *
278      * <p>This defaults to the non-running state, so is equivalent to ProcessStats(false).
279      */
ProcessStats()280     public ProcessStats() {
281         this(false);
282     }
283 
add(ProcessStats other)284     public void add(ProcessStats other) {
285         ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
286                 other.mPackages.getMap();
287         for (int ip=0; ip<pkgMap.size(); ip++) {
288             final String pkgName = pkgMap.keyAt(ip);
289             final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
290             for (int iu=0; iu<uids.size(); iu++) {
291                 final int uid = uids.keyAt(iu);
292                 final LongSparseArray<PackageState> versions = uids.valueAt(iu);
293                 for (int iv=0; iv<versions.size(); iv++) {
294                     final long vers = versions.keyAt(iv);
295                     final PackageState otherState = versions.valueAt(iv);
296                     final int NPROCS = otherState.mProcesses.size();
297                     final int NSRVS = otherState.mServices.size();
298                     final int NASCS = otherState.mAssociations.size();
299                     for (int iproc=0; iproc<NPROCS; iproc++) {
300                         ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
301                         if (otherProc.getCommonProcess() != otherProc) {
302                             if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
303                                     + " vers " + vers + " proc " + otherProc.getName());
304                             ProcessState thisProc = getProcessStateLocked(pkgName, uid, vers,
305                                     otherProc.getName());
306                             if (thisProc.getCommonProcess() == thisProc) {
307                                 if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
308                                 thisProc.setMultiPackage(true);
309                                 long now = SystemClock.uptimeMillis();
310                                 final PackageState pkgState = getPackageStateLocked(pkgName, uid,
311                                         vers);
312                                 thisProc = thisProc.clone(now);
313                                 pkgState.mProcesses.put(thisProc.getName(), thisProc);
314                             }
315                             thisProc.add(otherProc);
316                         }
317                     }
318                     for (int isvc=0; isvc<NSRVS; isvc++) {
319                         ServiceState otherSvc = otherState.mServices.valueAt(isvc);
320                         if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
321                                 + " service " + otherSvc.getName());
322                         ServiceState thisSvc = getServiceStateLocked(pkgName, uid, vers,
323                                 otherSvc.getProcessName(), otherSvc.getName());
324                         thisSvc.add(otherSvc);
325                     }
326                     for (int iasc=0; iasc<NASCS; iasc++) {
327                         AssociationState otherAsc = otherState.mAssociations.valueAt(iasc);
328                         if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
329                                 + " association " + otherAsc.getName());
330                         AssociationState thisAsc = getAssociationStateLocked(pkgName, uid, vers,
331                                 otherAsc.getProcessName(), otherAsc.getName());
332                         thisAsc.add(otherAsc);
333                     }
334                 }
335             }
336         }
337 
338         ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
339         for (int ip=0; ip<procMap.size(); ip++) {
340             SparseArray<ProcessState> uids = procMap.valueAt(ip);
341             for (int iu=0; iu<uids.size(); iu++) {
342                 int uid = uids.keyAt(iu);
343                 ProcessState otherProc = uids.valueAt(iu);
344                 final String name = otherProc.getName();
345                 final String pkg = otherProc.getPackage();
346                 final long vers = otherProc.getVersion();
347                 ProcessState thisProc = mProcesses.get(name, uid);
348                 if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + name);
349                 if (thisProc == null) {
350                     if (DEBUG) Slog.d(TAG, "Creating new process!");
351                     thisProc = new ProcessState(this, pkg, uid, vers, name);
352                     mProcesses.put(name, uid, thisProc);
353                     PackageState thisState = getPackageStateLocked(pkg, uid, vers);
354                     if (!thisState.mProcesses.containsKey(name)) {
355                         thisState.mProcesses.put(name, thisProc);
356                     }
357                 }
358                 thisProc.add(otherProc);
359             }
360         }
361 
362         for (int i=0; i<ADJ_COUNT; i++) {
363             if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
364                     + other.mMemFactorDurations[i] + " from "
365                     + mMemFactorDurations[i]);
366             mMemFactorDurations[i] += other.mMemFactorDurations[i];
367         }
368 
369         mSysMemUsage.mergeStats(other.mSysMemUsage);
370 
371         mNumAggregated += other.mNumAggregated;
372 
373         if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
374             mTimePeriodStartClock = other.mTimePeriodStartClock;
375             mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
376         }
377         mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
378         mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime;
379 
380         mInternalSinglePssCount += other.mInternalSinglePssCount;
381         mInternalSinglePssTime += other.mInternalSinglePssTime;
382         mInternalAllMemPssCount += other.mInternalAllMemPssCount;
383         mInternalAllMemPssTime += other.mInternalAllMemPssTime;
384         mInternalAllPollPssCount += other.mInternalAllPollPssCount;
385         mInternalAllPollPssTime += other.mInternalAllPollPssTime;
386         mExternalPssCount += other.mExternalPssCount;
387         mExternalPssTime += other.mExternalPssTime;
388         mExternalSlowPssCount += other.mExternalSlowPssCount;
389         mExternalSlowPssTime += other.mExternalSlowPssTime;
390 
391         mHasSwappedOutPss |= other.mHasSwappedOutPss;
392     }
393 
addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem, long nativeMem)394     public void addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem,
395             long nativeMem) {
396         if (mMemFactor != STATE_NOTHING) {
397             int state = mMemFactor * STATE_COUNT;
398             mSysMemUsageArgs[SYS_MEM_USAGE_SAMPLE_COUNT] = 1;
399             for (int i=0; i<3; i++) {
400                 mSysMemUsageArgs[SYS_MEM_USAGE_CACHED_MINIMUM + i] = cachedMem;
401                 mSysMemUsageArgs[SYS_MEM_USAGE_FREE_MINIMUM + i] = freeMem;
402                 mSysMemUsageArgs[SYS_MEM_USAGE_ZRAM_MINIMUM + i] = zramMem;
403                 mSysMemUsageArgs[SYS_MEM_USAGE_KERNEL_MINIMUM + i] = kernelMem;
404                 mSysMemUsageArgs[SYS_MEM_USAGE_NATIVE_MINIMUM + i] = nativeMem;
405             }
406             mSysMemUsage.mergeStats(state, mSysMemUsageArgs, 0);
407         }
408     }
409 
410     public static final Parcelable.Creator<ProcessStats> CREATOR
411             = new Parcelable.Creator<ProcessStats>() {
412         public ProcessStats createFromParcel(Parcel in) {
413             return new ProcessStats(in);
414         }
415 
416         public ProcessStats[] newArray(int size) {
417             return new ProcessStats[size];
418         }
419     };
420 
computeTotalMemoryUse(TotalMemoryUseCollection data, long now)421     public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) {
422         data.totalTime = 0;
423         for (int i=0; i<STATE_COUNT; i++) {
424             data.processStateWeight[i] = 0;
425             data.processStatePss[i] = 0;
426             data.processStateTime[i] = 0;
427             data.processStateSamples[i] = 0;
428         }
429         for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) {
430             data.sysMemUsage[i] = 0;
431         }
432         data.sysMemCachedWeight = 0;
433         data.sysMemFreeWeight = 0;
434         data.sysMemZRamWeight = 0;
435         data.sysMemKernelWeight = 0;
436         data.sysMemNativeWeight = 0;
437         data.sysMemSamples = 0;
438         final long[] totalMemUsage = mSysMemUsage.getTotalMemUsage();
439         for (int is=0; is<data.screenStates.length; is++) {
440             for (int im=0; im<data.memStates.length; im++) {
441                 int memBucket = data.screenStates[is] + data.memStates[im];
442                 int stateBucket = memBucket * STATE_COUNT;
443                 long memTime = mMemFactorDurations[memBucket];
444                 if (mMemFactor == memBucket) {
445                     memTime += now - mStartTime;
446                 }
447                 data.totalTime += memTime;
448                 final int sysKey = mSysMemUsage.getKey((byte)stateBucket);
449                 long[] longs = totalMemUsage;
450                 int idx = 0;
451                 if (sysKey != SparseMappingTable.INVALID_KEY) {
452                     final long[] tmpLongs = mSysMemUsage.getArrayForKey(sysKey);
453                     final int tmpIndex = SparseMappingTable.getIndexFromKey(sysKey);
454                     if (tmpLongs[tmpIndex+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) {
455                         SysMemUsageTable.mergeSysMemUsage(data.sysMemUsage, 0, longs, idx);
456                         longs = tmpLongs;
457                         idx = tmpIndex;
458                     }
459                 }
460                 data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE]
461                         * (double)memTime;
462                 data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE]
463                         * (double)memTime;
464                 data.sysMemZRamWeight += longs[idx + SYS_MEM_USAGE_ZRAM_AVERAGE]
465                         * (double) memTime;
466                 data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE]
467                         * (double)memTime;
468                 data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE]
469                         * (double)memTime;
470                 data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT];
471              }
472         }
473         data.hasSwappedOutPss = mHasSwappedOutPss;
474         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
475         for (int iproc=0; iproc<procMap.size(); iproc++) {
476             SparseArray<ProcessState> uids = procMap.valueAt(iproc);
477             for (int iu=0; iu<uids.size(); iu++) {
478                 final ProcessState proc = uids.valueAt(iu);
479                 proc.aggregatePss(data, now);
480             }
481         }
482     }
483 
reset()484     public void reset() {
485         if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr);
486         resetCommon();
487         mPackages.getMap().clear();
488         mProcesses.getMap().clear();
489         mMemFactor = STATE_NOTHING;
490         mStartTime = 0;
491         if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
492     }
493 
resetSafely()494     public void resetSafely() {
495         if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
496         resetCommon();
497 
498         // First initialize use count of all common processes.
499         final long now = SystemClock.uptimeMillis();
500         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
501         for (int ip=procMap.size()-1; ip>=0; ip--) {
502             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
503             for (int iu=uids.size()-1; iu>=0; iu--) {
504                 uids.valueAt(iu).tmpNumInUse = 0;
505            }
506         }
507 
508         // Next reset or prune all per-package processes, and for the ones that are reset
509         // track this back to the common processes.
510         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
511                 mPackages.getMap();
512         for (int ip=pkgMap.size()-1; ip>=0; ip--) {
513             final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
514             for (int iu=uids.size()-1; iu>=0; iu--) {
515                 final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
516                 for (int iv=vpkgs.size()-1; iv>=0; iv--) {
517                     final PackageState pkgState = vpkgs.valueAt(iv);
518                     for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
519                         final ProcessState ps = pkgState.mProcesses.valueAt(iproc);
520                         if (ps.isInUse()) {
521                             ps.resetSafely(now);
522                             ps.getCommonProcess().tmpNumInUse++;
523                             ps.getCommonProcess().tmpFoundSubProc = ps;
524                         } else {
525                             pkgState.mProcesses.valueAt(iproc).makeDead();
526                             pkgState.mProcesses.removeAt(iproc);
527                         }
528                     }
529                     for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
530                         final ServiceState ss = pkgState.mServices.valueAt(isvc);
531                         if (ss.isInUse()) {
532                             ss.resetSafely(now);
533                         } else {
534                             pkgState.mServices.removeAt(isvc);
535                         }
536                     }
537                     for (int iasc=pkgState.mAssociations.size()-1; iasc>=0; iasc--) {
538                         final AssociationState as = pkgState.mAssociations.valueAt(iasc);
539                         if (as.isInUse()) {
540                             as.resetSafely(now);
541                         } else {
542                             pkgState.mAssociations.removeAt(iasc);
543                         }
544                     }
545                     if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0
546                             && pkgState.mAssociations.size() <= 0) {
547                         vpkgs.removeAt(iv);
548                     }
549                 }
550                 if (vpkgs.size() <= 0) {
551                     uids.removeAt(iu);
552                 }
553             }
554             if (uids.size() <= 0) {
555                 pkgMap.removeAt(ip);
556             }
557         }
558 
559         // Finally prune out any common processes that are no longer in use.
560         for (int ip=procMap.size()-1; ip>=0; ip--) {
561             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
562             for (int iu=uids.size()-1; iu>=0; iu--) {
563                 ProcessState ps = uids.valueAt(iu);
564                 if (ps.isInUse() || ps.tmpNumInUse > 0) {
565                     // If this is a process for multiple packages, we could at this point
566                     // be back down to one package.  In that case, we want to revert back
567                     // to a single shared ProcessState.  We can do this by converting the
568                     // current package-specific ProcessState up to the shared ProcessState,
569                     // throwing away the current one we have here (because nobody else is
570                     // using it).
571                     if (!ps.isActive() && ps.isMultiPackage() && ps.tmpNumInUse == 1) {
572                         // Here we go...
573                         ps = ps.tmpFoundSubProc;
574                         ps.makeStandalone();
575                         uids.setValueAt(iu, ps);
576                     } else {
577                         ps.resetSafely(now);
578                     }
579                 } else {
580                     ps.makeDead();
581                     uids.removeAt(iu);
582                 }
583             }
584             if (uids.size() <= 0) {
585                 procMap.removeAt(ip);
586             }
587         }
588 
589         mStartTime = now;
590         if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
591     }
592 
resetCommon()593     private void resetCommon() {
594         mNumAggregated = 1;
595         mTimePeriodStartClock = System.currentTimeMillis();
596         buildTimePeriodStartClockStr();
597         mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
598         mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis();
599         mInternalSinglePssCount = 0;
600         mInternalSinglePssTime = 0;
601         mInternalAllMemPssCount = 0;
602         mInternalAllMemPssTime = 0;
603         mInternalAllPollPssCount = 0;
604         mInternalAllPollPssTime = 0;
605         mExternalPssCount = 0;
606         mExternalPssTime = 0;
607         mExternalSlowPssCount = 0;
608         mExternalSlowPssTime = 0;
609         mTableData.reset();
610         Arrays.fill(mMemFactorDurations, 0);
611         mSysMemUsage.resetTable();
612         mStartTime = 0;
613         mReadError = null;
614         mFlags = 0;
615         evaluateSystemProperties(true);
616         updateFragmentation();
617     }
618 
evaluateSystemProperties(boolean update)619     public boolean evaluateSystemProperties(boolean update) {
620         boolean changed = false;
621         String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2",
622                 VMRuntime.getRuntime().vmLibrary());
623         if (!Objects.equals(runtime, mRuntime)) {
624             changed = true;
625             if (update) {
626                 mRuntime = runtime;
627             }
628         }
629         return changed;
630     }
631 
buildTimePeriodStartClockStr()632     private void buildTimePeriodStartClockStr() {
633         mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss",
634                 mTimePeriodStartClock).toString();
635     }
636 
637     static final int[] BAD_TABLE = new int[0];
638 
639 
640     /**
641      * Load the system's memory fragmentation info.
642      */
updateFragmentation()643     public void updateFragmentation() {
644         // Parse /proc/pagetypeinfo and store the values.
645         BufferedReader reader = null;
646         try {
647             reader = new BufferedReader(new FileReader("/proc/pagetypeinfo"));
648             final Matcher matcher = sPageTypeRegex.matcher("");
649             mPageTypeNodes.clear();
650             mPageTypeZones.clear();
651             mPageTypeLabels.clear();
652             mPageTypeSizes.clear();
653             while (true) {
654                 final String line = reader.readLine();
655                 if (line == null) {
656                     break;
657                 }
658                 matcher.reset(line);
659                 if (matcher.matches()) {
660                     final Integer node = Integer.valueOf(matcher.group(1), 10);
661                     if (node == null) {
662                         continue;
663                     }
664                     mPageTypeNodes.add(node);
665                     mPageTypeZones.add(matcher.group(2));
666                     mPageTypeLabels.add(matcher.group(3));
667                     mPageTypeSizes.add(splitAndParseNumbers(matcher.group(4)));
668                 }
669             }
670         } catch (IOException ex) {
671             mPageTypeNodes.clear();
672             mPageTypeZones.clear();
673             mPageTypeLabels.clear();
674             mPageTypeSizes.clear();
675             return;
676         } finally {
677             if (reader != null) {
678                 try {
679                     reader.close();
680                 } catch (IOException allHopeIsLost) {
681                 }
682             }
683         }
684     }
685 
686     /**
687      * Split the string of digits separaed by spaces.  There must be no
688      * leading or trailing spaces.  The format is ensured by the regex
689      * above.
690      */
splitAndParseNumbers(String s)691     private static int[] splitAndParseNumbers(String s) {
692         // These are always positive and the numbers can't be so big that we'll overflow
693         // so just do the parsing inline.
694         boolean digit = false;
695         int count = 0;
696         final int N = s.length();
697         // Count the numbers
698         for (int i=0; i<N; i++) {
699             final char c = s.charAt(i);
700             if (c >= '0' && c <= '9') {
701                 if (!digit) {
702                     digit = true;
703                     count++;
704                 }
705             } else {
706                 digit = false;
707             }
708         }
709         // Parse the numbers
710         final int[] result = new int[count];
711         int p = 0;
712         int val = 0;
713         for (int i=0; i<N; i++) {
714             final char c = s.charAt(i);
715             if (c >= '0' && c <= '9') {
716                 if (!digit) {
717                     digit = true;
718                     val = c - '0';
719                 } else {
720                     val *= 10;
721                     val += c - '0';
722                 }
723             } else {
724                 if (digit) {
725                     digit = false;
726                     result[p++] = val;
727                 }
728             }
729         }
730         if (count > 0) {
731             result[count-1] = val;
732         }
733         return result;
734     }
735 
736 
writeCompactedLongArray(Parcel out, long[] array, int num)737     private void writeCompactedLongArray(Parcel out, long[] array, int num) {
738         for (int i=0; i<num; i++) {
739             long val = array[i];
740             if (val < 0) {
741                 Slog.w(TAG, "Time val negative: " + val);
742                 val = 0;
743             }
744             if (val <= Integer.MAX_VALUE) {
745                 out.writeInt((int)val);
746             } else {
747                 int top = ~((int)((val>>32)&0x7fffffff));
748                 int bottom = (int)(val&0x0ffffffffL);
749                 out.writeInt(top);
750                 out.writeInt(bottom);
751             }
752         }
753     }
754 
readCompactedLongArray(Parcel in, int version, long[] array, int num)755     private void readCompactedLongArray(Parcel in, int version, long[] array, int num) {
756         if (version <= 10) {
757             in.readLongArray(array);
758             return;
759         }
760         final int alen = array.length;
761         if (num > alen) {
762             throw new RuntimeException("bad array lengths: got " + num + " array is " + alen);
763         }
764         int i;
765         for (i=0; i<num; i++) {
766             int val = in.readInt();
767             if (val >= 0) {
768                 array[i] = val;
769             } else {
770                 int bottom = in.readInt();
771                 array[i] = (((long)~val)<<32) | bottom;
772             }
773         }
774         while (i < alen) {
775             array[i] = 0;
776             i++;
777         }
778     }
779 
writeCommonString(Parcel out, String name)780     void writeCommonString(Parcel out, String name) {
781         Integer index = mCommonStringToIndex.get(name);
782         if (index != null) {
783             out.writeInt(index);
784             return;
785         }
786         index = mCommonStringToIndex.size();
787         mCommonStringToIndex.put(name, index);
788         out.writeInt(~index);
789         out.writeString(name);
790     }
791 
readCommonString(Parcel in, int version)792     String readCommonString(Parcel in, int version) {
793         if (version <= 9) {
794             return in.readString();
795         }
796         int index = in.readInt();
797         if (index >= 0) {
798             return mIndexToCommonString.get(index);
799         }
800         index = ~index;
801         String name = in.readString();
802         while (mIndexToCommonString.size() <= index) {
803             mIndexToCommonString.add(null);
804         }
805         mIndexToCommonString.set(index, name);
806         return name;
807     }
808 
809     @Override
describeContents()810     public int describeContents() {
811         return 0;
812     }
813 
814     @Override
writeToParcel(Parcel out, int flags)815     public void writeToParcel(Parcel out, int flags) {
816         writeToParcel(out, SystemClock.uptimeMillis(), flags);
817     }
818 
819     /** @hide */
writeToParcel(Parcel out, long now, int flags)820     public void writeToParcel(Parcel out, long now, int flags) {
821         out.writeInt(MAGIC);
822         out.writeInt(PARCEL_VERSION);
823         out.writeInt(STATE_COUNT);
824         out.writeInt(ADJ_COUNT);
825         out.writeInt(PSS_COUNT);
826         out.writeInt(SYS_MEM_USAGE_COUNT);
827         out.writeInt(SparseMappingTable.ARRAY_SIZE);
828 
829         mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.size());
830 
831         // First commit all running times.
832         ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
833         final int NPROC = procMap.size();
834         for (int ip=0; ip<NPROC; ip++) {
835             SparseArray<ProcessState> uids = procMap.valueAt(ip);
836             final int NUID = uids.size();
837             for (int iu=0; iu<NUID; iu++) {
838                 uids.valueAt(iu).commitStateTime(now);
839             }
840         }
841         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
842                 mPackages.getMap();
843         final int NPKG = pkgMap.size();
844         for (int ip=0; ip<NPKG; ip++) {
845             final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
846             final int NUID = uids.size();
847             for (int iu=0; iu<NUID; iu++) {
848                 final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
849                 final int NVERS = vpkgs.size();
850                 for (int iv=0; iv<NVERS; iv++) {
851                     PackageState pkgState = vpkgs.valueAt(iv);
852                     final int NPROCS = pkgState.mProcesses.size();
853                     for (int iproc=0; iproc<NPROCS; iproc++) {
854                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
855                         if (proc.getCommonProcess() != proc) {
856                             proc.commitStateTime(now);
857                         }
858                     }
859                     final int NSRVS = pkgState.mServices.size();
860                     for (int isvc=0; isvc<NSRVS; isvc++) {
861                         pkgState.mServices.valueAt(isvc).commitStateTime(now);
862                     }
863                     final int NASCS = pkgState.mAssociations.size();
864                     for (int iasc=0; iasc<NASCS; iasc++) {
865                         pkgState.mAssociations.valueAt(iasc).commitStateTime(now);
866                     }
867                 }
868             }
869         }
870 
871         out.writeInt(mNumAggregated);
872         out.writeLong(mTimePeriodStartClock);
873         out.writeLong(mTimePeriodStartRealtime);
874         out.writeLong(mTimePeriodEndRealtime);
875         out.writeLong(mTimePeriodStartUptime);
876         out.writeLong(mTimePeriodEndUptime);
877         out.writeLong(mInternalSinglePssCount);
878         out.writeLong(mInternalSinglePssTime);
879         out.writeLong(mInternalAllMemPssCount);
880         out.writeLong(mInternalAllMemPssTime);
881         out.writeLong(mInternalAllPollPssCount);
882         out.writeLong(mInternalAllPollPssTime);
883         out.writeLong(mExternalPssCount);
884         out.writeLong(mExternalPssTime);
885         out.writeLong(mExternalSlowPssCount);
886         out.writeLong(mExternalSlowPssTime);
887         out.writeString(mRuntime);
888         out.writeInt(mHasSwappedOutPss ? 1 : 0);
889         out.writeInt(mFlags);
890 
891         mTableData.writeToParcel(out);
892 
893         if (mMemFactor != STATE_NOTHING) {
894             mMemFactorDurations[mMemFactor] += now - mStartTime;
895             mStartTime = now;
896         }
897         writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length);
898 
899         mSysMemUsage.writeToParcel(out);
900 
901         out.writeInt(NPROC);
902         for (int ip=0; ip<NPROC; ip++) {
903             writeCommonString(out, procMap.keyAt(ip));
904             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
905             final int NUID = uids.size();
906             out.writeInt(NUID);
907             for (int iu=0; iu<NUID; iu++) {
908                 out.writeInt(uids.keyAt(iu));
909                 final ProcessState proc = uids.valueAt(iu);
910                 writeCommonString(out, proc.getPackage());
911                 out.writeLong(proc.getVersion());
912                 proc.writeToParcel(out, now);
913             }
914         }
915         out.writeInt(NPKG);
916         for (int ip=0; ip<NPKG; ip++) {
917             writeCommonString(out, pkgMap.keyAt(ip));
918             final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
919             final int NUID = uids.size();
920             out.writeInt(NUID);
921             for (int iu=0; iu<NUID; iu++) {
922                 out.writeInt(uids.keyAt(iu));
923                 final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
924                 final int NVERS = vpkgs.size();
925                 out.writeInt(NVERS);
926                 for (int iv=0; iv<NVERS; iv++) {
927                     out.writeLong(vpkgs.keyAt(iv));
928                     final PackageState pkgState = vpkgs.valueAt(iv);
929                     final int NPROCS = pkgState.mProcesses.size();
930                     out.writeInt(NPROCS);
931                     for (int iproc=0; iproc<NPROCS; iproc++) {
932                         writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
933                         final ProcessState proc = pkgState.mProcesses.valueAt(iproc);
934                         if (proc.getCommonProcess() == proc) {
935                             // This is the same as the common process we wrote above.
936                             out.writeInt(0);
937                         } else {
938                             // There is separate data for this package's process.
939                             out.writeInt(1);
940                             proc.writeToParcel(out, now);
941                         }
942                     }
943                     final int NSRVS = pkgState.mServices.size();
944                     out.writeInt(NSRVS);
945                     for (int isvc=0; isvc<NSRVS; isvc++) {
946                         out.writeString(pkgState.mServices.keyAt(isvc));
947                         final ServiceState svc = pkgState.mServices.valueAt(isvc);
948                         writeCommonString(out, svc.getProcessName());
949                         svc.writeToParcel(out, now);
950                     }
951                     final int NASCS = pkgState.mAssociations.size();
952                     out.writeInt(NASCS);
953                     for (int iasc=0; iasc<NASCS; iasc++) {
954                         writeCommonString(out, pkgState.mAssociations.keyAt(iasc));
955                         final AssociationState asc = pkgState.mAssociations.valueAt(iasc);
956                         writeCommonString(out, asc.getProcessName());
957                         asc.writeToParcel(this, out, now);
958                     }
959                 }
960             }
961         }
962 
963         // Fragmentation info (/proc/pagetypeinfo)
964         final int NPAGETYPES = mPageTypeLabels.size();
965         out.writeInt(NPAGETYPES);
966         for (int i=0; i<NPAGETYPES; i++) {
967             out.writeInt(mPageTypeNodes.get(i));
968             out.writeString(mPageTypeZones.get(i));
969             out.writeString(mPageTypeLabels.get(i));
970             out.writeIntArray(mPageTypeSizes.get(i));
971         }
972 
973         mCommonStringToIndex = null;
974     }
975 
readCheckedInt(Parcel in, int val, String what)976     private boolean readCheckedInt(Parcel in, int val, String what) {
977         int got;
978         if ((got=in.readInt()) != val) {
979             mReadError = "bad " + what + ": " + got;
980             return false;
981         }
982         return true;
983     }
984 
readFully(InputStream stream, int[] outLen)985     static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
986         int pos = 0;
987         final int initialAvail = stream.available();
988         byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
989         while (true) {
990             int amt = stream.read(data, pos, data.length-pos);
991             if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
992                     + " of avail " + data.length);
993             if (amt < 0) {
994                 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
995                         + " len=" + data.length);
996                 outLen[0] = pos;
997                 return data;
998             }
999             pos += amt;
1000             if (pos >= data.length) {
1001                 byte[] newData = new byte[pos+16384];
1002                 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
1003                         + newData.length);
1004                 System.arraycopy(data, 0, newData, 0, pos);
1005                 data = newData;
1006             }
1007         }
1008     }
1009 
read(InputStream stream)1010     public void read(InputStream stream) {
1011         try {
1012             int[] len = new int[1];
1013             byte[] raw = readFully(stream, len);
1014             Parcel in = Parcel.obtain();
1015             in.unmarshall(raw, 0, len[0]);
1016             in.setDataPosition(0);
1017             stream.close();
1018 
1019             readFromParcel(in);
1020         } catch (IOException e) {
1021             mReadError = "caught exception: " + e;
1022         }
1023     }
1024 
readFromParcel(Parcel in)1025     public void readFromParcel(Parcel in) {
1026         final boolean hadData = mPackages.getMap().size() > 0
1027                 || mProcesses.getMap().size() > 0;
1028         if (hadData) {
1029             resetSafely();
1030         }
1031 
1032         if (!readCheckedInt(in, MAGIC, "magic number")) {
1033             return;
1034         }
1035         int version = in.readInt();
1036         if (version != PARCEL_VERSION) {
1037             mReadError = "bad version: " + version;
1038             return;
1039         }
1040         if (!readCheckedInt(in, STATE_COUNT, "state count")) {
1041             return;
1042         }
1043         if (!readCheckedInt(in, ADJ_COUNT, "adj count")) {
1044             return;
1045         }
1046         if (!readCheckedInt(in, PSS_COUNT, "pss count")) {
1047             return;
1048         }
1049         if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) {
1050             return;
1051         }
1052         if (!readCheckedInt(in, SparseMappingTable.ARRAY_SIZE, "longs size")) {
1053             return;
1054         }
1055 
1056         mIndexToCommonString = new ArrayList<String>();
1057 
1058         mNumAggregated = in.readInt();
1059         mTimePeriodStartClock = in.readLong();
1060         buildTimePeriodStartClockStr();
1061         mTimePeriodStartRealtime = in.readLong();
1062         mTimePeriodEndRealtime = in.readLong();
1063         mTimePeriodStartUptime = in.readLong();
1064         mTimePeriodEndUptime = in.readLong();
1065         mInternalSinglePssCount = in.readLong();
1066         mInternalSinglePssTime = in.readLong();
1067         mInternalAllMemPssCount = in.readLong();
1068         mInternalAllMemPssTime = in.readLong();
1069         mInternalAllPollPssCount = in.readLong();
1070         mInternalAllPollPssTime = in.readLong();
1071         mExternalPssCount = in.readLong();
1072         mExternalPssTime = in.readLong();
1073         mExternalSlowPssCount = in.readLong();
1074         mExternalSlowPssTime = in.readLong();
1075         mRuntime = in.readString();
1076         mHasSwappedOutPss = in.readInt() != 0;
1077         mFlags = in.readInt();
1078         mTableData.readFromParcel(in);
1079         readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length);
1080         if (!mSysMemUsage.readFromParcel(in)) {
1081             return;
1082         }
1083 
1084         int NPROC = in.readInt();
1085         if (NPROC < 0) {
1086             mReadError = "bad process count: " + NPROC;
1087             return;
1088         }
1089         while (NPROC > 0) {
1090             NPROC--;
1091             final String procName = readCommonString(in, version);
1092             if (procName == null) {
1093                 mReadError = "bad process name";
1094                 return;
1095             }
1096             int NUID = in.readInt();
1097             if (NUID < 0) {
1098                 mReadError = "bad uid count: " + NUID;
1099                 return;
1100             }
1101             while (NUID > 0) {
1102                 NUID--;
1103                 final int uid = in.readInt();
1104                 if (uid < 0) {
1105                     mReadError = "bad uid: " + uid;
1106                     return;
1107                 }
1108                 final String pkgName = readCommonString(in, version);
1109                 if (pkgName == null) {
1110                     mReadError = "bad process package name";
1111                     return;
1112                 }
1113                 final long vers = in.readLong();
1114                 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
1115                 if (proc != null) {
1116                     if (!proc.readFromParcel(in, false)) {
1117                         return;
1118                     }
1119                 } else {
1120                     proc = new ProcessState(this, pkgName, uid, vers, procName);
1121                     if (!proc.readFromParcel(in, true)) {
1122                         return;
1123                     }
1124                 }
1125                 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
1126                         + " " + proc);
1127                 mProcesses.put(procName, uid, proc);
1128             }
1129         }
1130 
1131         if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
1132 
1133         int NPKG = in.readInt();
1134         if (NPKG < 0) {
1135             mReadError = "bad package count: " + NPKG;
1136             return;
1137         }
1138         while (NPKG > 0) {
1139             NPKG--;
1140             final String pkgName = readCommonString(in, version);
1141             if (pkgName == null) {
1142                 mReadError = "bad package name";
1143                 return;
1144             }
1145             int NUID = in.readInt();
1146             if (NUID < 0) {
1147                 mReadError = "bad uid count: " + NUID;
1148                 return;
1149             }
1150             while (NUID > 0) {
1151                 NUID--;
1152                 final int uid = in.readInt();
1153                 if (uid < 0) {
1154                     mReadError = "bad uid: " + uid;
1155                     return;
1156                 }
1157                 int NVERS = in.readInt();
1158                 if (NVERS < 0) {
1159                     mReadError = "bad versions count: " + NVERS;
1160                     return;
1161                 }
1162                 while (NVERS > 0) {
1163                     NVERS--;
1164                     final long vers = in.readLong();
1165                     PackageState pkgState = new PackageState(this, pkgName, uid, vers);
1166                     LongSparseArray<PackageState> vpkg = mPackages.get(pkgName, uid);
1167                     if (vpkg == null) {
1168                         vpkg = new LongSparseArray<>();
1169                         mPackages.put(pkgName, uid, vpkg);
1170                     }
1171                     vpkg.put(vers, pkgState);
1172                     int NPROCS = in.readInt();
1173                     if (NPROCS < 0) {
1174                         mReadError = "bad package process count: " + NPROCS;
1175                         return;
1176                     }
1177                     while (NPROCS > 0) {
1178                         NPROCS--;
1179                         String procName = readCommonString(in, version);
1180                         if (procName == null) {
1181                             mReadError = "bad package process name";
1182                             return;
1183                         }
1184                         int hasProc = in.readInt();
1185                         if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
1186                                 + " process " + procName + " hasProc=" + hasProc);
1187                         ProcessState commonProc = mProcesses.get(procName, uid);
1188                         if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
1189                                 + ": " + commonProc);
1190                         if (commonProc == null) {
1191                             mReadError = "no common proc: " + procName;
1192                             return;
1193                         }
1194                         if (hasProc != 0) {
1195                             // The process for this package is unique to the package; we
1196                             // need to load it.  We don't need to do anything about it if
1197                             // it is not unique because if someone later looks for it
1198                             // they will find and use it from the global procs.
1199                             ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
1200                             if (proc != null) {
1201                                 if (!proc.readFromParcel(in, false)) {
1202                                     return;
1203                                 }
1204                             } else {
1205                                 proc = new ProcessState(commonProc, pkgName, uid, vers, procName,
1206                                         0);
1207                                 if (!proc.readFromParcel(in, true)) {
1208                                     return;
1209                                 }
1210                             }
1211                             if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
1212                                     + procName + " " + uid + " " + proc);
1213                             pkgState.mProcesses.put(procName, proc);
1214                         } else {
1215                             if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
1216                                     + procName + " " + uid + " " + commonProc);
1217                             pkgState.mProcesses.put(procName, commonProc);
1218                         }
1219                     }
1220                     int NSRVS = in.readInt();
1221                     if (NSRVS < 0) {
1222                         mReadError = "bad package service count: " + NSRVS;
1223                         return;
1224                     }
1225                     while (NSRVS > 0) {
1226                         NSRVS--;
1227                         String serviceName = in.readString();
1228                         if (serviceName == null) {
1229                             mReadError = "bad package service name";
1230                             return;
1231                         }
1232                         String processName = version > 9 ? readCommonString(in, version) : null;
1233                         ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
1234                         if (serv == null) {
1235                             serv = new ServiceState(this, pkgName, serviceName, processName, null);
1236                         }
1237                         if (!serv.readFromParcel(in)) {
1238                             return;
1239                         }
1240                         if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
1241                                 + serviceName + " " + uid + " " + serv);
1242                         pkgState.mServices.put(serviceName, serv);
1243                     }
1244                     int NASCS = in.readInt();
1245                     if (NASCS < 0) {
1246                         mReadError = "bad package association count: " + NASCS;
1247                         return;
1248                     }
1249                     while (NASCS > 0) {
1250                         NASCS--;
1251                         String associationName = readCommonString(in, version);
1252                         if (associationName == null) {
1253                             mReadError = "bad package association name";
1254                             return;
1255                         }
1256                         String processName = readCommonString(in, version);
1257                         AssociationState asc = hadData
1258                                 ? pkgState.mAssociations.get(associationName) : null;
1259                         if (asc == null) {
1260                             asc = new AssociationState(this, pkgState, associationName,
1261                                     processName, null);
1262                         }
1263                         String errorMsg = asc.readFromParcel(this, in, version);
1264                         if (errorMsg != null) {
1265                             mReadError = errorMsg;
1266                             return;
1267                         }
1268                         if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " association: "
1269                                 + associationName + " " + uid + " " + asc);
1270                         pkgState.mAssociations.put(associationName, asc);
1271                     }
1272                 }
1273             }
1274         }
1275 
1276         // Fragmentation info
1277         final int NPAGETYPES = in.readInt();
1278         mPageTypeNodes.clear();
1279         mPageTypeNodes.ensureCapacity(NPAGETYPES);
1280         mPageTypeZones.clear();
1281         mPageTypeZones.ensureCapacity(NPAGETYPES);
1282         mPageTypeLabels.clear();
1283         mPageTypeLabels.ensureCapacity(NPAGETYPES);
1284         mPageTypeSizes.clear();
1285         mPageTypeSizes.ensureCapacity(NPAGETYPES);
1286         for (int i=0; i<NPAGETYPES; i++) {
1287             mPageTypeNodes.add(in.readInt());
1288             mPageTypeZones.add(in.readString());
1289             mPageTypeLabels.add(in.readString());
1290             mPageTypeSizes.add(in.createIntArray());
1291         }
1292 
1293         mIndexToCommonString = null;
1294 
1295         if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
1296     }
1297 
getPackageStateLocked(String packageName, int uid, long vers)1298     public PackageState getPackageStateLocked(String packageName, int uid, long vers) {
1299         LongSparseArray<PackageState> vpkg = mPackages.get(packageName, uid);
1300         if (vpkg == null) {
1301             vpkg = new LongSparseArray<>();
1302             mPackages.put(packageName, uid, vpkg);
1303         }
1304         PackageState as = vpkg.get(vers);
1305         if (as != null) {
1306             return as;
1307         }
1308         as = new PackageState(this, packageName, uid, vers);
1309         vpkg.put(vers, as);
1310         return as;
1311     }
1312 
getProcessStateLocked(String packageName, int uid, long vers, String processName)1313     public ProcessState getProcessStateLocked(String packageName, int uid, long vers,
1314             String processName) {
1315         return getProcessStateLocked(getPackageStateLocked(packageName, uid, vers), processName);
1316     }
1317 
getProcessStateLocked(PackageState pkgState, String processName)1318     public ProcessState getProcessStateLocked(PackageState pkgState, String processName) {
1319         ProcessState ps = pkgState.mProcesses.get(processName);
1320         if (ps != null) {
1321             return ps;
1322         }
1323         ProcessState commonProc = mProcesses.get(processName, pkgState.mUid);
1324         if (commonProc == null) {
1325             commonProc = new ProcessState(this, pkgState.mPackageName, pkgState.mUid,
1326                     pkgState.mVersionCode, processName);
1327             mProcesses.put(processName, pkgState.mUid, commonProc);
1328             if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
1329         }
1330         if (!commonProc.isMultiPackage()) {
1331             if (pkgState.mPackageName.equals(commonProc.getPackage())
1332                     && pkgState.mVersionCode == commonProc.getVersion()) {
1333                 // This common process is not in use by multiple packages, and
1334                 // is for the calling package, so we can just use it directly.
1335                 ps = commonProc;
1336                 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
1337             } else {
1338                 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
1339                 // This common process has not been in use by multiple packages,
1340                 // but it was created for a different package than the caller.
1341                 // We need to convert it to a multi-package process.
1342                 commonProc.setMultiPackage(true);
1343                 // To do this, we need to make two new process states, one a copy
1344                 // of the current state for the process under the original package
1345                 // name, and the second a free new process state for it as the
1346                 // new package name.
1347                 long now = SystemClock.uptimeMillis();
1348                 // First let's make a copy of the current process state and put
1349                 // that under the now unique state for its original package name.
1350                 final PackageState commonPkgState = getPackageStateLocked(commonProc.getPackage(),
1351                         pkgState.mUid, commonProc.getVersion());
1352                 if (commonPkgState != null) {
1353                     ProcessState cloned = commonProc.clone(now);
1354                     if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.getPackage()
1355                             + ": " + cloned);
1356                     commonPkgState.mProcesses.put(commonProc.getName(), cloned);
1357                     // If this has active services, we need to update their process pointer
1358                     // to point to the new package-specific process state.
1359                     for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
1360                         ServiceState ss = commonPkgState.mServices.valueAt(i);
1361                         if (ss.getProcess() == commonProc) {
1362                             if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: " + ss);
1363                             ss.setProcess(cloned);
1364                         } else if (DEBUG) {
1365                             Slog.d(TAG, "GETPROC leaving proc of " + ss);
1366                         }
1367                     }
1368                     // Also update active associations.
1369                     for (int i=commonPkgState.mAssociations.size()-1; i>=0; i--) {
1370                         AssociationState as = commonPkgState.mAssociations.valueAt(i);
1371                         if (as.getProcess() == commonProc) {
1372                             if (DEBUG) Slog.d(TAG, "GETPROC switching association to cloned: "
1373                                     + as);
1374                             as.setProcess(cloned);
1375                         } else if (DEBUG) {
1376                             Slog.d(TAG, "GETPROC leaving proc of " + as);
1377                         }
1378                     }
1379                 } else {
1380                     Slog.w(TAG, "Cloning proc state: no package state " + commonProc.getPackage()
1381                             + "/" + pkgState.mUid + " for proc " + commonProc.getName());
1382                 }
1383                 // And now make a fresh new process state for the new package name.
1384                 ps = new ProcessState(commonProc, pkgState.mPackageName, pkgState.mUid,
1385                         pkgState.mVersionCode, processName, now);
1386                 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
1387             }
1388         } else {
1389             // The common process is for multiple packages, we need to create a
1390             // separate object for the per-package data.
1391             ps = new ProcessState(commonProc, pkgState.mPackageName, pkgState.mUid,
1392                     pkgState.mVersionCode, processName,
1393                     SystemClock.uptimeMillis());
1394             if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
1395         }
1396         pkgState.mProcesses.put(processName, ps);
1397         if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
1398         return ps;
1399     }
1400 
getServiceStateLocked(String packageName, int uid, long vers, String processName, String className)1401     public ServiceState getServiceStateLocked(String packageName, int uid, long vers,
1402             String processName, String className) {
1403         final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers);
1404         ServiceState ss = as.mServices.get(className);
1405         if (ss != null) {
1406             if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
1407             return ss;
1408         }
1409         final ProcessState ps = processName != null
1410                 ? getProcessStateLocked(packageName, uid, vers, processName) : null;
1411         ss = new ServiceState(this, packageName, className, processName, ps);
1412         as.mServices.put(className, ss);
1413         if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
1414         return ss;
1415     }
1416 
getAssociationStateLocked(String packageName, int uid, long vers, String processName, String className)1417     public AssociationState getAssociationStateLocked(String packageName, int uid, long vers,
1418             String processName, String className) {
1419         final ProcessStats.PackageState pkgs = getPackageStateLocked(packageName, uid, vers);
1420         AssociationState as = pkgs.mAssociations.get(className);
1421         if (as != null) {
1422             if (DEBUG) Slog.d(TAG, "GETASC: returning existing " + as);
1423             return as;
1424         }
1425         final ProcessState procs = processName != null
1426                 ? getProcessStateLocked(packageName, uid, vers, processName) : null;
1427         as = new AssociationState(this, pkgs, className, processName, procs);
1428         pkgs.mAssociations.put(className, as);
1429         if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + procs);
1430         return as;
1431     }
1432 
1433     // See b/118826162 -- to avoid logspaming, we rate limit the warnings.
1434     private static final long INVERSE_PROC_STATE_WARNING_MIN_INTERVAL_MS = 10_000L;
1435     private long mNextInverseProcStateWarningUptime;
1436     private int mSkippedInverseProcStateWarningCount;
1437 
updateTrackingAssociationsLocked(int curSeq, long now)1438     public void updateTrackingAssociationsLocked(int curSeq, long now) {
1439         final int NUM = mTrackingAssociations.size();
1440         for (int i = NUM - 1; i >= 0; i--) {
1441             final AssociationState.SourceState act = mTrackingAssociations.get(i);
1442             if (act.mProcStateSeq != curSeq || act.mProcState >= ProcessStats.STATE_HOME) {
1443                 // If this association did not get touched the last time we computed
1444                 // process states, or its state ended up down in cached, then we no
1445                 // longer have a reason to track it at all.
1446                 act.stopActive(now);
1447                 act.mInTrackingList = false;
1448                 act.mProcState = ProcessStats.STATE_NOTHING;
1449                 mTrackingAssociations.remove(i);
1450             } else {
1451                 final ProcessState proc = act.getAssociationState().getProcess();
1452                 if (proc != null) {
1453                     final int procState = proc.getCombinedState() % STATE_COUNT;
1454                     if (act.mProcState == procState) {
1455                         act.startActive(now);
1456                     } else {
1457                         act.stopActive(now);
1458                         if (act.mProcState < procState) {
1459                             final long nowUptime = SystemClock.uptimeMillis();
1460                             if (mNextInverseProcStateWarningUptime > nowUptime) {
1461                                 mSkippedInverseProcStateWarningCount++;
1462                             } else {
1463                                 // TODO We still see it during boot related to GMS-core.
1464                                 // b/118826162
1465                                 Slog.w(TAG, "Tracking association " + act + " whose proc state "
1466                                         + act.mProcState + " is better than process " + proc
1467                                         + " proc state " + procState
1468                                         + " (" +  mSkippedInverseProcStateWarningCount
1469                                         + " skipped)");
1470                                 mSkippedInverseProcStateWarningCount = 0;
1471                                 mNextInverseProcStateWarningUptime =
1472                                         nowUptime + INVERSE_PROC_STATE_WARNING_MIN_INTERVAL_MS;
1473                             }
1474                         }
1475                     }
1476                 } else {
1477                     // Don't need rate limiting on it.
1478                     Slog.wtf(TAG, "Tracking association without process: " + act
1479                             + " in " + act.getAssociationState());
1480                 }
1481             }
1482         }
1483     }
1484 
1485     final class AssociationDumpContainer {
1486         final AssociationState mState;
1487         ArrayList<Pair<AssociationState.SourceKey, AssociationState.SourceDumpContainer>> mSources;
1488         long mTotalTime;
1489         long mActiveTime;
1490 
AssociationDumpContainer(AssociationState state)1491         AssociationDumpContainer(AssociationState state) {
1492             mState = state;
1493         }
1494     }
1495 
1496     static final Comparator<AssociationDumpContainer> ASSOCIATION_COMPARATOR = (o1, o2) -> {
1497         int diff = o1.mState.getProcessName().compareTo(o2.mState.getProcessName());
1498         if (diff != 0) {
1499             return diff;
1500         }
1501         if (o1.mActiveTime != o2.mActiveTime) {
1502             return o1.mActiveTime > o2.mActiveTime ? -1 : 1;
1503         }
1504         if (o1.mTotalTime != o2.mTotalTime) {
1505             return o1.mTotalTime > o2.mTotalTime ? -1 : 1;
1506         }
1507         diff = o1.mState.getName().compareTo(o2.mState.getName());
1508         if (diff != 0) {
1509             return diff;
1510         }
1511         return 0;
1512     };
1513 
dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, boolean dumpDetails, boolean dumpAll, boolean activeOnly, int section)1514     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
1515             boolean dumpDetails, boolean dumpAll, boolean activeOnly, int section) {
1516         long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
1517                 mStartTime, now);
1518         pw.print("          Start time: ");
1519         pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
1520         pw.println();
1521         pw.print("        Total uptime: ");
1522         TimeUtils.formatDuration(
1523                 (mRunning ? SystemClock.uptimeMillis() : mTimePeriodEndUptime)
1524                         - mTimePeriodStartUptime, pw);
1525         pw.println();
1526         pw.print("  Total elapsed time: ");
1527         TimeUtils.formatDuration(
1528                 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
1529                         - mTimePeriodStartRealtime, pw);
1530         boolean partial = true;
1531         if ((mFlags & FLAG_SHUTDOWN) != 0) {
1532             pw.print(" (shutdown)");
1533             partial = false;
1534         }
1535         if ((mFlags & FLAG_SYSPROPS) != 0) {
1536             pw.print(" (sysprops)");
1537             partial = false;
1538         }
1539         if ((mFlags & FLAG_COMPLETE) != 0) {
1540             pw.print(" (complete)");
1541             partial = false;
1542         }
1543         if (partial) {
1544             pw.print(" (partial)");
1545         }
1546         if (mHasSwappedOutPss) {
1547             pw.print(" (swapped-out-pss)");
1548         }
1549         pw.print(' ');
1550         pw.print(mRuntime);
1551         pw.println();
1552         pw.print("     Aggregated over: ");
1553         pw.println(mNumAggregated);
1554         if (mSysMemUsage.getKeyCount() > 0) {
1555             pw.println();
1556             pw.println("System memory usage:");
1557             mSysMemUsage.dump(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
1558         }
1559         boolean printedHeader = false;
1560         if ((section & REPORT_PKG_STATS) != 0) {
1561             ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
1562                     mPackages.getMap();
1563             for (int ip = 0; ip < pkgMap.size(); ip++) {
1564                 final String pkgName = pkgMap.keyAt(ip);
1565                 final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
1566                 for (int iu = 0; iu < uids.size(); iu++) {
1567                     final int uid = uids.keyAt(iu);
1568                     final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
1569                     for (int iv = 0; iv < vpkgs.size(); iv++) {
1570                         final long vers = vpkgs.keyAt(iv);
1571                         final PackageState pkgState = vpkgs.valueAt(iv);
1572                         final int NPROCS = pkgState.mProcesses.size();
1573                         final int NSRVS = pkgState.mServices.size();
1574                         final int NASCS = pkgState.mAssociations.size();
1575                         final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
1576                         boolean onlyAssociations = false;
1577                         boolean procMatch = false;
1578                         if (!pkgMatch) {
1579                             for (int iproc = 0; iproc < NPROCS; iproc++) {
1580                                 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1581                                 if (reqPackage.equals(proc.getName())) {
1582                                     procMatch = true;
1583                                     break;
1584                                 }
1585                             }
1586                             if (!procMatch) {
1587                                 // Check if this app has any associations with the requested
1588                                 // package, so that if so we print those.
1589                                 for (int iasc = 0; iasc < NASCS; iasc++) {
1590                                     AssociationState asc = pkgState.mAssociations.valueAt(iasc);
1591                                     if (asc.hasProcessOrPackage(reqPackage)) {
1592                                         onlyAssociations = true;
1593                                         break;
1594                                     }
1595                                 }
1596                                 if (!onlyAssociations) {
1597                                     continue;
1598                                 }
1599                             }
1600                         }
1601                         if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) {
1602                             if (!printedHeader) {
1603                                 pw.println();
1604                                 pw.println("Per-Package Stats:");
1605                                 printedHeader = true;
1606                             }
1607                             pw.print("  * ");
1608                             pw.print(pkgName);
1609                             pw.print(" / ");
1610                             UserHandle.formatUid(pw, uid);
1611                             pw.print(" / v");
1612                             pw.print(vers);
1613                             pw.println(":");
1614                         }
1615                         if ((section & REPORT_PKG_PROC_STATS) != 0 && !onlyAssociations) {
1616                             if (!dumpSummary || dumpAll) {
1617                                 for (int iproc = 0; iproc < NPROCS; iproc++) {
1618                                     ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1619                                     if (!pkgMatch && !reqPackage.equals(proc.getName())) {
1620                                         continue;
1621                                     }
1622                                     if (activeOnly && !proc.isInUse()) {
1623                                         pw.print("      (Not active: ");
1624                                         pw.print(pkgState.mProcesses.keyAt(iproc));
1625                                         pw.println(")");
1626                                         continue;
1627                                     }
1628                                     pw.print("      Process ");
1629                                     pw.print(pkgState.mProcesses.keyAt(iproc));
1630                                     if (proc.getCommonProcess().isMultiPackage()) {
1631                                         pw.print(" (multi, ");
1632                                     } else {
1633                                         pw.print(" (unique, ");
1634                                     }
1635                                     pw.print(proc.getDurationsBucketCount());
1636                                     pw.print(" entries)");
1637                                     pw.println(":");
1638                                     proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ,
1639                                             ALL_MEM_ADJ,
1640                                             ALL_PROC_STATES, now);
1641                                     proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1642                                             ALL_PROC_STATES, now);
1643                                     proc.dumpInternalLocked(pw, "        ", dumpAll);
1644                                 }
1645                             } else {
1646                                 ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
1647                                 for (int iproc = 0; iproc < NPROCS; iproc++) {
1648                                     ProcessState proc = pkgState.mProcesses.valueAt(iproc);
1649                                     if (!pkgMatch && !reqPackage.equals(proc.getName())) {
1650                                         continue;
1651                                     }
1652                                     if (activeOnly && !proc.isInUse()) {
1653                                         continue;
1654                                     }
1655                                     procs.add(proc);
1656                                 }
1657                                 DumpUtils.dumpProcessSummaryLocked(pw, "      ", "Prc ", procs,
1658                                         ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES,
1659                                         now, totalTime);
1660                             }
1661                         }
1662                         if ((section & REPORT_PKG_SVC_STATS) != 0 && !onlyAssociations) {
1663                             for (int isvc = 0; isvc < NSRVS; isvc++) {
1664                                 ServiceState svc = pkgState.mServices.valueAt(isvc);
1665                                 if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) {
1666                                     continue;
1667                                 }
1668                                 if (activeOnly && !svc.isInUse()) {
1669                                     pw.print("      (Not active service: ");
1670                                     pw.print(pkgState.mServices.keyAt(isvc));
1671                                     pw.println(")");
1672                                     continue;
1673                                 }
1674                                 if (dumpAll) {
1675                                     pw.print("      Service ");
1676                                 } else {
1677                                     pw.print("      * Svc ");
1678                                 }
1679                                 pw.print(pkgState.mServices.keyAt(isvc));
1680                                 pw.println(":");
1681                                 pw.print("        Process: ");
1682                                 pw.println(svc.getProcessName());
1683                                 svc.dumpStats(pw, "        ", "          ", "    ",
1684                                         now, totalTime, dumpSummary, dumpAll);
1685                             }
1686                         }
1687                         if ((section & REPORT_PKG_ASC_STATS) != 0) {
1688                             ArrayList<AssociationDumpContainer> associations =
1689                                     new ArrayList<>(NASCS);
1690                             for (int iasc = 0; iasc < NASCS; iasc++) {
1691                                 AssociationState asc = pkgState.mAssociations.valueAt(iasc);
1692                                 if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) {
1693                                     if (!onlyAssociations || !asc.hasProcessOrPackage(reqPackage)) {
1694                                         continue;
1695                                     }
1696                                 }
1697                                 final AssociationDumpContainer cont =
1698                                         new AssociationDumpContainer(asc);
1699                                 cont.mSources = asc.createSortedAssociations(now, totalTime);
1700                                 cont.mTotalTime = asc.getTotalDuration(now);
1701                                 cont.mActiveTime = asc.getActiveDuration(now);
1702                                 associations.add(cont);
1703                             }
1704                             Collections.sort(associations, ASSOCIATION_COMPARATOR);
1705                             final int NCONT = associations.size();
1706                             for (int iasc = 0; iasc < NCONT; iasc++) {
1707                                 final AssociationDumpContainer cont = associations.get(iasc);
1708                                 final AssociationState asc = cont.mState;
1709                                 if (activeOnly && !asc.isInUse()) {
1710                                     pw.print("      (Not active association: ");
1711                                     pw.print(pkgState.mAssociations.keyAt(iasc));
1712                                     pw.println(")");
1713                                     continue;
1714                                 }
1715                                 if (dumpAll) {
1716                                     pw.print("      Association ");
1717                                 } else {
1718                                     pw.print("      * Asc ");
1719                                 }
1720                                 pw.print(cont.mState.getName());
1721                                 pw.println(":");
1722                                 pw.print("        Process: ");
1723                                 pw.println(asc.getProcessName());
1724                                 asc.dumpStats(pw, "        ", "          ", "    ",
1725                                         cont.mSources, now, totalTime,
1726                                         onlyAssociations && !pkgMatch && !procMatch
1727                                                 && !asc.getProcessName().equals(reqPackage)
1728                                                 ? reqPackage : null, dumpDetails, dumpAll);
1729                             }
1730                         }
1731                     }
1732                 }
1733             }
1734         }
1735 
1736         if ((section & REPORT_PROC_STATS) != 0) {
1737             ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
1738             printedHeader = false;
1739             int numShownProcs = 0, numTotalProcs = 0;
1740             for (int ip = 0; ip < procMap.size(); ip++) {
1741                 String procName = procMap.keyAt(ip);
1742                 SparseArray<ProcessState> uids = procMap.valueAt(ip);
1743                 for (int iu = 0; iu < uids.size(); iu++) {
1744                     int uid = uids.keyAt(iu);
1745                     numTotalProcs++;
1746                     final ProcessState proc = uids.valueAt(iu);
1747                     if (!proc.hasAnyData()) {
1748                         continue;
1749                     }
1750                     if (!proc.isMultiPackage()) {
1751                         continue;
1752                     }
1753                     if (reqPackage != null && !reqPackage.equals(procName)
1754                             && !reqPackage.equals(proc.getPackage())) {
1755                         continue;
1756                     }
1757                     numShownProcs++;
1758                     pw.println();
1759                     if (!printedHeader) {
1760                         pw.println("Multi-Package Common Processes:");
1761                         printedHeader = true;
1762                     }
1763                     if (activeOnly && !proc.isInUse()) {
1764                         pw.print("      (Not active: ");
1765                         pw.print(procName);
1766                         pw.println(")");
1767                         continue;
1768                     }
1769                     pw.print("  * ");
1770                     pw.print(procName);
1771                     pw.print(" / ");
1772                     UserHandle.formatUid(pw, uid);
1773                     pw.print(" (");
1774                     pw.print(proc.getDurationsBucketCount());
1775                     pw.print(" entries)");
1776                     pw.println(":");
1777                     proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1778                             ALL_PROC_STATES, now);
1779                     proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now);
1780                     proc.dumpInternalLocked(pw, "        ", dumpAll);
1781                 }
1782             }
1783             pw.print("  Total procs: "); pw.print(numShownProcs);
1784             pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
1785         }
1786 
1787         if (dumpAll) {
1788             pw.println();
1789             if (mTrackingAssociations.size() > 0) {
1790                 pw.println();
1791                 pw.println("Tracking associations:");
1792                 for (int i = 0; i < mTrackingAssociations.size(); i++) {
1793                     final AssociationState.SourceState src = mTrackingAssociations.get(i);
1794                     final AssociationState asc = src.getAssociationState();
1795                     pw.print("  #");
1796                     pw.print(i);
1797                     pw.print(": ");
1798                     pw.print(asc.getProcessName());
1799                     pw.print("/");
1800                     UserHandle.formatUid(pw, asc.getUid());
1801                     pw.print(" <- ");
1802                     pw.print(src.getProcessName());
1803                     pw.print("/");
1804                     UserHandle.formatUid(pw, src.getUid());
1805                     pw.println(":");
1806                     pw.print("    Tracking for: ");
1807                     TimeUtils.formatDuration(now - src.mTrackingUptime, pw);
1808                     pw.println();
1809                     pw.print("    Component: ");
1810                     pw.print(new ComponentName(asc.getPackage(), asc.getName())
1811                             .flattenToShortString());
1812                     pw.println();
1813                     pw.print("    Proc state: ");
1814                     if (src.mProcState != ProcessStats.STATE_NOTHING) {
1815                         pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
1816                     } else {
1817                         pw.print("--");
1818                     }
1819                     pw.print(" #");
1820                     pw.println(src.mProcStateSeq);
1821                     pw.print("    Process: ");
1822                     pw.println(asc.getProcess());
1823                     if (src.mActiveCount > 0) {
1824                         pw.print("    Active count ");
1825                         pw.print(src.mActiveCount);
1826                         pw.print(": ");
1827                         asc.dumpActiveDurationSummary(pw, src, totalTime, now, dumpAll);
1828                         pw.println();
1829                     }
1830                 }
1831             }
1832         }
1833 
1834         pw.println();
1835         if (dumpSummary) {
1836             pw.println("Process summary:");
1837             dumpSummaryLocked(pw, reqPackage, now, activeOnly);
1838         } else {
1839             dumpTotalsLocked(pw, now);
1840         }
1841 
1842         if (dumpAll) {
1843             pw.println();
1844             pw.println("Internal state:");
1845             /*
1846             pw.print("  Num long arrays: "); pw.println(mLongs.size());
1847             pw.print("  Next long entry: "); pw.println(mNextLong);
1848             */
1849             pw.print("  mRunning="); pw.println(mRunning);
1850         }
1851 
1852         if (reqPackage == null) {
1853             dumpFragmentationLocked(pw);
1854         }
1855     }
1856 
dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly)1857     public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
1858         long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
1859                 mStartTime, now);
1860         dumpFilteredSummaryLocked(pw, null, "  ", null, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
1861                 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
1862         pw.println();
1863         dumpTotalsLocked(pw, now);
1864     }
1865 
dumpFragmentationLocked(PrintWriter pw)1866     private void dumpFragmentationLocked(PrintWriter pw) {
1867         pw.println();
1868         pw.println("Available pages by page size:");
1869         final int NPAGETYPES = mPageTypeLabels.size();
1870         for (int i=0; i<NPAGETYPES; i++) {
1871             pw.format("Node %3d Zone %7s  %14s ", mPageTypeNodes.get(i), mPageTypeZones.get(i),
1872                     mPageTypeLabels.get(i));
1873             final int[] sizes = mPageTypeSizes.get(i);
1874             final int N = sizes == null ? 0 : sizes.length;
1875             for (int j=0; j<N; j++) {
1876                 pw.format("%6d", sizes[j]);
1877             }
1878             pw.println();
1879         }
1880     }
1881 
printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, long totalTime, long curTotalMem, int samples)1882     long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight,
1883             long totalTime, long curTotalMem, int samples) {
1884         if (memWeight != 0) {
1885             long mem = (long)(memWeight * 1024 / totalTime);
1886             pw.print(prefix);
1887             pw.print(label);
1888             pw.print(": ");
1889             DebugUtils.printSizeValue(pw, mem);
1890             pw.print(" (");
1891             pw.print(samples);
1892             pw.print(" samples)");
1893             pw.println();
1894             return curTotalMem + mem;
1895         }
1896         return curTotalMem;
1897     }
1898 
dumpTotalsLocked(PrintWriter pw, long now)1899     void dumpTotalsLocked(PrintWriter pw, long now) {
1900         pw.println("Run time Stats:");
1901         DumpUtils.dumpSingleTime(pw, "  ", mMemFactorDurations, mMemFactor, mStartTime, now);
1902         pw.println();
1903         pw.println("Memory usage:");
1904         TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
1905                 ALL_MEM_ADJ);
1906         computeTotalMemoryUse(totalMem, now);
1907         long totalPss = 0;
1908         totalPss = printMemoryCategory(pw, "  ", "Kernel ", totalMem.sysMemKernelWeight,
1909                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1910         totalPss = printMemoryCategory(pw, "  ", "Native ", totalMem.sysMemNativeWeight,
1911                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1912         for (int i=0; i<STATE_COUNT; i++) {
1913             // Skip restarting service state -- that is not actually a running process.
1914             if (i != STATE_SERVICE_RESTARTING) {
1915                 totalPss = printMemoryCategory(pw, "  ", DumpUtils.STATE_NAMES[i],
1916                         totalMem.processStateWeight[i], totalMem.totalTime, totalPss,
1917                         totalMem.processStateSamples[i]);
1918             }
1919         }
1920         totalPss = printMemoryCategory(pw, "  ", "Cached ", totalMem.sysMemCachedWeight,
1921                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1922         totalPss = printMemoryCategory(pw, "  ", "Free   ", totalMem.sysMemFreeWeight,
1923                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1924         totalPss = printMemoryCategory(pw, "  ", "Z-Ram  ", totalMem.sysMemZRamWeight,
1925                 totalMem.totalTime, totalPss, totalMem.sysMemSamples);
1926         pw.print("  TOTAL  : ");
1927         DebugUtils.printSizeValue(pw, totalPss);
1928         pw.println();
1929         printMemoryCategory(pw, "  ", DumpUtils.STATE_NAMES[STATE_SERVICE_RESTARTING],
1930                 totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss,
1931                 totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
1932         pw.println();
1933         pw.println("PSS collection stats:");
1934         pw.print("  Internal Single: ");
1935         pw.print(mInternalSinglePssCount);
1936         pw.print("x over ");
1937         TimeUtils.formatDuration(mInternalSinglePssTime, pw);
1938         pw.println();
1939         pw.print("  Internal All Procs (Memory Change): ");
1940         pw.print(mInternalAllMemPssCount);
1941         pw.print("x over ");
1942         TimeUtils.formatDuration(mInternalAllMemPssTime, pw);
1943         pw.println();
1944         pw.print("  Internal All Procs (Polling): ");
1945         pw.print(mInternalAllPollPssCount);
1946         pw.print("x over ");
1947         TimeUtils.formatDuration(mInternalAllPollPssTime, pw);
1948         pw.println();
1949         pw.print("  External: ");
1950         pw.print(mExternalPssCount);
1951         pw.print("x over ");
1952         TimeUtils.formatDuration(mExternalPssTime, pw);
1953         pw.println();
1954         pw.print("  External Slow: ");
1955         pw.print(mExternalSlowPssCount);
1956         pw.print("x over ");
1957         TimeUtils.formatDuration(mExternalSlowPssTime, pw);
1958         pw.println();
1959     }
1960 
dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, String prcLabel, int[] screenStates, int[] memStates, int[] procStates, int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly)1961     void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, String prcLabel,
1962             int[] screenStates, int[] memStates, int[] procStates,
1963             int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
1964         ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
1965                 procStates, sortProcStates, now, reqPackage, activeOnly);
1966         if (procs.size() > 0) {
1967             if (header != null) {
1968                 pw.println();
1969                 pw.println(header);
1970             }
1971             DumpUtils.dumpProcessSummaryLocked(pw, prefix, prcLabel, procs, screenStates, memStates,
1972                     sortProcStates, now, totalTime);
1973         }
1974     }
1975 
collectProcessesLocked(int[] screenStates, int[] memStates, int[] procStates, int sortProcStates[], long now, String reqPackage, boolean activeOnly)1976     public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
1977             int[] procStates, int sortProcStates[], long now, String reqPackage,
1978             boolean activeOnly) {
1979         final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
1980         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
1981                 mPackages.getMap();
1982         for (int ip=0; ip<pkgMap.size(); ip++) {
1983             final String pkgName = pkgMap.keyAt(ip);
1984             final SparseArray<LongSparseArray<PackageState>> procs = pkgMap.valueAt(ip);
1985             for (int iu=0; iu<procs.size(); iu++) {
1986                 final LongSparseArray<PackageState> vpkgs = procs.valueAt(iu);
1987                 final int NVERS = vpkgs.size();
1988                 for (int iv=0; iv<NVERS; iv++) {
1989                     final PackageState state = vpkgs.valueAt(iv);
1990                     final int NPROCS = state.mProcesses.size();
1991                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
1992                     for (int iproc=0; iproc<NPROCS; iproc++) {
1993                         final ProcessState proc = state.mProcesses.valueAt(iproc);
1994                         if (!pkgMatch && !reqPackage.equals(proc.getName())) {
1995                             continue;
1996                         }
1997                         if (activeOnly && !proc.isInUse()) {
1998                             continue;
1999                         }
2000                         foundProcs.add(proc.getCommonProcess());
2001                     }
2002                 }
2003             }
2004         }
2005         ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
2006         for (int i=0; i<foundProcs.size(); i++) {
2007             ProcessState proc = foundProcs.valueAt(i);
2008             if (proc.computeProcessTimeLocked(screenStates, memStates, procStates, now) > 0) {
2009                 outProcs.add(proc);
2010                 if (procStates != sortProcStates) {
2011                     proc.computeProcessTimeLocked(screenStates, memStates, sortProcStates, now);
2012                 }
2013             }
2014         }
2015         Collections.sort(outProcs, ProcessState.COMPARATOR);
2016         return outProcs;
2017     }
2018 
2019     /**
2020      * Prints checkin style stats dump.
2021      */
dumpCheckinLocked(PrintWriter pw, String reqPackage, int section)2022     public void dumpCheckinLocked(PrintWriter pw, String reqPackage, int section) {
2023         final long now = SystemClock.uptimeMillis();
2024         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
2025                 mPackages.getMap();
2026         pw.println("vers,5");
2027         pw.print("period,"); pw.print(mTimePeriodStartClockStr);
2028         pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(",");
2029         pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
2030         boolean partial = true;
2031         if ((mFlags&FLAG_SHUTDOWN) != 0) {
2032             pw.print(",shutdown");
2033             partial = false;
2034         }
2035         if ((mFlags&FLAG_SYSPROPS) != 0) {
2036             pw.print(",sysprops");
2037             partial = false;
2038         }
2039         if ((mFlags&FLAG_COMPLETE) != 0) {
2040             pw.print(",complete");
2041             partial = false;
2042         }
2043         if (partial) {
2044             pw.print(",partial");
2045         }
2046         if (mHasSwappedOutPss) {
2047             pw.print(",swapped-out-pss");
2048         }
2049         pw.println();
2050         pw.print("config,"); pw.println(mRuntime);
2051 
2052         if ((section & REPORT_PKG_STATS) != 0) {
2053             for (int ip = 0; ip < pkgMap.size(); ip++) {
2054                 final String pkgName = pkgMap.keyAt(ip);
2055                 if (reqPackage != null && !reqPackage.equals(pkgName)) {
2056                     continue;
2057                 }
2058                 final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
2059                 for (int iu = 0; iu < uids.size(); iu++) {
2060                     final int uid = uids.keyAt(iu);
2061                     final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
2062                     for (int iv = 0; iv < vpkgs.size(); iv++) {
2063                         final long vers = vpkgs.keyAt(iv);
2064                         final PackageState pkgState = vpkgs.valueAt(iv);
2065                         final int NPROCS = pkgState.mProcesses.size();
2066                         final int NSRVS = pkgState.mServices.size();
2067                         final int NASCS = pkgState.mAssociations.size();
2068                         if ((section & REPORT_PKG_PROC_STATS) != 0) {
2069                             for (int iproc = 0; iproc < NPROCS; iproc++) {
2070                                 ProcessState proc = pkgState.mProcesses.valueAt(iproc);
2071                                 proc.dumpPackageProcCheckin(pw, pkgName, uid, vers,
2072                                         pkgState.mProcesses.keyAt(iproc), now);
2073                             }
2074                         }
2075                         if ((section & REPORT_PKG_SVC_STATS) != 0) {
2076                             for (int isvc = 0; isvc < NSRVS; isvc++) {
2077                                 final String serviceName = DumpUtils.collapseString(pkgName,
2078                                         pkgState.mServices.keyAt(isvc));
2079                                 final ServiceState svc = pkgState.mServices.valueAt(isvc);
2080                                 svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now);
2081                             }
2082                         }
2083                         if ((section & REPORT_PKG_ASC_STATS) != 0) {
2084                             for (int iasc = 0; iasc < NASCS; iasc++) {
2085                                 final String associationName = DumpUtils.collapseString(pkgName,
2086                                         pkgState.mAssociations.keyAt(iasc));
2087                                 final AssociationState asc = pkgState.mAssociations.valueAt(iasc);
2088                                 asc.dumpTimesCheckin(pw, pkgName, uid, vers, associationName, now);
2089                             }
2090                         }
2091                     }
2092                 }
2093             }
2094         }
2095 
2096         if ((section & REPORT_PROC_STATS) != 0) {
2097             ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2098             for (int ip = 0; ip < procMap.size(); ip++) {
2099                 String procName = procMap.keyAt(ip);
2100                 SparseArray<ProcessState> uids = procMap.valueAt(ip);
2101                 for (int iu = 0; iu < uids.size(); iu++) {
2102                     final int uid = uids.keyAt(iu);
2103                     final ProcessState procState = uids.valueAt(iu);
2104                     procState.dumpProcCheckin(pw, procName, uid, now);
2105                 }
2106             }
2107         }
2108         pw.print("total");
2109         DumpUtils.dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor, mStartTime, now);
2110         pw.println();
2111         final int sysMemUsageCount = mSysMemUsage.getKeyCount();
2112         if (sysMemUsageCount > 0) {
2113             pw.print("sysmemusage");
2114             for (int i=0; i<sysMemUsageCount; i++) {
2115                 final int key = mSysMemUsage.getKeyAt(i);
2116                 final int type = SparseMappingTable.getIdFromKey(key);
2117                 pw.print(",");
2118                 DumpUtils.printProcStateTag(pw, type);
2119                 for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) {
2120                     if (j > SYS_MEM_USAGE_CACHED_MINIMUM) {
2121                         pw.print(":");
2122                     }
2123                     pw.print(mSysMemUsage.getValue(key, j));
2124                 }
2125             }
2126         }
2127         pw.println();
2128         TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ,
2129                 ALL_MEM_ADJ);
2130         computeTotalMemoryUse(totalMem, now);
2131         pw.print("weights,");
2132         pw.print(totalMem.totalTime);
2133         pw.print(",");
2134         pw.print(totalMem.sysMemCachedWeight);
2135         pw.print(":");
2136         pw.print(totalMem.sysMemSamples);
2137         pw.print(",");
2138         pw.print(totalMem.sysMemFreeWeight);
2139         pw.print(":");
2140         pw.print(totalMem.sysMemSamples);
2141         pw.print(",");
2142         pw.print(totalMem.sysMemZRamWeight);
2143         pw.print(":");
2144         pw.print(totalMem.sysMemSamples);
2145         pw.print(",");
2146         pw.print(totalMem.sysMemKernelWeight);
2147         pw.print(":");
2148         pw.print(totalMem.sysMemSamples);
2149         pw.print(",");
2150         pw.print(totalMem.sysMemNativeWeight);
2151         pw.print(":");
2152         pw.print(totalMem.sysMemSamples);
2153         for (int i=0; i<STATE_COUNT; i++) {
2154             pw.print(",");
2155             pw.print(totalMem.processStateWeight[i]);
2156             pw.print(":");
2157             pw.print(totalMem.processStateSamples[i]);
2158         }
2159         pw.println();
2160 
2161         final int NPAGETYPES = mPageTypeLabels.size();
2162         for (int i=0; i<NPAGETYPES; i++) {
2163             pw.print("availablepages,");
2164             pw.print(mPageTypeLabels.get(i));
2165             pw.print(",");
2166             pw.print(mPageTypeZones.get(i));
2167             pw.print(",");
2168             // Wasn't included in original output.
2169             //pw.print(mPageTypeNodes.get(i));
2170             //pw.print(",");
2171             final int[] sizes = mPageTypeSizes.get(i);
2172             final int N = sizes == null ? 0 : sizes.length;
2173             for (int j=0; j<N; j++) {
2174                 if (j != 0) {
2175                     pw.print(",");
2176                 }
2177                 pw.print(sizes[j]);
2178             }
2179             pw.println();
2180         }
2181     }
2182 
2183     /**
2184      * Writes to ProtoOutputStream.
2185      */
dumpDebug(ProtoOutputStream proto, long now, int section)2186     public void dumpDebug(ProtoOutputStream proto, long now, int section) {
2187         dumpProtoPreamble(proto);
2188 
2189         final int NPAGETYPES = mPageTypeLabels.size();
2190         for (int i = 0; i < NPAGETYPES; i++) {
2191             final long token = proto.start(ProcessStatsSectionProto.AVAILABLE_PAGES);
2192             proto.write(ProcessStatsAvailablePagesProto.NODE, mPageTypeNodes.get(i));
2193             proto.write(ProcessStatsAvailablePagesProto.ZONE, mPageTypeZones.get(i));
2194             proto.write(ProcessStatsAvailablePagesProto.LABEL, mPageTypeLabels.get(i));
2195             final int[] sizes = mPageTypeSizes.get(i);
2196             final int N = sizes == null ? 0 : sizes.length;
2197             for (int j = 0; j < N; j++) {
2198                 proto.write(ProcessStatsAvailablePagesProto.PAGES_PER_ORDER, sizes[j]);
2199             }
2200             proto.end(token);
2201         }
2202 
2203         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2204         if ((section & REPORT_PROC_STATS) != 0) {
2205             for (int ip = 0; ip < procMap.size(); ip++) {
2206                 final String procName = procMap.keyAt(ip);
2207                 final SparseArray<ProcessState> uids = procMap.valueAt(ip);
2208                 for (int iu = 0; iu < uids.size(); iu++) {
2209                     final int uid = uids.keyAt(iu);
2210                     final ProcessState procState = uids.valueAt(iu);
2211                     procState.dumpDebug(proto, ProcessStatsSectionProto.PROCESS_STATS, procName,
2212                             uid, now);
2213                 }
2214             }
2215         }
2216 
2217         if ((section & REPORT_PKG_STATS) != 0) {
2218             final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
2219                     mPackages.getMap();
2220             for (int ip = 0; ip < pkgMap.size(); ip++) {
2221                 final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
2222                 for (int iu = 0; iu < uids.size(); iu++) {
2223                     final LongSparseArray<PackageState> vers = uids.valueAt(iu);
2224                     for (int iv = 0; iv < vers.size(); iv++) {
2225                         final PackageState pkgState = vers.valueAt(iv);
2226                         pkgState.dumpDebug(proto, ProcessStatsSectionProto.PACKAGE_STATS, now,
2227                                 section);
2228                     }
2229                 }
2230             }
2231         }
2232     }
2233 
2234     /** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
dumpAggregatedProtoForStatsd(ProtoOutputStream[] protoStreams, long maxRawShardSizeBytes)2235     public void dumpAggregatedProtoForStatsd(ProtoOutputStream[] protoStreams,
2236             long maxRawShardSizeBytes) {
2237         int shardIndex = 0;
2238         dumpProtoPreamble(protoStreams[shardIndex]);
2239 
2240         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
2241         final ProcessMap<ArraySet<PackageState>> procToPkgMap = new ProcessMap<>();
2242         final SparseArray<ArraySet<String>> uidToPkgMap = new SparseArray<>();
2243         collectProcessPackageMaps(null, false, procToPkgMap, uidToPkgMap);
2244 
2245         for (int ip = 0; ip < procMap.size(); ip++) {
2246             final String procName = procMap.keyAt(ip);
2247             if (protoStreams[shardIndex].getRawSize() > maxRawShardSizeBytes) {
2248                 shardIndex++;
2249                 if (shardIndex >= protoStreams.length) {
2250                     // We have run out of space; we'll drop the rest of the processes.
2251                     Slog.d(TAG, String.format("Dropping process indices from %d to %d from "
2252                             + "statsd proto (too large)", ip, procMap.size()));
2253                     break;
2254                 }
2255                 dumpProtoPreamble(protoStreams[shardIndex]);
2256             }
2257 
2258             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
2259             for (int iu = 0; iu < uids.size(); iu++) {
2260                 final int uid = uids.keyAt(iu);
2261                 final ProcessState procState = uids.valueAt(iu);
2262                 procState.dumpAggregatedProtoForStatsd(protoStreams[shardIndex],
2263                         ProcessStatsSectionProto.PROCESS_STATS,
2264                         procName, uid, mTimePeriodEndRealtime,
2265                         procToPkgMap, uidToPkgMap);
2266             }
2267         }
2268 
2269         for (int i = 0; i <= shardIndex; i++) {
2270             protoStreams[i].flush();
2271         }
2272     }
2273 
dumpProtoPreamble(ProtoOutputStream proto)2274     private void dumpProtoPreamble(ProtoOutputStream proto) {
2275         proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
2276         proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
2277                 mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
2278         proto.write(ProcessStatsSectionProto.START_UPTIME_MS, mTimePeriodStartUptime);
2279         proto.write(ProcessStatsSectionProto.END_UPTIME_MS, mTimePeriodEndUptime);
2280         proto.write(ProcessStatsSectionProto.RUNTIME, mRuntime);
2281         proto.write(ProcessStatsSectionProto.HAS_SWAPPED_PSS, mHasSwappedOutPss);
2282         boolean partial = true;
2283         if ((mFlags & FLAG_SHUTDOWN) != 0) {
2284             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SHUTDOWN);
2285             partial = false;
2286         }
2287         if ((mFlags & FLAG_SYSPROPS) != 0) {
2288             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SYSPROPS);
2289             partial = false;
2290         }
2291         if ((mFlags & FLAG_COMPLETE) != 0) {
2292             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_COMPLETE);
2293             partial = false;
2294         }
2295         if (partial) {
2296             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
2297         }
2298     }
2299 
2300     /**
2301      * Walk through the known processes and build up the process -> packages map if necessary.
2302      */
collectProcessPackageMaps(String reqPackage, boolean activeOnly, final ProcessMap<ArraySet<PackageState>> procToPkgMap, final SparseArray<ArraySet<String>> uidToPkgMap)2303     private void collectProcessPackageMaps(String reqPackage, boolean activeOnly,
2304             final ProcessMap<ArraySet<PackageState>> procToPkgMap,
2305             final SparseArray<ArraySet<String>> uidToPkgMap) {
2306         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
2307                 mPackages.getMap();
2308         for (int ip = pkgMap.size() - 1; ip >= 0; ip--) {
2309             final String pkgName = pkgMap.keyAt(ip);
2310             final SparseArray<LongSparseArray<PackageState>> procs = pkgMap.valueAt(ip);
2311             for (int iu = procs.size() - 1; iu >= 0; iu--) {
2312                 final LongSparseArray<PackageState> vpkgs = procs.valueAt(iu);
2313                 for (int iv = vpkgs.size() - 1; iv >= 0; iv--) {
2314                     final PackageState state = vpkgs.valueAt(iv);
2315                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
2316                     for (int iproc = state.mProcesses.size() - 1; iproc >= 0; iproc--) {
2317                         final ProcessState proc = state.mProcesses.valueAt(iproc);
2318                         if (!pkgMatch && !reqPackage.equals(proc.getName())) {
2319                             continue;
2320                         }
2321                         if (activeOnly && !proc.isInUse()) {
2322                             continue;
2323                         }
2324 
2325                         final String name = proc.getName();
2326                         final int uid = proc.getUid();
2327                         ArraySet<PackageState> pkgStates = procToPkgMap.get(name, uid);
2328                         if (pkgStates == null) {
2329                             pkgStates = new ArraySet<>();
2330                             procToPkgMap.put(name, uid, pkgStates);
2331                         }
2332                         pkgStates.add(state);
2333                         ArraySet<String> packages = uidToPkgMap.get(uid);
2334                         if (packages == null) {
2335                             packages = new ArraySet<>();
2336                             uidToPkgMap.put(uid, packages);
2337                         }
2338                         packages.add(state.mPackageName);
2339                     }
2340                 }
2341             }
2342         }
2343     }
2344 
2345     /**
2346      * Dump the association states related to given process into statsd.
2347      *
2348      * <p> Note: Only dump the single-package process state, or the common process state of
2349      * multi-package process; while the per-package process state of a multi-package process
2350      * should not be dumped into the statsd due to its incompletion.</p>
2351      *
2352      * @param proto     The proto output stream
2353      * @param fieldId   The proto output field ID
2354      * @param now       The timestamp when the dump was initiated.
2355      * @param procState The target process where its association states should be dumped.
2356      * @param proc2Pkg  The map between process to packages running within it.
2357      * @param uidToPkgMap The map between UID to packages with this UID
2358      */
dumpFilteredAssociationStatesProtoForProc(ProtoOutputStream proto, long fieldId, long now, ProcessState procState, final ProcessMap<ArraySet<PackageState>> proc2Pkg, final SparseArray<ArraySet<String>> uidToPkgMap)2359     public void dumpFilteredAssociationStatesProtoForProc(ProtoOutputStream proto,
2360             long fieldId, long now, ProcessState procState,
2361             final ProcessMap<ArraySet<PackageState>> proc2Pkg,
2362             final SparseArray<ArraySet<String>> uidToPkgMap) {
2363         if (procState.isMultiPackage() && procState.getCommonProcess() != procState) {
2364             // It's a per-package process state, don't bother to write into statsd
2365             return;
2366         }
2367         ArrayMap<SourceKey, long[]> assocVals = new ArrayMap<>();
2368         final String procName = procState.getName();
2369         final int procUid = procState.getUid();
2370         final long procVersion = procState.getVersion();
2371         final ArraySet<PackageState> packages = proc2Pkg.get(procName, procUid);
2372         if (packages == null || packages.isEmpty()) {
2373             // Shouldn't happen
2374             return;
2375         }
2376         for (int i = packages.size() - 1; i >= 0; i--) {
2377             final PackageState pkgState = packages.valueAt(i);
2378             final ArrayMap<String, AssociationState> associations = pkgState.mAssociations;
2379             for (int j = associations.size() - 1; j >= 0; j--) {
2380                 final AssociationState assoc = associations.valueAt(j);
2381                 // Make sure this association is really about this process
2382                 if (!TextUtils.equals(assoc.getProcessName(), procName)) {
2383                     continue;
2384                 }
2385                 final ArrayMap<SourceKey, SourceState> sources = assoc.mSources;
2386                 for (int k = sources.size() - 1; k >= 0; k--) {
2387                     final SourceKey key = sources.keyAt(k);
2388                     final SourceState state = sources.valueAt(k);
2389                     long[] vals = assocVals.get(key);
2390                     if (vals == null) {
2391                         vals = new long[2];
2392                         assocVals.put(key, vals);
2393                     }
2394                     vals[0] += state.mDuration;
2395                     vals[1] += state.mCount;
2396                     if (state.mNesting > 0) {
2397                         vals[0] += now - state.mStartUptime;
2398                     }
2399                 }
2400             }
2401         }
2402         final IProcessStats procStatsService = IProcessStats.Stub.asInterface(
2403                 ServiceManager.getService(SERVICE_NAME));
2404         if (procStatsService != null) {
2405             try {
2406                 final long minimum = procStatsService.getMinAssociationDumpDuration();
2407                 if (minimum > 0) {
2408                     // Now filter out unnecessary ones.
2409                     for (int i = assocVals.size() - 1; i >= 0; i--) {
2410                         final long[] vals = assocVals.valueAt(i);
2411                         if (vals[0] < minimum) {
2412                             assocVals.removeAt(i);
2413                         }
2414                     }
2415                 }
2416             } catch (RemoteException e) {
2417                 // ignore.
2418             }
2419         }
2420         if (!assocVals.isEmpty()) {
2421             for (int i = assocVals.size() - 1; i >= 0; i--) {
2422                 final SourceKey key = assocVals.keyAt(i);
2423                 final long[] vals = assocVals.valueAt(i);
2424                 final long token = proto.start(fieldId);
2425                 final int idx = uidToPkgMap.indexOfKey(key.mUid);
2426                 ProcessState.writeCompressedProcessName(proto,
2427                         ProcessStatsAssociationProto.ASSOC_PROCESS_NAME,
2428                         key.mProcess, key.mPackage,
2429                         idx >= 0 && uidToPkgMap.valueAt(idx).size() > 1);
2430                 proto.write(ProcessStatsAssociationProto.ASSOC_UID, key.mUid);
2431                 proto.write(ProcessStatsAssociationProto.TOTAL_COUNT, (int) vals[1]);
2432                 proto.write(ProcessStatsAssociationProto.TOTAL_DURATION_SECS,
2433                         (int) (vals[0] / 1000));
2434                 proto.end(token);
2435             }
2436         }
2437     }
2438 
2439     final public static class ProcessStateHolder {
2440         public final long appVersion;
2441         public ProcessState state;
2442         public PackageState pkg;
2443 
ProcessStateHolder(long _appVersion)2444         public ProcessStateHolder(long _appVersion) {
2445             appVersion = _appVersion;
2446         }
2447     }
2448 
2449     public static final class PackageState {
2450         public final ProcessStats mProcessStats;
2451         public final ArrayMap<String, ProcessState> mProcesses = new ArrayMap<>();
2452         public final ArrayMap<String, ServiceState> mServices = new ArrayMap<>();
2453         public final ArrayMap<String, AssociationState> mAssociations = new ArrayMap<>();
2454         public final String mPackageName;
2455         public final int mUid;
2456         public final long mVersionCode;
2457 
PackageState(ProcessStats procStats, String packageName, int uid, long versionCode)2458         public PackageState(ProcessStats procStats, String packageName, int uid, long versionCode) {
2459             mProcessStats = procStats;
2460             mUid = uid;
2461             mPackageName = packageName;
2462             mVersionCode = versionCode;
2463         }
2464 
getAssociationStateLocked(ProcessState proc, String className)2465         public AssociationState getAssociationStateLocked(ProcessState proc, String className) {
2466             AssociationState as = mAssociations.get(className);
2467             if (as != null) {
2468                 if (DEBUG) Slog.d(TAG, "GETASC: returning existing " + as);
2469                 if (proc != null) {
2470                     as.setProcess(proc);
2471                 }
2472                 return as;
2473             }
2474             as = new AssociationState(mProcessStats, this, className, proc.getName(),
2475                     proc);
2476             mAssociations.put(className, as);
2477             if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + proc.getName());
2478             return as;
2479         }
2480 
2481         /**
2482          * Writes the containing stats into proto, with options to choose smaller sections.
2483          */
dumpDebug(ProtoOutputStream proto, long fieldId, long now, int section)2484         public void dumpDebug(ProtoOutputStream proto, long fieldId, long now, int section) {
2485             final long token = proto.start(fieldId);
2486 
2487             proto.write(ProcessStatsPackageProto.PACKAGE, mPackageName);
2488             proto.write(ProcessStatsPackageProto.UID, mUid);
2489             proto.write(ProcessStatsPackageProto.VERSION, mVersionCode);
2490 
2491             if ((section & ProcessStats.REPORT_PKG_PROC_STATS) != 0) {
2492                 for (int ip = 0; ip < mProcesses.size(); ip++) {
2493                     final String procName = mProcesses.keyAt(ip);
2494                     final ProcessState procState = mProcesses.valueAt(ip);
2495                     procState.dumpDebug(proto, ProcessStatsPackageProto.PROCESS_STATS, procName,
2496                             mUid, now);
2497                 }
2498             }
2499 
2500             if ((section & ProcessStats.REPORT_PKG_SVC_STATS) != 0) {
2501                 for (int is = 0; is < mServices.size(); is++) {
2502                     final ServiceState serviceState = mServices.valueAt(is);
2503                     serviceState.dumpDebug(proto, ProcessStatsPackageProto.SERVICE_STATS,
2504                             now);
2505                 }
2506             }
2507 
2508             if ((section & ProcessStats.REPORT_PKG_ASC_STATS) != 0) {
2509                 for (int ia = 0; ia < mAssociations.size(); ia++) {
2510                     final AssociationState ascState = mAssociations.valueAt(ia);
2511                     ascState.dumpDebug(proto, ProcessStatsPackageProto.ASSOCIATION_STATS,
2512                             now);
2513                 }
2514             }
2515 
2516             proto.end(token);
2517         }
2518     }
2519 
2520     public static final class ProcessDataCollection {
2521         final int[] screenStates;
2522         final int[] memStates;
2523         final int[] procStates;
2524 
2525         public long totalTime;
2526         public long numPss;
2527         public long minPss;
2528         public long avgPss;
2529         public long maxPss;
2530         public long minUss;
2531         public long avgUss;
2532         public long maxUss;
2533         public long minRss;
2534         public long avgRss;
2535         public long maxRss;
2536 
ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates)2537         public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
2538             screenStates = _screenStates;
2539             memStates = _memStates;
2540             procStates = _procStates;
2541         }
2542 
print(PrintWriter pw, long overallTime, boolean full)2543         void print(PrintWriter pw, long overallTime, boolean full) {
2544             if (totalTime > overallTime) {
2545                 pw.print("*");
2546             }
2547             DumpUtils.printPercent(pw, (double) totalTime / (double) overallTime);
2548             if (numPss > 0) {
2549                 pw.print(" (");
2550                 DebugUtils.printSizeValue(pw, minPss * 1024);
2551                 pw.print("-");
2552                 DebugUtils.printSizeValue(pw, avgPss * 1024);
2553                 pw.print("-");
2554                 DebugUtils.printSizeValue(pw, maxPss * 1024);
2555                 pw.print("/");
2556                 DebugUtils.printSizeValue(pw, minUss * 1024);
2557                 pw.print("-");
2558                 DebugUtils.printSizeValue(pw, avgUss * 1024);
2559                 pw.print("-");
2560                 DebugUtils.printSizeValue(pw, maxUss * 1024);
2561                 pw.print("/");
2562                 DebugUtils.printSizeValue(pw, minRss * 1024);
2563                 pw.print("-");
2564                 DebugUtils.printSizeValue(pw, avgRss * 1024);
2565                 pw.print("-");
2566                 DebugUtils.printSizeValue(pw, maxRss * 1024);
2567                 if (full) {
2568                     pw.print(" over ");
2569                     pw.print(numPss);
2570                 }
2571                 pw.print(")");
2572             }
2573         }
2574     }
2575 
2576     public static class TotalMemoryUseCollection {
2577         final int[] screenStates;
2578         final int[] memStates;
2579 
TotalMemoryUseCollection(int[] _screenStates, int[] _memStates)2580         public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) {
2581             screenStates = _screenStates;
2582             memStates = _memStates;
2583         }
2584 
2585         public long totalTime;
2586         public long[] processStatePss = new long[STATE_COUNT];
2587         public double[] processStateWeight = new double[STATE_COUNT];
2588         public long[] processStateTime = new long[STATE_COUNT];
2589         public int[] processStateSamples = new int[STATE_COUNT];
2590         public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT];
2591         public double sysMemCachedWeight;
2592         public double sysMemFreeWeight;
2593         public double sysMemZRamWeight;
2594         public double sysMemKernelWeight;
2595         public double sysMemNativeWeight;
2596         public int sysMemSamples;
2597         public boolean hasSwappedOutPss;
2598     }
2599 
2600 }
2601