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