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