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