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