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