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