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