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