ProcessStats.java revision 25e1ecaabbde4741663c8e5a777d9df9b939572c
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 17package com.android.internal.app; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21import android.os.SystemClock; 22import android.os.SystemProperties; 23import android.os.UserHandle; 24import android.text.format.DateFormat; 25import android.util.ArrayMap; 26import android.util.ArraySet; 27import android.util.Log; 28import android.util.Slog; 29import android.util.SparseArray; 30import android.util.TimeUtils; 31 32import com.android.internal.util.GrowingArrayUtils; 33 34import dalvik.system.VMRuntime; 35import libcore.util.EmptyArray; 36 37import java.io.IOException; 38import java.io.InputStream; 39import java.io.PrintWriter; 40import java.util.ArrayList; 41import java.util.Arrays; 42import java.util.Collections; 43import java.util.Comparator; 44import java.util.Objects; 45 46public final class ProcessStats implements Parcelable { 47 static final String TAG = "ProcessStats"; 48 static final boolean DEBUG = false; 49 static final boolean DEBUG_PARCEL = false; 50 51 public static final String SERVICE_NAME = "procstats"; 52 53 // How often the service commits its data, giving the minimum batching 54 // that is done. 55 public static long COMMIT_PERIOD = 3*60*60*1000; // Commit current stats every 3 hours 56 57 // Minimum uptime period before committing. If the COMMIT_PERIOD has elapsed but 58 // the total uptime has not exceeded this amount, then the commit will be held until 59 // it is reached. 60 public static long COMMIT_UPTIME_PERIOD = 60*60*1000; // Must have at least 1 hour elapsed 61 62 public static final int STATE_NOTHING = -1; 63 public static final int STATE_PERSISTENT = 0; 64 public static final int STATE_TOP = 1; 65 public static final int STATE_IMPORTANT_FOREGROUND = 2; 66 public static final int STATE_IMPORTANT_BACKGROUND = 3; 67 public static final int STATE_BACKUP = 4; 68 public static final int STATE_HEAVY_WEIGHT = 5; 69 public static final int STATE_SERVICE = 6; 70 public static final int STATE_SERVICE_RESTARTING = 7; 71 public static final int STATE_RECEIVER = 8; 72 public static final int STATE_HOME = 9; 73 public static final int STATE_LAST_ACTIVITY = 10; 74 public static final int STATE_CACHED_ACTIVITY = 11; 75 public static final int STATE_CACHED_ACTIVITY_CLIENT = 12; 76 public static final int STATE_CACHED_EMPTY = 13; 77 public static final int STATE_COUNT = STATE_CACHED_EMPTY+1; 78 79 public static final int PSS_SAMPLE_COUNT = 0; 80 public static final int PSS_MINIMUM = 1; 81 public static final int PSS_AVERAGE = 2; 82 public static final int PSS_MAXIMUM = 3; 83 public static final int PSS_USS_MINIMUM = 4; 84 public static final int PSS_USS_AVERAGE = 5; 85 public static final int PSS_USS_MAXIMUM = 6; 86 public static final int PSS_COUNT = PSS_USS_MAXIMUM+1; 87 88 public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0; 89 public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1; 90 public static final int SYS_MEM_USAGE_CACHED_AVERAGE = 2; 91 public static final int SYS_MEM_USAGE_CACHED_MAXIMUM = 3; 92 public static final int SYS_MEM_USAGE_FREE_MINIMUM = 4; 93 public static final int SYS_MEM_USAGE_FREE_AVERAGE = 5; 94 public static final int SYS_MEM_USAGE_FREE_MAXIMUM = 6; 95 public static final int SYS_MEM_USAGE_ZRAM_MINIMUM = 7; 96 public static final int SYS_MEM_USAGE_ZRAM_AVERAGE = 8; 97 public static final int SYS_MEM_USAGE_ZRAM_MAXIMUM = 9; 98 public static final int SYS_MEM_USAGE_KERNEL_MINIMUM = 10; 99 public static final int SYS_MEM_USAGE_KERNEL_AVERAGE = 11; 100 public static final int SYS_MEM_USAGE_KERNEL_MAXIMUM = 12; 101 public static final int SYS_MEM_USAGE_NATIVE_MINIMUM = 13; 102 public static final int SYS_MEM_USAGE_NATIVE_AVERAGE = 14; 103 public static final int SYS_MEM_USAGE_NATIVE_MAXIMUM = 15; 104 public static final int SYS_MEM_USAGE_COUNT = SYS_MEM_USAGE_NATIVE_MAXIMUM+1; 105 106 public static final int ADJ_NOTHING = -1; 107 public static final int ADJ_MEM_FACTOR_NORMAL = 0; 108 public static final int ADJ_MEM_FACTOR_MODERATE = 1; 109 public static final int ADJ_MEM_FACTOR_LOW = 2; 110 public static final int ADJ_MEM_FACTOR_CRITICAL = 3; 111 public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1; 112 public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT; 113 public static final int ADJ_SCREEN_OFF = 0; 114 public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD; 115 public static final int ADJ_COUNT = ADJ_SCREEN_ON*2; 116 117 public static final int FLAG_COMPLETE = 1<<0; 118 public static final int FLAG_SHUTDOWN = 1<<1; 119 public static final int FLAG_SYSPROPS = 1<<2; 120 121 public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL, 122 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL }; 123 124 public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON }; 125 126 public static final int[] NON_CACHED_PROC_STATES = new int[] { 127 STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND, 128 STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT, 129 STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER 130 }; 131 132 public static final int[] BACKGROUND_PROC_STATES = new int[] { 133 STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, 134 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER 135 }; 136 137 // Map from process states to the states we track. 138 static final int[] PROCESS_STATE_TO_STATE = new int[] { 139 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT 140 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI 141 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP 142 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND 143 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 144 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP 145 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT 146 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE 147 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER 148 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME 149 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY 150 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY 151 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT 152 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY 153 }; 154 155 public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT, 156 STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, 157 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER, 158 STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY, 159 STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY 160 }; 161 162 static final String[] STATE_NAMES = new String[] { 163 "Persist", "Top ", "ImpFg ", "ImpBg ", 164 "Backup ", "HeavyWt", "Service", "ServRst", 165 "Receivr", "Home ", 166 "LastAct", "CchAct ", "CchCAct", "CchEmty" 167 }; 168 169 public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] { 170 "off", "on" 171 }; 172 173 public static final String[] ADJ_MEM_NAMES_CSV = new String[] { 174 "norm", "mod", "low", "crit" 175 }; 176 177 public static final String[] STATE_NAMES_CSV = new String[] { 178 "pers", "top", "impfg", "impbg", "backup", "heavy", 179 "service", "service-rs", "receiver", "home", "lastact", 180 "cch-activity", "cch-aclient", "cch-empty" 181 }; 182 183 static final String[] ADJ_SCREEN_TAGS = new String[] { 184 "0", "1" 185 }; 186 187 static final String[] ADJ_MEM_TAGS = new String[] { 188 "n", "m", "l", "c" 189 }; 190 191 static final String[] STATE_TAGS = new String[] { 192 "p", "t", "f", "b", "u", "w", 193 "s", "x", "r", "h", "l", "a", "c", "e" 194 }; 195 196 static final String CSV_SEP = "\t"; 197 198 // Current version of the parcel format. 199 private static final int PARCEL_VERSION = 18; 200 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 201 private static final int MAGIC = 0x50535453; 202 203 // Where the "type"/"state" part of the data appears in an offset integer. 204 static int OFFSET_TYPE_SHIFT = 0; 205 static int OFFSET_TYPE_MASK = 0xff; 206 // Where the "which array" part of the data appears in an offset integer. 207 static int OFFSET_ARRAY_SHIFT = 8; 208 static int OFFSET_ARRAY_MASK = 0xff; 209 // Where the "index into array" part of the data appears in an offset integer. 210 static int OFFSET_INDEX_SHIFT = 16; 211 static int OFFSET_INDEX_MASK = 0xffff; 212 213 public String mReadError; 214 public String mTimePeriodStartClockStr; 215 public int mFlags; 216 217 public final ProcessMap<SparseArray<PackageState>> mPackages 218 = new ProcessMap<SparseArray<PackageState>>(); 219 public final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>(); 220 221 public final long[] mMemFactorDurations = new long[ADJ_COUNT]; 222 public int mMemFactor = STATE_NOTHING; 223 public long mStartTime; 224 225 public int[] mSysMemUsageTable = null; 226 public int mSysMemUsageTableSize = 0; 227 public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT]; 228 229 public long mTimePeriodStartClock; 230 public long mTimePeriodStartRealtime; 231 public long mTimePeriodEndRealtime; 232 public long mTimePeriodStartUptime; 233 public long mTimePeriodEndUptime; 234 String mRuntime; 235 boolean mRunning; 236 237 static final int LONGS_SIZE = 4096; 238 final ArrayList<long[]> mLongs = new ArrayList<long[]>(); 239 int mNextLong; 240 241 int[] mAddLongTable; 242 int mAddLongTableSize; 243 244 // For writing parcels. 245 ArrayMap<String, Integer> mCommonStringToIndex; 246 247 // For reading parcels. 248 ArrayList<String> mIndexToCommonString; 249 250 public ProcessStats(boolean running) { 251 mRunning = running; 252 reset(); 253 } 254 255 public ProcessStats(Parcel in) { 256 reset(); 257 readFromParcel(in); 258 } 259 260 public void add(ProcessStats other) { 261 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = other.mPackages.getMap(); 262 for (int ip=0; ip<pkgMap.size(); ip++) { 263 final String pkgName = pkgMap.keyAt(ip); 264 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 265 for (int iu=0; iu<uids.size(); iu++) { 266 final int uid = uids.keyAt(iu); 267 final SparseArray<PackageState> versions = uids.valueAt(iu); 268 for (int iv=0; iv<versions.size(); iv++) { 269 final int vers = versions.keyAt(iv); 270 final PackageState otherState = versions.valueAt(iv); 271 final int NPROCS = otherState.mProcesses.size(); 272 final int NSRVS = otherState.mServices.size(); 273 for (int iproc=0; iproc<NPROCS; iproc++) { 274 ProcessState otherProc = otherState.mProcesses.valueAt(iproc); 275 if (otherProc.mCommonProcess != otherProc) { 276 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid 277 + " vers " + vers + " proc " + otherProc.mName); 278 ProcessState thisProc = getProcessStateLocked(pkgName, uid, vers, 279 otherProc.mName); 280 if (thisProc.mCommonProcess == thisProc) { 281 if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting"); 282 thisProc.mMultiPackage = true; 283 long now = SystemClock.uptimeMillis(); 284 final PackageState pkgState = getPackageStateLocked(pkgName, uid, 285 vers); 286 thisProc = thisProc.clone(thisProc.mPackage, now); 287 pkgState.mProcesses.put(thisProc.mName, thisProc); 288 } 289 thisProc.add(otherProc); 290 } 291 } 292 for (int isvc=0; isvc<NSRVS; isvc++) { 293 ServiceState otherSvc = otherState.mServices.valueAt(isvc); 294 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid 295 + " service " + otherSvc.mName); 296 ServiceState thisSvc = getServiceStateLocked(pkgName, uid, vers, 297 otherSvc.mProcessName, otherSvc.mName); 298 thisSvc.add(otherSvc); 299 } 300 } 301 } 302 } 303 304 ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap(); 305 for (int ip=0; ip<procMap.size(); ip++) { 306 SparseArray<ProcessState> uids = procMap.valueAt(ip); 307 for (int iu=0; iu<uids.size(); iu++) { 308 int uid = uids.keyAt(iu); 309 ProcessState otherProc = uids.valueAt(iu); 310 ProcessState thisProc = mProcesses.get(otherProc.mName, uid); 311 if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName); 312 if (thisProc == null) { 313 if (DEBUG) Slog.d(TAG, "Creating new process!"); 314 thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mVersion, 315 otherProc.mName); 316 mProcesses.put(otherProc.mName, uid, thisProc); 317 PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid, 318 otherProc.mVersion); 319 if (!thisState.mProcesses.containsKey(otherProc.mName)) { 320 thisState.mProcesses.put(otherProc.mName, thisProc); 321 } 322 } 323 thisProc.add(otherProc); 324 } 325 } 326 327 for (int i=0; i<ADJ_COUNT; i++) { 328 if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by " 329 + other.mMemFactorDurations[i] + " from " 330 + mMemFactorDurations[i]); 331 mMemFactorDurations[i] += other.mMemFactorDurations[i]; 332 } 333 334 for (int i=0; i<other.mSysMemUsageTableSize; i++) { 335 int ent = other.mSysMemUsageTable[i]; 336 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 337 long[] longs = other.mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 338 addSysMemUsage(state, longs, ((ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK)); 339 } 340 341 if (other.mTimePeriodStartClock < mTimePeriodStartClock) { 342 mTimePeriodStartClock = other.mTimePeriodStartClock; 343 mTimePeriodStartClockStr = other.mTimePeriodStartClockStr; 344 } 345 mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime; 346 mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime; 347 } 348 349 public void addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem, 350 long nativeMem) { 351 if (mMemFactor != STATE_NOTHING) { 352 int state = mMemFactor * STATE_COUNT; 353 mSysMemUsageArgs[SYS_MEM_USAGE_SAMPLE_COUNT] = 1; 354 for (int i=0; i<3; i++) { 355 mSysMemUsageArgs[SYS_MEM_USAGE_CACHED_MINIMUM + i] = cachedMem; 356 mSysMemUsageArgs[SYS_MEM_USAGE_FREE_MINIMUM + i] = freeMem; 357 mSysMemUsageArgs[SYS_MEM_USAGE_ZRAM_MINIMUM + i] = zramMem; 358 mSysMemUsageArgs[SYS_MEM_USAGE_KERNEL_MINIMUM + i] = kernelMem; 359 mSysMemUsageArgs[SYS_MEM_USAGE_NATIVE_MINIMUM + i] = nativeMem; 360 } 361 addSysMemUsage(state, mSysMemUsageArgs, 0); 362 } 363 } 364 365 void addSysMemUsage(int state, long[] data, int dataOff) { 366 int idx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, state); 367 int off; 368 if (idx >= 0) { 369 off = mSysMemUsageTable[idx]; 370 } else { 371 mAddLongTable = mSysMemUsageTable; 372 mAddLongTableSize = mSysMemUsageTableSize; 373 off = addLongData(~idx, state, SYS_MEM_USAGE_COUNT); 374 mSysMemUsageTable = mAddLongTable; 375 mSysMemUsageTableSize = mAddLongTableSize; 376 } 377 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 378 idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK; 379 addSysMemUsage(longs, idx, data, dataOff); 380 } 381 382 static void addSysMemUsage(long[] dstData, int dstOff, long[] addData, int addOff) { 383 final long dstCount = dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT]; 384 final long addCount = addData[addOff+SYS_MEM_USAGE_SAMPLE_COUNT]; 385 if (dstCount == 0) { 386 dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = addCount; 387 for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i++) { 388 dstData[dstOff+i] = addData[addOff+i]; 389 } 390 } else if (addCount > 0) { 391 dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = dstCount + addCount; 392 for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i+=3) { 393 if (dstData[dstOff+i] > addData[addOff+i]) { 394 dstData[dstOff+i] = addData[addOff+i]; 395 } 396 dstData[dstOff+i+1] = (long)( 397 ((dstData[dstOff+i+1]*(double)dstCount) 398 + (addData[addOff+i+1]*(double)addCount)) 399 / (dstCount+addCount) ); 400 if (dstData[dstOff+i+2] < addData[addOff+i+2]) { 401 dstData[dstOff+i+2] = addData[addOff+i+2]; 402 } 403 } 404 } 405 } 406 407 public static final Parcelable.Creator<ProcessStats> CREATOR 408 = new Parcelable.Creator<ProcessStats>() { 409 public ProcessStats createFromParcel(Parcel in) { 410 return new ProcessStats(in); 411 } 412 413 public ProcessStats[] newArray(int size) { 414 return new ProcessStats[size]; 415 } 416 }; 417 418 private static void printScreenLabel(PrintWriter pw, int offset) { 419 switch (offset) { 420 case ADJ_NOTHING: 421 pw.print(" "); 422 break; 423 case ADJ_SCREEN_OFF: 424 pw.print("SOff/"); 425 break; 426 case ADJ_SCREEN_ON: 427 pw.print("SOn /"); 428 break; 429 default: 430 pw.print("????/"); 431 break; 432 } 433 } 434 435 public static void printScreenLabelCsv(PrintWriter pw, int offset) { 436 switch (offset) { 437 case ADJ_NOTHING: 438 break; 439 case ADJ_SCREEN_OFF: 440 pw.print(ADJ_SCREEN_NAMES_CSV[0]); 441 break; 442 case ADJ_SCREEN_ON: 443 pw.print(ADJ_SCREEN_NAMES_CSV[1]); 444 break; 445 default: 446 pw.print("???"); 447 break; 448 } 449 } 450 451 private static void printMemLabel(PrintWriter pw, int offset, char sep) { 452 switch (offset) { 453 case ADJ_NOTHING: 454 pw.print(" "); 455 if (sep != 0) pw.print(' '); 456 break; 457 case ADJ_MEM_FACTOR_NORMAL: 458 pw.print("Norm"); 459 if (sep != 0) pw.print(sep); 460 break; 461 case ADJ_MEM_FACTOR_MODERATE: 462 pw.print("Mod "); 463 if (sep != 0) pw.print(sep); 464 break; 465 case ADJ_MEM_FACTOR_LOW: 466 pw.print("Low "); 467 if (sep != 0) pw.print(sep); 468 break; 469 case ADJ_MEM_FACTOR_CRITICAL: 470 pw.print("Crit"); 471 if (sep != 0) pw.print(sep); 472 break; 473 default: 474 pw.print("????"); 475 if (sep != 0) pw.print(sep); 476 break; 477 } 478 } 479 480 public static void printMemLabelCsv(PrintWriter pw, int offset) { 481 if (offset >= ADJ_MEM_FACTOR_NORMAL) { 482 if (offset <= ADJ_MEM_FACTOR_CRITICAL) { 483 pw.print(ADJ_MEM_NAMES_CSV[offset]); 484 } else { 485 pw.print("???"); 486 } 487 } 488 } 489 490 public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations, 491 int curState, long curStartTime, long now) { 492 long totalTime = 0; 493 int printedScreen = -1; 494 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) { 495 int printedMem = -1; 496 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) { 497 int state = imem+iscreen; 498 long time = durations[state]; 499 String running = ""; 500 if (curState == state) { 501 time += now - curStartTime; 502 if (pw != null) { 503 running = " (running)"; 504 } 505 } 506 if (time != 0) { 507 if (pw != null) { 508 pw.print(prefix); 509 printScreenLabel(pw, printedScreen != iscreen 510 ? iscreen : STATE_NOTHING); 511 printedScreen = iscreen; 512 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0); 513 printedMem = imem; 514 pw.print(": "); 515 TimeUtils.formatDuration(time, pw); pw.println(running); 516 } 517 totalTime += time; 518 } 519 } 520 } 521 if (totalTime != 0 && pw != null) { 522 pw.print(prefix); 523 pw.print(" TOTAL: "); 524 TimeUtils.formatDuration(totalTime, pw); 525 pw.println(); 526 } 527 return totalTime; 528 } 529 530 static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations, 531 int curState, long curStartTime, long now) { 532 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) { 533 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) { 534 int state = imem+iscreen; 535 long time = durations[state]; 536 if (curState == state) { 537 time += now - curStartTime; 538 } 539 if (time != 0) { 540 printAdjTagAndValue(pw, state, time); 541 } 542 } 543 } 544 } 545 546 static void dumpServiceTimeCheckin(PrintWriter pw, String label, String packageName, 547 int uid, int vers, String serviceName, ServiceState svc, int serviceType, int opCount, 548 int curState, long curStartTime, long now) { 549 if (opCount <= 0) { 550 return; 551 } 552 pw.print(label); 553 pw.print(","); 554 pw.print(packageName); 555 pw.print(","); 556 pw.print(uid); 557 pw.print(","); 558 pw.print(vers); 559 pw.print(","); 560 pw.print(serviceName); 561 pw.print(","); 562 pw.print(opCount); 563 boolean didCurState = false; 564 for (int i=0; i<svc.mDurationsTableSize; i++) { 565 int off = svc.mDurationsTable[i]; 566 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 567 int memFactor = type / ServiceState.SERVICE_COUNT; 568 type %= ServiceState.SERVICE_COUNT; 569 if (type != serviceType) { 570 continue; 571 } 572 long time = svc.mStats.getLong(off, 0); 573 if (curState == memFactor) { 574 didCurState = true; 575 time += now - curStartTime; 576 } 577 printAdjTagAndValue(pw, memFactor, time); 578 } 579 if (!didCurState && curState != STATE_NOTHING) { 580 printAdjTagAndValue(pw, curState, now - curStartTime); 581 } 582 pw.println(); 583 } 584 585 public static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) { 586 data.totalTime = 0; 587 data.numPss = data.minPss = data.avgPss = data.maxPss = 588 data.minUss = data.avgUss = data.maxUss = 0; 589 for (int is=0; is<data.screenStates.length; is++) { 590 for (int im=0; im<data.memStates.length; im++) { 591 for (int ip=0; ip<data.procStates.length; ip++) { 592 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT) 593 + data.procStates[ip]; 594 data.totalTime += proc.getDuration(bucket, now); 595 long samples = proc.getPssSampleCount(bucket); 596 if (samples > 0) { 597 long minPss = proc.getPssMinimum(bucket); 598 long avgPss = proc.getPssAverage(bucket); 599 long maxPss = proc.getPssMaximum(bucket); 600 long minUss = proc.getPssUssMinimum(bucket); 601 long avgUss = proc.getPssUssAverage(bucket); 602 long maxUss = proc.getPssUssMaximum(bucket); 603 if (data.numPss == 0) { 604 data.minPss = minPss; 605 data.avgPss = avgPss; 606 data.maxPss = maxPss; 607 data.minUss = minUss; 608 data.avgUss = avgUss; 609 data.maxUss = maxUss; 610 } else { 611 if (minPss < data.minPss) { 612 data.minPss = minPss; 613 } 614 data.avgPss = (long)( ((data.avgPss*(double)data.numPss) 615 + (avgPss*(double)samples)) / (data.numPss+samples) ); 616 if (maxPss > data.maxPss) { 617 data.maxPss = maxPss; 618 } 619 if (minUss < data.minUss) { 620 data.minUss = minUss; 621 } 622 data.avgUss = (long)( ((data.avgUss*(double)data.numPss) 623 + (avgUss*(double)samples)) / (data.numPss+samples) ); 624 if (maxUss > data.maxUss) { 625 data.maxUss = maxUss; 626 } 627 } 628 data.numPss += samples; 629 } 630 } 631 } 632 } 633 } 634 635 static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates, 636 int[] procStates, long now) { 637 long totalTime = 0; 638 /* 639 for (int i=0; i<proc.mDurationsTableSize; i++) { 640 int val = proc.mDurationsTable[i]; 641 totalTime += proc.mState.getLong(val, 0); 642 if ((val&0xff) == proc.mCurState) { 643 totalTime += now - proc.mStartTime; 644 } 645 } 646 */ 647 for (int is=0; is<screenStates.length; is++) { 648 for (int im=0; im<memStates.length; im++) { 649 for (int ip=0; ip<procStates.length; ip++) { 650 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT) 651 + procStates[ip]; 652 totalTime += proc.getDuration(bucket, now); 653 } 654 } 655 } 656 proc.mTmpTotalTime = totalTime; 657 return totalTime; 658 } 659 660 static class PssAggr { 661 long pss = 0; 662 long samples = 0; 663 664 void add(long newPss, long newSamples) { 665 pss = (long)( (pss*(double)samples) + (newPss*(double)newSamples) ) 666 / (samples+newSamples); 667 samples += newSamples; 668 } 669 } 670 671 public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) { 672 data.totalTime = 0; 673 for (int i=0; i<STATE_COUNT; i++) { 674 data.processStateWeight[i] = 0; 675 data.processStatePss[i] = 0; 676 data.processStateTime[i] = 0; 677 data.processStateSamples[i] = 0; 678 } 679 for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) { 680 data.sysMemUsage[i] = 0; 681 } 682 data.sysMemCachedWeight = 0; 683 data.sysMemFreeWeight = 0; 684 data.sysMemZRamWeight = 0; 685 data.sysMemKernelWeight = 0; 686 data.sysMemNativeWeight = 0; 687 data.sysMemSamples = 0; 688 long[] totalMemUsage = new long[SYS_MEM_USAGE_COUNT]; 689 for (int i=0; i<mSysMemUsageTableSize; i++) { 690 int ent = mSysMemUsageTable[i]; 691 long[] longs = mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 692 int idx = (ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK; 693 addSysMemUsage(totalMemUsage, 0, longs, idx); 694 } 695 for (int is=0; is<data.screenStates.length; is++) { 696 for (int im=0; im<data.memStates.length; im++) { 697 int memBucket = data.screenStates[is] + data.memStates[im]; 698 int stateBucket = memBucket * STATE_COUNT; 699 long memTime = mMemFactorDurations[memBucket]; 700 if (mMemFactor == memBucket) { 701 memTime += now - mStartTime; 702 } 703 data.totalTime += memTime; 704 int sysIdx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, stateBucket); 705 long[] longs = totalMemUsage; 706 int idx = 0; 707 if (sysIdx >= 0) { 708 int ent = mSysMemUsageTable[sysIdx]; 709 long[] tmpLongs = mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 710 int tmpIdx = (ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK; 711 if (tmpLongs[tmpIdx+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) { 712 addSysMemUsage(data.sysMemUsage, 0, longs, idx); 713 longs = tmpLongs; 714 idx = tmpIdx; 715 } 716 } 717 data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE] 718 * (double)memTime; 719 data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE] 720 * (double)memTime; 721 data.sysMemZRamWeight += longs[idx+SYS_MEM_USAGE_ZRAM_AVERAGE] 722 * (double)memTime; 723 data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE] 724 * (double)memTime; 725 data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE] 726 * (double)memTime; 727 data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT]; 728 } 729 } 730 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 731 for (int iproc=0; iproc<procMap.size(); iproc++) { 732 SparseArray<ProcessState> uids = procMap.valueAt(iproc); 733 for (int iu=0; iu<uids.size(); iu++) { 734 final ProcessState proc = uids.valueAt(iu); 735 final PssAggr fgPss = new PssAggr(); 736 final PssAggr bgPss = new PssAggr(); 737 final PssAggr cachedPss = new PssAggr(); 738 boolean havePss = false; 739 for (int i=0; i<proc.mDurationsTableSize; i++) { 740 int off = proc.mDurationsTable[i]; 741 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 742 int procState = type % STATE_COUNT; 743 long samples = proc.getPssSampleCount(type); 744 if (samples > 0) { 745 long avg = proc.getPssAverage(type); 746 havePss = true; 747 if (procState <= STATE_IMPORTANT_FOREGROUND) { 748 fgPss.add(avg, samples); 749 } else if (procState <= STATE_RECEIVER) { 750 bgPss.add(avg, samples); 751 } else { 752 cachedPss.add(avg, samples); 753 } 754 } 755 } 756 if (!havePss) { 757 continue; 758 } 759 boolean fgHasBg = false; 760 boolean fgHasCached = false; 761 boolean bgHasCached = false; 762 if (fgPss.samples < 3 && bgPss.samples > 0) { 763 fgHasBg = true; 764 fgPss.add(bgPss.pss, bgPss.samples); 765 } 766 if (fgPss.samples < 3 && cachedPss.samples > 0) { 767 fgHasCached = true; 768 fgPss.add(cachedPss.pss, cachedPss.samples); 769 } 770 if (bgPss.samples < 3 && cachedPss.samples > 0) { 771 bgHasCached = true; 772 bgPss.add(cachedPss.pss, cachedPss.samples); 773 } 774 if (bgPss.samples < 3 && !fgHasBg && fgPss.samples > 0) { 775 bgPss.add(fgPss.pss, fgPss.samples); 776 } 777 if (cachedPss.samples < 3 && !bgHasCached && bgPss.samples > 0) { 778 cachedPss.add(bgPss.pss, bgPss.samples); 779 } 780 if (cachedPss.samples < 3 && !fgHasCached && fgPss.samples > 0) { 781 cachedPss.add(fgPss.pss, fgPss.samples); 782 } 783 for (int i=0; i<proc.mDurationsTableSize; i++) { 784 final int off = proc.mDurationsTable[i]; 785 final int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 786 long time = getLong(off, 0); 787 if (proc.mCurState == type) { 788 time += now - proc.mStartTime; 789 } 790 final int procState = type % STATE_COUNT; 791 data.processStateTime[procState] += time; 792 long samples = proc.getPssSampleCount(type); 793 long avg; 794 if (samples > 0) { 795 avg = proc.getPssAverage(type); 796 } else if (procState <= STATE_IMPORTANT_FOREGROUND) { 797 samples = fgPss.samples; 798 avg = fgPss.pss; 799 } else if (procState <= STATE_RECEIVER) { 800 samples = bgPss.samples; 801 avg = bgPss.pss; 802 } else { 803 samples = cachedPss.samples; 804 avg = cachedPss.pss; 805 } 806 double newAvg = ( (data.processStatePss[procState] 807 * (double)data.processStateSamples[procState]) 808 + (avg*(double)samples) 809 ) / (data.processStateSamples[procState]+samples); 810 data.processStatePss[procState] = (long)newAvg; 811 data.processStateSamples[procState] += samples; 812 data.processStateWeight[procState] += avg * (double)time; 813 } 814 } 815 } 816 } 817 818 static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc, 819 int[] screenStates, int[] memStates, int[] procStates, long now) { 820 long totalTime = 0; 821 int printedScreen = -1; 822 for (int is=0; is<screenStates.length; is++) { 823 int printedMem = -1; 824 for (int im=0; im<memStates.length; im++) { 825 for (int ip=0; ip<procStates.length; ip++) { 826 final int iscreen = screenStates[is]; 827 final int imem = memStates[im]; 828 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip]; 829 long time = proc.getDuration(bucket, now); 830 String running = ""; 831 if (proc.mCurState == bucket) { 832 running = " (running)"; 833 } 834 if (time != 0) { 835 pw.print(prefix); 836 if (screenStates.length > 1) { 837 printScreenLabel(pw, printedScreen != iscreen 838 ? iscreen : STATE_NOTHING); 839 printedScreen = iscreen; 840 } 841 if (memStates.length > 1) { 842 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/'); 843 printedMem = imem; 844 } 845 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": "); 846 TimeUtils.formatDuration(time, pw); pw.println(running); 847 totalTime += time; 848 } 849 } 850 } 851 } 852 if (totalTime != 0) { 853 pw.print(prefix); 854 if (screenStates.length > 1) { 855 printScreenLabel(pw, STATE_NOTHING); 856 } 857 if (memStates.length > 1) { 858 printMemLabel(pw, STATE_NOTHING, '/'); 859 } 860 pw.print("TOTAL : "); 861 TimeUtils.formatDuration(totalTime, pw); 862 pw.println(); 863 } 864 } 865 866 static void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates, 867 int[] memStates, int[] procStates) { 868 boolean printedHeader = false; 869 int printedScreen = -1; 870 for (int is=0; is<screenStates.length; is++) { 871 int printedMem = -1; 872 for (int im=0; im<memStates.length; im++) { 873 for (int ip=0; ip<procStates.length; ip++) { 874 final int iscreen = screenStates[is]; 875 final int imem = memStates[im]; 876 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip]; 877 long count = proc.getPssSampleCount(bucket); 878 if (count > 0) { 879 if (!printedHeader) { 880 pw.print(prefix); 881 pw.print("PSS/USS ("); 882 pw.print(proc.mPssTableSize); 883 pw.println(" entries):"); 884 printedHeader = true; 885 } 886 pw.print(prefix); 887 pw.print(" "); 888 if (screenStates.length > 1) { 889 printScreenLabel(pw, printedScreen != iscreen 890 ? iscreen : STATE_NOTHING); 891 printedScreen = iscreen; 892 } 893 if (memStates.length > 1) { 894 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/'); 895 printedMem = imem; 896 } 897 pw.print(STATE_NAMES[procStates[ip]]); pw.print(": "); 898 pw.print(count); 899 pw.print(" samples "); 900 printSizeValue(pw, proc.getPssMinimum(bucket) * 1024); 901 pw.print(" "); 902 printSizeValue(pw, proc.getPssAverage(bucket) * 1024); 903 pw.print(" "); 904 printSizeValue(pw, proc.getPssMaximum(bucket) * 1024); 905 pw.print(" / "); 906 printSizeValue(pw, proc.getPssUssMinimum(bucket) * 1024); 907 pw.print(" "); 908 printSizeValue(pw, proc.getPssUssAverage(bucket) * 1024); 909 pw.print(" "); 910 printSizeValue(pw, proc.getPssUssMaximum(bucket) * 1024); 911 pw.println(); 912 } 913 } 914 } 915 } 916 if (proc.mNumExcessiveWake != 0) { 917 pw.print(prefix); pw.print("Killed for excessive wake locks: "); 918 pw.print(proc.mNumExcessiveWake); pw.println(" times"); 919 } 920 if (proc.mNumExcessiveCpu != 0) { 921 pw.print(prefix); pw.print("Killed for excessive CPU use: "); 922 pw.print(proc.mNumExcessiveCpu); pw.println(" times"); 923 } 924 if (proc.mNumCachedKill != 0) { 925 pw.print(prefix); pw.print("Killed from cached state: "); 926 pw.print(proc.mNumCachedKill); pw.print(" times from pss "); 927 printSizeValue(pw, proc.mMinCachedKillPss * 1024); pw.print("-"); 928 printSizeValue(pw, proc.mAvgCachedKillPss * 1024); pw.print("-"); 929 printSizeValue(pw, proc.mMaxCachedKillPss * 1024); pw.println(); 930 } 931 } 932 933 long getSysMemUsageValue(int state, int index) { 934 int idx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, state); 935 return idx >= 0 ? getLong(mSysMemUsageTable[idx], index) : 0; 936 } 937 938 void dumpSysMemUsageCategory(PrintWriter pw, String prefix, String label, 939 int bucket, int index) { 940 pw.print(prefix); pw.print(label); 941 pw.print(": "); 942 printSizeValue(pw, getSysMemUsageValue(bucket, index) * 1024); 943 pw.print(" min, "); 944 printSizeValue(pw, getSysMemUsageValue(bucket, index + 1) * 1024); 945 pw.print(" avg, "); 946 printSizeValue(pw, getSysMemUsageValue(bucket, index+2) * 1024); 947 pw.println(" max"); 948 } 949 950 void dumpSysMemUsage(PrintWriter pw, String prefix, int[] screenStates, 951 int[] memStates) { 952 int printedScreen = -1; 953 for (int is=0; is<screenStates.length; is++) { 954 int printedMem = -1; 955 for (int im=0; im<memStates.length; im++) { 956 final int iscreen = screenStates[is]; 957 final int imem = memStates[im]; 958 final int bucket = ((iscreen + imem) * STATE_COUNT); 959 long count = getSysMemUsageValue(bucket, SYS_MEM_USAGE_SAMPLE_COUNT); 960 if (count > 0) { 961 pw.print(prefix); 962 if (screenStates.length > 1) { 963 printScreenLabel(pw, printedScreen != iscreen 964 ? iscreen : STATE_NOTHING); 965 printedScreen = iscreen; 966 } 967 if (memStates.length > 1) { 968 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '\0'); 969 printedMem = imem; 970 } 971 pw.print(": "); 972 pw.print(count); 973 pw.println(" samples:"); 974 dumpSysMemUsageCategory(pw, prefix, " Cached", bucket, 975 SYS_MEM_USAGE_CACHED_MINIMUM); 976 dumpSysMemUsageCategory(pw, prefix, " Free", bucket, 977 SYS_MEM_USAGE_FREE_MINIMUM); 978 dumpSysMemUsageCategory(pw, prefix, " ZRam", bucket, 979 SYS_MEM_USAGE_ZRAM_MINIMUM); 980 dumpSysMemUsageCategory(pw, prefix, " Kernel", bucket, 981 SYS_MEM_USAGE_KERNEL_MINIMUM); 982 dumpSysMemUsageCategory(pw, prefix, " Native", bucket, 983 SYS_MEM_USAGE_NATIVE_MINIMUM); 984 } 985 } 986 } 987 } 988 989 static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates, 990 int[] memStates, int[] procStates) { 991 final int NS = screenStates != null ? screenStates.length : 1; 992 final int NM = memStates != null ? memStates.length : 1; 993 final int NP = procStates != null ? procStates.length : 1; 994 for (int is=0; is<NS; is++) { 995 for (int im=0; im<NM; im++) { 996 for (int ip=0; ip<NP; ip++) { 997 pw.print(sep); 998 boolean printed = false; 999 if (screenStates != null && screenStates.length > 1) { 1000 printScreenLabelCsv(pw, screenStates[is]); 1001 printed = true; 1002 } 1003 if (memStates != null && memStates.length > 1) { 1004 if (printed) { 1005 pw.print("-"); 1006 } 1007 printMemLabelCsv(pw, memStates[im]); 1008 printed = true; 1009 } 1010 if (procStates != null && procStates.length > 1) { 1011 if (printed) { 1012 pw.print("-"); 1013 } 1014 pw.print(STATE_NAMES_CSV[procStates[ip]]); 1015 } 1016 } 1017 } 1018 } 1019 } 1020 1021 static void dumpProcessStateCsv(PrintWriter pw, ProcessState proc, 1022 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, 1023 boolean sepProcStates, int[] procStates, long now) { 1024 final int NSS = sepScreenStates ? screenStates.length : 1; 1025 final int NMS = sepMemStates ? memStates.length : 1; 1026 final int NPS = sepProcStates ? procStates.length : 1; 1027 for (int iss=0; iss<NSS; iss++) { 1028 for (int ims=0; ims<NMS; ims++) { 1029 for (int ips=0; ips<NPS; ips++) { 1030 final int vsscreen = sepScreenStates ? screenStates[iss] : 0; 1031 final int vsmem = sepMemStates ? memStates[ims] : 0; 1032 final int vsproc = sepProcStates ? procStates[ips] : 0; 1033 final int NSA = sepScreenStates ? 1 : screenStates.length; 1034 final int NMA = sepMemStates ? 1 : memStates.length; 1035 final int NPA = sepProcStates ? 1 : procStates.length; 1036 long totalTime = 0; 1037 for (int isa=0; isa<NSA; isa++) { 1038 for (int ima=0; ima<NMA; ima++) { 1039 for (int ipa=0; ipa<NPA; ipa++) { 1040 final int vascreen = sepScreenStates ? 0 : screenStates[isa]; 1041 final int vamem = sepMemStates ? 0 : memStates[ima]; 1042 final int vaproc = sepProcStates ? 0 : procStates[ipa]; 1043 final int bucket = ((vsscreen + vascreen + vsmem + vamem) 1044 * STATE_COUNT) + vsproc + vaproc; 1045 totalTime += proc.getDuration(bucket, now); 1046 } 1047 } 1048 } 1049 pw.print(CSV_SEP); 1050 pw.print(totalTime); 1051 } 1052 } 1053 } 1054 } 1055 1056 static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs, 1057 int[] screenStates, int[] memStates, int[] procStates, long now) { 1058 String innerPrefix = prefix + " "; 1059 for (int i=procs.size()-1; i>=0; i--) { 1060 ProcessState proc = procs.get(i); 1061 pw.print(prefix); 1062 pw.print(proc.mName); 1063 pw.print(" / "); 1064 UserHandle.formatUid(pw, proc.mUid); 1065 pw.print(" ("); 1066 pw.print(proc.mDurationsTableSize); 1067 pw.print(" entries)"); 1068 pw.println(":"); 1069 dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now); 1070 if (proc.mPssTableSize > 0) { 1071 dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates); 1072 } 1073 } 1074 } 1075 1076 static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix, 1077 String label, int[] screenStates, int[] memStates, int[] procStates, 1078 long now, long totalTime, boolean full) { 1079 ProcessDataCollection totals = new ProcessDataCollection(screenStates, 1080 memStates, procStates); 1081 computeProcessData(proc, totals, now); 1082 if (totals.totalTime != 0 || totals.numPss != 0) { 1083 if (prefix != null) { 1084 pw.print(prefix); 1085 } 1086 if (label != null) { 1087 pw.print(label); 1088 } 1089 totals.print(pw, totalTime, full); 1090 if (prefix != null) { 1091 pw.println(); 1092 } 1093 } 1094 } 1095 1096 static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, 1097 ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates, 1098 boolean inclUidVers, long now, long totalTime) { 1099 for (int i=procs.size()-1; i>=0; i--) { 1100 ProcessState proc = procs.get(i); 1101 pw.print(prefix); 1102 pw.print("* "); 1103 pw.print(proc.mName); 1104 pw.print(" / "); 1105 UserHandle.formatUid(pw, proc.mUid); 1106 pw.print(" / v"); 1107 pw.print(proc.mVersion); 1108 pw.println(":"); 1109 dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates, 1110 procStates, now, totalTime, true); 1111 dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates, 1112 new int[] { STATE_PERSISTENT }, now, totalTime, true); 1113 dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates, 1114 new int[] {STATE_TOP}, now, totalTime, true); 1115 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Fg: ", screenStates, memStates, 1116 new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true); 1117 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Bg: ", screenStates, memStates, 1118 new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true); 1119 dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates, 1120 new int[] {STATE_BACKUP}, now, totalTime, true); 1121 dumpProcessSummaryDetails(pw, proc, prefix, " Heavy Wgt: ", screenStates, memStates, 1122 new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true); 1123 dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates, 1124 new int[] {STATE_SERVICE}, now, totalTime, true); 1125 dumpProcessSummaryDetails(pw, proc, prefix, " Service Rs: ", screenStates, memStates, 1126 new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true); 1127 dumpProcessSummaryDetails(pw, proc, prefix, " Receiver: ", screenStates, memStates, 1128 new int[] {STATE_RECEIVER}, now, totalTime, true); 1129 dumpProcessSummaryDetails(pw, proc, prefix, " (Home): ", screenStates, memStates, 1130 new int[] {STATE_HOME}, now, totalTime, true); 1131 dumpProcessSummaryDetails(pw, proc, prefix, " (Last Act): ", screenStates, memStates, 1132 new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true); 1133 dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates, 1134 new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT, 1135 STATE_CACHED_EMPTY}, now, totalTime, true); 1136 } 1137 } 1138 1139 static void printPercent(PrintWriter pw, double fraction) { 1140 fraction *= 100; 1141 if (fraction < 1) { 1142 pw.print(String.format("%.2f", fraction)); 1143 } else if (fraction < 10) { 1144 pw.print(String.format("%.1f", fraction)); 1145 } else { 1146 pw.print(String.format("%.0f", fraction)); 1147 } 1148 pw.print("%"); 1149 } 1150 1151 static void printSizeValue(PrintWriter pw, long number) { 1152 float result = number; 1153 String suffix = ""; 1154 if (result > 900) { 1155 suffix = "KB"; 1156 result = result / 1024; 1157 } 1158 if (result > 900) { 1159 suffix = "MB"; 1160 result = result / 1024; 1161 } 1162 if (result > 900) { 1163 suffix = "GB"; 1164 result = result / 1024; 1165 } 1166 if (result > 900) { 1167 suffix = "TB"; 1168 result = result / 1024; 1169 } 1170 if (result > 900) { 1171 suffix = "PB"; 1172 result = result / 1024; 1173 } 1174 String value; 1175 if (result < 1) { 1176 value = String.format("%.2f", result); 1177 } else if (result < 10) { 1178 value = String.format("%.1f", result); 1179 } else if (result < 100) { 1180 value = String.format("%.0f", result); 1181 } else { 1182 value = String.format("%.0f", result); 1183 } 1184 pw.print(value); 1185 pw.print(suffix); 1186 } 1187 1188 public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs, 1189 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, 1190 boolean sepProcStates, int[] procStates, long now) { 1191 pw.print("process"); 1192 pw.print(CSV_SEP); 1193 pw.print("uid"); 1194 pw.print(CSV_SEP); 1195 pw.print("vers"); 1196 dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null, 1197 sepMemStates ? memStates : null, 1198 sepProcStates ? procStates : null); 1199 pw.println(); 1200 for (int i=procs.size()-1; i>=0; i--) { 1201 ProcessState proc = procs.get(i); 1202 pw.print(proc.mName); 1203 pw.print(CSV_SEP); 1204 UserHandle.formatUid(pw, proc.mUid); 1205 pw.print(CSV_SEP); 1206 pw.print(proc.mVersion); 1207 dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates, 1208 sepMemStates, memStates, sepProcStates, procStates, now); 1209 pw.println(); 1210 } 1211 } 1212 1213 static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) { 1214 int index = value/mod; 1215 if (index >= 0 && index < array.length) { 1216 pw.print(array[index]); 1217 } else { 1218 pw.print('?'); 1219 } 1220 return value - index*mod; 1221 } 1222 1223 static void printProcStateTag(PrintWriter pw, int state) { 1224 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT); 1225 state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT); 1226 printArrayEntry(pw, STATE_TAGS, state, 1); 1227 } 1228 1229 static void printAdjTag(PrintWriter pw, int state) { 1230 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD); 1231 printArrayEntry(pw, ADJ_MEM_TAGS, state, 1); 1232 } 1233 1234 static void printProcStateTagAndValue(PrintWriter pw, int state, long value) { 1235 pw.print(','); 1236 printProcStateTag(pw, state); 1237 pw.print(':'); 1238 pw.print(value); 1239 } 1240 1241 static void printAdjTagAndValue(PrintWriter pw, int state, long value) { 1242 pw.print(','); 1243 printAdjTag(pw, state); 1244 pw.print(':'); 1245 pw.print(value); 1246 } 1247 1248 static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) { 1249 boolean didCurState = false; 1250 for (int i=0; i<proc.mDurationsTableSize; i++) { 1251 int off = proc.mDurationsTable[i]; 1252 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 1253 long time = proc.mStats.getLong(off, 0); 1254 if (proc.mCurState == type) { 1255 didCurState = true; 1256 time += now - proc.mStartTime; 1257 } 1258 printProcStateTagAndValue(pw, type, time); 1259 } 1260 if (!didCurState && proc.mCurState != STATE_NOTHING) { 1261 printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime); 1262 } 1263 } 1264 1265 static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) { 1266 for (int i=0; i<proc.mPssTableSize; i++) { 1267 int off = proc.mPssTable[i]; 1268 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 1269 long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT); 1270 long min = proc.mStats.getLong(off, PSS_MINIMUM); 1271 long avg = proc.mStats.getLong(off, PSS_AVERAGE); 1272 long max = proc.mStats.getLong(off, PSS_MAXIMUM); 1273 long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM); 1274 long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE); 1275 long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM); 1276 pw.print(','); 1277 printProcStateTag(pw, type); 1278 pw.print(':'); 1279 pw.print(count); 1280 pw.print(':'); 1281 pw.print(min); 1282 pw.print(':'); 1283 pw.print(avg); 1284 pw.print(':'); 1285 pw.print(max); 1286 pw.print(':'); 1287 pw.print(umin); 1288 pw.print(':'); 1289 pw.print(uavg); 1290 pw.print(':'); 1291 pw.print(umax); 1292 } 1293 } 1294 1295 public void reset() { 1296 if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr); 1297 resetCommon(); 1298 mPackages.getMap().clear(); 1299 mProcesses.getMap().clear(); 1300 mMemFactor = STATE_NOTHING; 1301 mStartTime = 0; 1302 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr); 1303 } 1304 1305 public void resetSafely() { 1306 if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr); 1307 resetCommon(); 1308 1309 // First initialize use count of all common processes. 1310 final long now = SystemClock.uptimeMillis(); 1311 final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 1312 for (int ip=procMap.size()-1; ip>=0; ip--) { 1313 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 1314 for (int iu=uids.size()-1; iu>=0; iu--) { 1315 uids.valueAt(iu).mTmpNumInUse = 0; 1316 } 1317 } 1318 1319 // Next reset or prune all per-package processes, and for the ones that are reset 1320 // track this back to the common processes. 1321 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1322 for (int ip=pkgMap.size()-1; ip>=0; ip--) { 1323 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1324 for (int iu=uids.size()-1; iu>=0; iu--) { 1325 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1326 for (int iv=vpkgs.size()-1; iv>=0; iv--) { 1327 final PackageState pkgState = vpkgs.valueAt(iv); 1328 for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) { 1329 final ProcessState ps = pkgState.mProcesses.valueAt(iproc); 1330 if (ps.isInUse()) { 1331 ps.resetSafely(now); 1332 ps.mCommonProcess.mTmpNumInUse++; 1333 ps.mCommonProcess.mTmpFoundSubProc = ps; 1334 } else { 1335 pkgState.mProcesses.valueAt(iproc).makeDead(); 1336 pkgState.mProcesses.removeAt(iproc); 1337 } 1338 } 1339 for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) { 1340 final ServiceState ss = pkgState.mServices.valueAt(isvc); 1341 if (ss.isInUse()) { 1342 ss.resetSafely(now); 1343 } else { 1344 pkgState.mServices.removeAt(isvc); 1345 } 1346 } 1347 if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) { 1348 vpkgs.removeAt(iv); 1349 } 1350 } 1351 if (vpkgs.size() <= 0) { 1352 uids.removeAt(iu); 1353 } 1354 } 1355 if (uids.size() <= 0) { 1356 pkgMap.removeAt(ip); 1357 } 1358 } 1359 1360 // Finally prune out any common processes that are no longer in use. 1361 for (int ip=procMap.size()-1; ip>=0; ip--) { 1362 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 1363 for (int iu=uids.size()-1; iu>=0; iu--) { 1364 ProcessState ps = uids.valueAt(iu); 1365 if (ps.isInUse() || ps.mTmpNumInUse > 0) { 1366 // If this is a process for multiple packages, we could at this point 1367 // be back down to one package. In that case, we want to revert back 1368 // to a single shared ProcessState. We can do this by converting the 1369 // current package-specific ProcessState up to the shared ProcessState, 1370 // throwing away the current one we have here (because nobody else is 1371 // using it). 1372 if (!ps.mActive && ps.mMultiPackage && ps.mTmpNumInUse == 1) { 1373 // Here we go... 1374 ps = ps.mTmpFoundSubProc; 1375 ps.mCommonProcess = ps; 1376 uids.setValueAt(iu, ps); 1377 } else { 1378 ps.resetSafely(now); 1379 } 1380 } else { 1381 ps.makeDead(); 1382 uids.removeAt(iu); 1383 } 1384 } 1385 if (uids.size() <= 0) { 1386 procMap.removeAt(ip); 1387 } 1388 } 1389 1390 mStartTime = now; 1391 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr); 1392 } 1393 1394 private void resetCommon() { 1395 mTimePeriodStartClock = System.currentTimeMillis(); 1396 buildTimePeriodStartClockStr(); 1397 mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); 1398 mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis(); 1399 mLongs.clear(); 1400 mLongs.add(new long[LONGS_SIZE]); 1401 mNextLong = 0; 1402 Arrays.fill(mMemFactorDurations, 0); 1403 mSysMemUsageTable = null; 1404 mSysMemUsageTableSize = 0; 1405 mStartTime = 0; 1406 mReadError = null; 1407 mFlags = 0; 1408 evaluateSystemProperties(true); 1409 } 1410 1411 public boolean evaluateSystemProperties(boolean update) { 1412 boolean changed = false; 1413 String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2", 1414 VMRuntime.getRuntime().vmLibrary()); 1415 if (!Objects.equals(runtime, mRuntime)) { 1416 changed = true; 1417 if (update) { 1418 mRuntime = runtime; 1419 } 1420 } 1421 return changed; 1422 } 1423 1424 private void buildTimePeriodStartClockStr() { 1425 mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss", 1426 mTimePeriodStartClock).toString(); 1427 } 1428 1429 static final int[] BAD_TABLE = new int[0]; 1430 1431 private int[] readTableFromParcel(Parcel in, String name, String what) { 1432 final int size = in.readInt(); 1433 if (size < 0) { 1434 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size); 1435 return BAD_TABLE; 1436 } 1437 if (size == 0) { 1438 return null; 1439 } 1440 final int[] table = new int[size]; 1441 for (int i=0; i<size; i++) { 1442 table[i] = in.readInt(); 1443 if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": " 1444 + ProcessStats.printLongOffset(table[i])); 1445 if (!validateLongOffset(table[i])) { 1446 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: " 1447 + ProcessStats.printLongOffset(table[i])); 1448 return null; 1449 } 1450 } 1451 return table; 1452 } 1453 1454 private void writeCompactedLongArray(Parcel out, long[] array, int num) { 1455 for (int i=0; i<num; i++) { 1456 long val = array[i]; 1457 if (val < 0) { 1458 Slog.w(TAG, "Time val negative: " + val); 1459 val = 0; 1460 } 1461 if (val <= Integer.MAX_VALUE) { 1462 out.writeInt((int)val); 1463 } else { 1464 int top = ~((int)((val>>32)&0x7fffffff)); 1465 int bottom = (int)(val&0xfffffff); 1466 out.writeInt(top); 1467 out.writeInt(bottom); 1468 } 1469 } 1470 } 1471 1472 private void readCompactedLongArray(Parcel in, int version, long[] array, int num) { 1473 if (version <= 10) { 1474 in.readLongArray(array); 1475 return; 1476 } 1477 final int alen = array.length; 1478 if (num > alen) { 1479 throw new RuntimeException("bad array lengths: got " + num + " array is " + alen); 1480 } 1481 int i; 1482 for (i=0; i<num; i++) { 1483 int val = in.readInt(); 1484 if (val >= 0) { 1485 array[i] = val; 1486 } else { 1487 int bottom = in.readInt(); 1488 array[i] = (((long)~val)<<32) | bottom; 1489 } 1490 } 1491 while (i < alen) { 1492 array[i] = 0; 1493 i++; 1494 } 1495 } 1496 1497 private void writeCommonString(Parcel out, String name) { 1498 Integer index = mCommonStringToIndex.get(name); 1499 if (index != null) { 1500 out.writeInt(index); 1501 return; 1502 } 1503 index = mCommonStringToIndex.size(); 1504 mCommonStringToIndex.put(name, index); 1505 out.writeInt(~index); 1506 out.writeString(name); 1507 } 1508 1509 private String readCommonString(Parcel in, int version) { 1510 if (version <= 9) { 1511 return in.readString(); 1512 } 1513 int index = in.readInt(); 1514 if (index >= 0) { 1515 return mIndexToCommonString.get(index); 1516 } 1517 index = ~index; 1518 String name = in.readString(); 1519 while (mIndexToCommonString.size() <= index) { 1520 mIndexToCommonString.add(null); 1521 } 1522 mIndexToCommonString.set(index, name); 1523 return name; 1524 } 1525 1526 @Override 1527 public int describeContents() { 1528 return 0; 1529 } 1530 1531 @Override 1532 public void writeToParcel(Parcel out, int flags) { 1533 writeToParcel(out, SystemClock.uptimeMillis(), flags); 1534 } 1535 1536 /** @hide */ 1537 public void writeToParcel(Parcel out, long now, int flags) { 1538 out.writeInt(MAGIC); 1539 out.writeInt(PARCEL_VERSION); 1540 out.writeInt(STATE_COUNT); 1541 out.writeInt(ADJ_COUNT); 1542 out.writeInt(PSS_COUNT); 1543 out.writeInt(SYS_MEM_USAGE_COUNT); 1544 out.writeInt(LONGS_SIZE); 1545 1546 mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size()); 1547 1548 // First commit all running times. 1549 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 1550 final int NPROC = procMap.size(); 1551 for (int ip=0; ip<NPROC; ip++) { 1552 SparseArray<ProcessState> uids = procMap.valueAt(ip); 1553 final int NUID = uids.size(); 1554 for (int iu=0; iu<NUID; iu++) { 1555 uids.valueAt(iu).commitStateTime(now); 1556 } 1557 } 1558 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1559 final int NPKG = pkgMap.size(); 1560 for (int ip=0; ip<NPKG; ip++) { 1561 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1562 final int NUID = uids.size(); 1563 for (int iu=0; iu<NUID; iu++) { 1564 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1565 final int NVERS = vpkgs.size(); 1566 for (int iv=0; iv<NVERS; iv++) { 1567 PackageState pkgState = vpkgs.valueAt(iv); 1568 final int NPROCS = pkgState.mProcesses.size(); 1569 for (int iproc=0; iproc<NPROCS; iproc++) { 1570 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1571 if (proc.mCommonProcess != proc) { 1572 proc.commitStateTime(now); 1573 } 1574 } 1575 final int NSRVS = pkgState.mServices.size(); 1576 for (int isvc=0; isvc<NSRVS; isvc++) { 1577 pkgState.mServices.valueAt(isvc).commitStateTime(now); 1578 } 1579 } 1580 } 1581 } 1582 1583 out.writeLong(mTimePeriodStartClock); 1584 out.writeLong(mTimePeriodStartRealtime); 1585 out.writeLong(mTimePeriodEndRealtime); 1586 out.writeLong(mTimePeriodStartUptime); 1587 out.writeLong(mTimePeriodEndUptime); 1588 out.writeString(mRuntime); 1589 out.writeInt(mFlags); 1590 1591 out.writeInt(mLongs.size()); 1592 out.writeInt(mNextLong); 1593 for (int i=0; i<(mLongs.size()-1); i++) { 1594 long[] array = mLongs.get(i); 1595 writeCompactedLongArray(out, array, array.length); 1596 } 1597 long[] lastLongs = mLongs.get(mLongs.size() - 1); 1598 writeCompactedLongArray(out, lastLongs, mNextLong); 1599 1600 if (mMemFactor != STATE_NOTHING) { 1601 mMemFactorDurations[mMemFactor] += now - mStartTime; 1602 mStartTime = now; 1603 } 1604 writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length); 1605 1606 out.writeInt(mSysMemUsageTableSize); 1607 for (int i=0; i<mSysMemUsageTableSize; i++) { 1608 if (DEBUG_PARCEL) Slog.i(TAG, "Writing sys mem usage #" + i + ": " 1609 + printLongOffset(mSysMemUsageTable[i])); 1610 out.writeInt(mSysMemUsageTable[i]); 1611 } 1612 1613 out.writeInt(NPROC); 1614 for (int ip=0; ip<NPROC; ip++) { 1615 writeCommonString(out, procMap.keyAt(ip)); 1616 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 1617 final int NUID = uids.size(); 1618 out.writeInt(NUID); 1619 for (int iu=0; iu<NUID; iu++) { 1620 out.writeInt(uids.keyAt(iu)); 1621 final ProcessState proc = uids.valueAt(iu); 1622 writeCommonString(out, proc.mPackage); 1623 out.writeInt(proc.mVersion); 1624 proc.writeToParcel(out, now); 1625 } 1626 } 1627 out.writeInt(NPKG); 1628 for (int ip=0; ip<NPKG; ip++) { 1629 writeCommonString(out, pkgMap.keyAt(ip)); 1630 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1631 final int NUID = uids.size(); 1632 out.writeInt(NUID); 1633 for (int iu=0; iu<NUID; iu++) { 1634 out.writeInt(uids.keyAt(iu)); 1635 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1636 final int NVERS = vpkgs.size(); 1637 out.writeInt(NVERS); 1638 for (int iv=0; iv<NVERS; iv++) { 1639 out.writeInt(vpkgs.keyAt(iv)); 1640 final PackageState pkgState = vpkgs.valueAt(iv); 1641 final int NPROCS = pkgState.mProcesses.size(); 1642 out.writeInt(NPROCS); 1643 for (int iproc=0; iproc<NPROCS; iproc++) { 1644 writeCommonString(out, pkgState.mProcesses.keyAt(iproc)); 1645 final ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1646 if (proc.mCommonProcess == proc) { 1647 // This is the same as the common process we wrote above. 1648 out.writeInt(0); 1649 } else { 1650 // There is separate data for this package's process. 1651 out.writeInt(1); 1652 proc.writeToParcel(out, now); 1653 } 1654 } 1655 final int NSRVS = pkgState.mServices.size(); 1656 out.writeInt(NSRVS); 1657 for (int isvc=0; isvc<NSRVS; isvc++) { 1658 out.writeString(pkgState.mServices.keyAt(isvc)); 1659 final ServiceState svc = pkgState.mServices.valueAt(isvc); 1660 writeCommonString(out, svc.mProcessName); 1661 svc.writeToParcel(out, now); 1662 } 1663 } 1664 } 1665 } 1666 1667 mCommonStringToIndex = null; 1668 } 1669 1670 private boolean readCheckedInt(Parcel in, int val, String what) { 1671 int got; 1672 if ((got=in.readInt()) != val) { 1673 mReadError = "bad " + what + ": " + got; 1674 return false; 1675 } 1676 return true; 1677 } 1678 1679 static byte[] readFully(InputStream stream, int[] outLen) throws IOException { 1680 int pos = 0; 1681 final int initialAvail = stream.available(); 1682 byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384]; 1683 while (true) { 1684 int amt = stream.read(data, pos, data.length-pos); 1685 if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos 1686 + " of avail " + data.length); 1687 if (amt < 0) { 1688 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos 1689 + " len=" + data.length); 1690 outLen[0] = pos; 1691 return data; 1692 } 1693 pos += amt; 1694 if (pos >= data.length) { 1695 byte[] newData = new byte[pos+16384]; 1696 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len " 1697 + newData.length); 1698 System.arraycopy(data, 0, newData, 0, pos); 1699 data = newData; 1700 } 1701 } 1702 } 1703 1704 public void read(InputStream stream) { 1705 try { 1706 int[] len = new int[1]; 1707 byte[] raw = readFully(stream, len); 1708 Parcel in = Parcel.obtain(); 1709 in.unmarshall(raw, 0, len[0]); 1710 in.setDataPosition(0); 1711 stream.close(); 1712 1713 readFromParcel(in); 1714 } catch (IOException e) { 1715 mReadError = "caught exception: " + e; 1716 } 1717 } 1718 1719 public void readFromParcel(Parcel in) { 1720 final boolean hadData = mPackages.getMap().size() > 0 1721 || mProcesses.getMap().size() > 0; 1722 if (hadData) { 1723 resetSafely(); 1724 } 1725 1726 if (!readCheckedInt(in, MAGIC, "magic number")) { 1727 return; 1728 } 1729 int version = in.readInt(); 1730 if (version != PARCEL_VERSION) { 1731 mReadError = "bad version: " + version; 1732 return; 1733 } 1734 if (!readCheckedInt(in, STATE_COUNT, "state count")) { 1735 return; 1736 } 1737 if (!readCheckedInt(in, ADJ_COUNT, "adj count")) { 1738 return; 1739 } 1740 if (!readCheckedInt(in, PSS_COUNT, "pss count")) { 1741 return; 1742 } 1743 if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) { 1744 return; 1745 } 1746 if (!readCheckedInt(in, LONGS_SIZE, "longs size")) { 1747 return; 1748 } 1749 1750 mIndexToCommonString = new ArrayList<String>(); 1751 1752 mTimePeriodStartClock = in.readLong(); 1753 buildTimePeriodStartClockStr(); 1754 mTimePeriodStartRealtime = in.readLong(); 1755 mTimePeriodEndRealtime = in.readLong(); 1756 mTimePeriodStartUptime = in.readLong(); 1757 mTimePeriodEndUptime = in.readLong(); 1758 mRuntime = in.readString(); 1759 mFlags = in.readInt(); 1760 1761 final int NLONGS = in.readInt(); 1762 final int NEXTLONG = in.readInt(); 1763 mLongs.clear(); 1764 for (int i=0; i<(NLONGS-1); i++) { 1765 while (i >= mLongs.size()) { 1766 mLongs.add(new long[LONGS_SIZE]); 1767 } 1768 readCompactedLongArray(in, version, mLongs.get(i), LONGS_SIZE); 1769 } 1770 long[] longs = new long[LONGS_SIZE]; 1771 mNextLong = NEXTLONG; 1772 readCompactedLongArray(in, version, longs, NEXTLONG); 1773 mLongs.add(longs); 1774 1775 readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length); 1776 1777 mSysMemUsageTable = readTableFromParcel(in, TAG, "sys mem usage"); 1778 if (mSysMemUsageTable == BAD_TABLE) { 1779 return; 1780 } 1781 mSysMemUsageTableSize = mSysMemUsageTable != null ? mSysMemUsageTable.length : 0; 1782 1783 int NPROC = in.readInt(); 1784 if (NPROC < 0) { 1785 mReadError = "bad process count: " + NPROC; 1786 return; 1787 } 1788 while (NPROC > 0) { 1789 NPROC--; 1790 final String procName = readCommonString(in, version); 1791 if (procName == null) { 1792 mReadError = "bad process name"; 1793 return; 1794 } 1795 int NUID = in.readInt(); 1796 if (NUID < 0) { 1797 mReadError = "bad uid count: " + NUID; 1798 return; 1799 } 1800 while (NUID > 0) { 1801 NUID--; 1802 final int uid = in.readInt(); 1803 if (uid < 0) { 1804 mReadError = "bad uid: " + uid; 1805 return; 1806 } 1807 final String pkgName = readCommonString(in, version); 1808 if (pkgName == null) { 1809 mReadError = "bad process package name"; 1810 return; 1811 } 1812 final int vers = in.readInt(); 1813 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null; 1814 if (proc != null) { 1815 if (!proc.readFromParcel(in, false)) { 1816 return; 1817 } 1818 } else { 1819 proc = new ProcessState(this, pkgName, uid, vers, procName); 1820 if (!proc.readFromParcel(in, true)) { 1821 return; 1822 } 1823 } 1824 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid 1825 + " " + proc); 1826 mProcesses.put(procName, uid, proc); 1827 } 1828 } 1829 1830 if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes"); 1831 1832 int NPKG = in.readInt(); 1833 if (NPKG < 0) { 1834 mReadError = "bad package count: " + NPKG; 1835 return; 1836 } 1837 while (NPKG > 0) { 1838 NPKG--; 1839 final String pkgName = readCommonString(in, version); 1840 if (pkgName == null) { 1841 mReadError = "bad package name"; 1842 return; 1843 } 1844 int NUID = in.readInt(); 1845 if (NUID < 0) { 1846 mReadError = "bad uid count: " + NUID; 1847 return; 1848 } 1849 while (NUID > 0) { 1850 NUID--; 1851 final int uid = in.readInt(); 1852 if (uid < 0) { 1853 mReadError = "bad uid: " + uid; 1854 return; 1855 } 1856 int NVERS = in.readInt(); 1857 if (NVERS < 0) { 1858 mReadError = "bad versions count: " + NVERS; 1859 return; 1860 } 1861 while (NVERS > 0) { 1862 NVERS--; 1863 final int vers = in.readInt(); 1864 PackageState pkgState = new PackageState(pkgName, uid); 1865 SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid); 1866 if (vpkg == null) { 1867 vpkg = new SparseArray<PackageState>(); 1868 mPackages.put(pkgName, uid, vpkg); 1869 } 1870 vpkg.put(vers, pkgState); 1871 int NPROCS = in.readInt(); 1872 if (NPROCS < 0) { 1873 mReadError = "bad package process count: " + NPROCS; 1874 return; 1875 } 1876 while (NPROCS > 0) { 1877 NPROCS--; 1878 String procName = readCommonString(in, version); 1879 if (procName == null) { 1880 mReadError = "bad package process name"; 1881 return; 1882 } 1883 int hasProc = in.readInt(); 1884 if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid 1885 + " process " + procName + " hasProc=" + hasProc); 1886 ProcessState commonProc = mProcesses.get(procName, uid); 1887 if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid 1888 + ": " + commonProc); 1889 if (commonProc == null) { 1890 mReadError = "no common proc: " + procName; 1891 return; 1892 } 1893 if (hasProc != 0) { 1894 // The process for this package is unique to the package; we 1895 // need to load it. We don't need to do anything about it if 1896 // it is not unique because if someone later looks for it 1897 // they will find and use it from the global procs. 1898 ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null; 1899 if (proc != null) { 1900 if (!proc.readFromParcel(in, false)) { 1901 return; 1902 } 1903 } else { 1904 proc = new ProcessState(commonProc, pkgName, uid, vers, procName, 1905 0); 1906 if (!proc.readFromParcel(in, true)) { 1907 return; 1908 } 1909 } 1910 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: " 1911 + procName + " " + uid + " " + proc); 1912 pkgState.mProcesses.put(procName, proc); 1913 } else { 1914 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: " 1915 + procName + " " + uid + " " + commonProc); 1916 pkgState.mProcesses.put(procName, commonProc); 1917 } 1918 } 1919 int NSRVS = in.readInt(); 1920 if (NSRVS < 0) { 1921 mReadError = "bad package service count: " + NSRVS; 1922 return; 1923 } 1924 while (NSRVS > 0) { 1925 NSRVS--; 1926 String serviceName = in.readString(); 1927 if (serviceName == null) { 1928 mReadError = "bad package service name"; 1929 return; 1930 } 1931 String processName = version > 9 ? readCommonString(in, version) : null; 1932 ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null; 1933 if (serv == null) { 1934 serv = new ServiceState(this, pkgName, serviceName, processName, null); 1935 } 1936 if (!serv.readFromParcel(in)) { 1937 return; 1938 } 1939 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: " 1940 + serviceName + " " + uid + " " + serv); 1941 pkgState.mServices.put(serviceName, serv); 1942 } 1943 } 1944 } 1945 } 1946 1947 mIndexToCommonString = null; 1948 1949 if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!"); 1950 } 1951 1952 int addLongData(int index, int type, int num) { 1953 int off = allocLongData(num); 1954 mAddLongTable = GrowingArrayUtils.insert( 1955 mAddLongTable != null ? mAddLongTable : EmptyArray.INT, 1956 mAddLongTableSize, index, type | off); 1957 mAddLongTableSize++; 1958 return off; 1959 } 1960 1961 int allocLongData(int num) { 1962 int whichLongs = mLongs.size()-1; 1963 long[] longs = mLongs.get(whichLongs); 1964 if (mNextLong + num > longs.length) { 1965 longs = new long[LONGS_SIZE]; 1966 mLongs.add(longs); 1967 whichLongs++; 1968 mNextLong = 0; 1969 } 1970 int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT); 1971 mNextLong += num; 1972 return off; 1973 } 1974 1975 boolean validateLongOffset(int off) { 1976 int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK; 1977 if (arr >= mLongs.size()) { 1978 return false; 1979 } 1980 int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK; 1981 if (idx >= LONGS_SIZE) { 1982 return false; 1983 } 1984 if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off) 1985 + ": " + getLong(off, 0)); 1986 return true; 1987 } 1988 1989 static String printLongOffset(int off) { 1990 StringBuilder sb = new StringBuilder(16); 1991 sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 1992 sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK); 1993 sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK); 1994 return sb.toString(); 1995 } 1996 1997 void setLong(int off, int index, long value) { 1998 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 1999 longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value; 2000 } 2001 2002 long getLong(int off, int index) { 2003 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 2004 return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)]; 2005 } 2006 2007 static int binarySearch(int[] array, int size, int value) { 2008 int lo = 0; 2009 int hi = size - 1; 2010 2011 while (lo <= hi) { 2012 int mid = (lo + hi) >>> 1; 2013 int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK; 2014 2015 if (midVal < value) { 2016 lo = mid + 1; 2017 } else if (midVal > value) { 2018 hi = mid - 1; 2019 } else { 2020 return mid; // value found 2021 } 2022 } 2023 return ~lo; // value not present 2024 } 2025 2026 public PackageState getPackageStateLocked(String packageName, int uid, int vers) { 2027 SparseArray<PackageState> vpkg = mPackages.get(packageName, uid); 2028 if (vpkg == null) { 2029 vpkg = new SparseArray<PackageState>(); 2030 mPackages.put(packageName, uid, vpkg); 2031 } 2032 PackageState as = vpkg.get(vers); 2033 if (as != null) { 2034 return as; 2035 } 2036 as = new PackageState(packageName, uid); 2037 vpkg.put(vers, as); 2038 return as; 2039 } 2040 2041 public ProcessState getProcessStateLocked(String packageName, int uid, int vers, 2042 String processName) { 2043 final PackageState pkgState = getPackageStateLocked(packageName, uid, vers); 2044 ProcessState ps = pkgState.mProcesses.get(processName); 2045 if (ps != null) { 2046 return ps; 2047 } 2048 ProcessState commonProc = mProcesses.get(processName, uid); 2049 if (commonProc == null) { 2050 commonProc = new ProcessState(this, packageName, uid, vers, processName); 2051 mProcesses.put(processName, uid, commonProc); 2052 if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc); 2053 } 2054 if (!commonProc.mMultiPackage) { 2055 if (packageName.equals(commonProc.mPackage) && vers == commonProc.mVersion) { 2056 // This common process is not in use by multiple packages, and 2057 // is for the calling package, so we can just use it directly. 2058 ps = commonProc; 2059 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc); 2060 } else { 2061 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!"); 2062 // This common process has not been in use by multiple packages, 2063 // but it was created for a different package than the caller. 2064 // We need to convert it to a multi-package process. 2065 commonProc.mMultiPackage = true; 2066 // To do this, we need to make two new process states, one a copy 2067 // of the current state for the process under the original package 2068 // name, and the second a free new process state for it as the 2069 // new package name. 2070 long now = SystemClock.uptimeMillis(); 2071 // First let's make a copy of the current process state and put 2072 // that under the now unique state for its original package name. 2073 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage, 2074 uid, commonProc.mVersion); 2075 if (commonPkgState != null) { 2076 ProcessState cloned = commonProc.clone(commonProc.mPackage, now); 2077 if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage 2078 + ": " + cloned); 2079 commonPkgState.mProcesses.put(commonProc.mName, cloned); 2080 // If this has active services, we need to update their process pointer 2081 // to point to the new package-specific process state. 2082 for (int i=commonPkgState.mServices.size()-1; i>=0; i--) { 2083 ServiceState ss = commonPkgState.mServices.valueAt(i); 2084 if (ss.mProc == commonProc) { 2085 if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: " 2086 + ss); 2087 ss.mProc = cloned; 2088 } else if (DEBUG) { 2089 Slog.d(TAG, "GETPROC leaving proc of " + ss); 2090 } 2091 } 2092 } else { 2093 Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage 2094 + "/" + uid + " for proc " + commonProc.mName); 2095 } 2096 // And now make a fresh new process state for the new package name. 2097 ps = new ProcessState(commonProc, packageName, uid, vers, processName, now); 2098 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps); 2099 } 2100 } else { 2101 // The common process is for multiple packages, we need to create a 2102 // separate object for the per-package data. 2103 ps = new ProcessState(commonProc, packageName, uid, vers, processName, 2104 SystemClock.uptimeMillis()); 2105 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps); 2106 } 2107 pkgState.mProcesses.put(processName, ps); 2108 if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps); 2109 return ps; 2110 } 2111 2112 public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid, int vers, 2113 String processName, String className) { 2114 final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers); 2115 ProcessStats.ServiceState ss = as.mServices.get(className); 2116 if (ss != null) { 2117 if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss); 2118 return ss; 2119 } 2120 final ProcessStats.ProcessState ps = processName != null 2121 ? getProcessStateLocked(packageName, uid, vers, processName) : null; 2122 ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps); 2123 as.mServices.put(className, ss); 2124 if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps); 2125 return ss; 2126 } 2127 2128 private void dumpProcessInternalLocked(PrintWriter pw, String prefix, ProcessState proc, 2129 boolean dumpAll) { 2130 if (dumpAll) { 2131 pw.print(prefix); pw.print("myID="); 2132 pw.print(Integer.toHexString(System.identityHashCode(proc))); 2133 pw.print(" mCommonProcess="); 2134 pw.print(Integer.toHexString(System.identityHashCode(proc.mCommonProcess))); 2135 pw.print(" mPackage="); pw.println(proc.mPackage); 2136 if (proc.mMultiPackage) { 2137 pw.print(prefix); pw.print("mMultiPackage="); pw.println(proc.mMultiPackage); 2138 } 2139 if (proc != proc.mCommonProcess) { 2140 pw.print(prefix); pw.print("Common Proc: "); pw.print(proc.mCommonProcess.mName); 2141 pw.print("/"); pw.print(proc.mCommonProcess.mUid); 2142 pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage); 2143 } 2144 } 2145 if (proc.mActive) { 2146 pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive); 2147 } 2148 if (proc.mDead) { 2149 pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead); 2150 } 2151 if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) { 2152 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices); 2153 pw.print(" mNumStartedServices="); 2154 pw.println(proc.mNumStartedServices); 2155 } 2156 } 2157 2158 public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, 2159 boolean dumpAll, boolean activeOnly) { 2160 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, 2161 mStartTime, now); 2162 if (mSysMemUsageTable != null) { 2163 pw.println("System memory usage:"); 2164 dumpSysMemUsage(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ); 2165 } 2166 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 2167 boolean printedHeader = false; 2168 boolean sepNeeded = false; 2169 for (int ip=0; ip<pkgMap.size(); ip++) { 2170 final String pkgName = pkgMap.keyAt(ip); 2171 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 2172 for (int iu=0; iu<uids.size(); iu++) { 2173 final int uid = uids.keyAt(iu); 2174 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 2175 for (int iv=0; iv<vpkgs.size(); iv++) { 2176 final int vers = vpkgs.keyAt(iv); 2177 final PackageState pkgState = vpkgs.valueAt(iv); 2178 final int NPROCS = pkgState.mProcesses.size(); 2179 final int NSRVS = pkgState.mServices.size(); 2180 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); 2181 if (!pkgMatch) { 2182 boolean procMatch = false; 2183 for (int iproc=0; iproc<NPROCS; iproc++) { 2184 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2185 if (reqPackage.equals(proc.mName)) { 2186 procMatch = true; 2187 break; 2188 } 2189 } 2190 if (!procMatch) { 2191 continue; 2192 } 2193 } 2194 if (NPROCS > 0 || NSRVS > 0) { 2195 if (!printedHeader) { 2196 pw.println("Per-Package Stats:"); 2197 printedHeader = true; 2198 sepNeeded = true; 2199 } 2200 pw.print(" * "); pw.print(pkgName); pw.print(" / "); 2201 UserHandle.formatUid(pw, uid); pw.print(" / v"); 2202 pw.print(vers); pw.println(":"); 2203 } 2204 if (!dumpSummary || dumpAll) { 2205 for (int iproc=0; iproc<NPROCS; iproc++) { 2206 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2207 if (!pkgMatch && !reqPackage.equals(proc.mName)) { 2208 continue; 2209 } 2210 if (activeOnly && !proc.isInUse()) { 2211 pw.print(" (Not active: "); 2212 pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")"); 2213 continue; 2214 } 2215 pw.print(" Process "); 2216 pw.print(pkgState.mProcesses.keyAt(iproc)); 2217 if (proc.mCommonProcess.mMultiPackage) { 2218 pw.print(" (multi, "); 2219 } else { 2220 pw.print(" (unique, "); 2221 } 2222 pw.print(proc.mDurationsTableSize); 2223 pw.print(" entries)"); 2224 pw.println(":"); 2225 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2226 ALL_PROC_STATES, now); 2227 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2228 ALL_PROC_STATES); 2229 dumpProcessInternalLocked(pw, " ", proc, dumpAll); 2230 } 2231 } else { 2232 ArrayList<ProcessState> procs = new ArrayList<ProcessState>(); 2233 for (int iproc=0; iproc<NPROCS; iproc++) { 2234 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2235 if (!pkgMatch && !reqPackage.equals(proc.mName)) { 2236 continue; 2237 } 2238 if (activeOnly && !proc.isInUse()) { 2239 continue; 2240 } 2241 procs.add(proc); 2242 } 2243 dumpProcessSummaryLocked(pw, " ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2244 NON_CACHED_PROC_STATES, false, now, totalTime); 2245 } 2246 for (int isvc=0; isvc<NSRVS; isvc++) { 2247 ServiceState svc = pkgState.mServices.valueAt(isvc); 2248 if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) { 2249 continue; 2250 } 2251 if (activeOnly && !svc.isInUse()) { 2252 pw.print(" (Not active: "); 2253 pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")"); 2254 continue; 2255 } 2256 if (dumpAll) { 2257 pw.print(" Service "); 2258 } else { 2259 pw.print(" * "); 2260 } 2261 pw.print(pkgState.mServices.keyAt(isvc)); 2262 pw.println(":"); 2263 pw.print(" Process: "); pw.println(svc.mProcessName); 2264 dumpServiceStats(pw, " ", " ", " ", "Running", svc, 2265 svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState, 2266 svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll); 2267 dumpServiceStats(pw, " ", " ", " ", "Started", svc, 2268 svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState, 2269 svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll); 2270 dumpServiceStats(pw, " ", " ", " ", "Bound", svc, 2271 svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState, 2272 svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll); 2273 dumpServiceStats(pw, " ", " ", " ", "Executing", svc, 2274 svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState, 2275 svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll); 2276 if (dumpAll) { 2277 if (svc.mOwner != null) { 2278 pw.print(" mOwner="); pw.println(svc.mOwner); 2279 } 2280 if (svc.mStarted || svc.mRestarting) { 2281 pw.print(" mStarted="); pw.print(svc.mStarted); 2282 pw.print(" mRestarting="); pw.println(svc.mRestarting); 2283 } 2284 } 2285 } 2286 } 2287 } 2288 } 2289 2290 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 2291 printedHeader = false; 2292 int numShownProcs = 0, numTotalProcs = 0; 2293 for (int ip=0; ip<procMap.size(); ip++) { 2294 String procName = procMap.keyAt(ip); 2295 SparseArray<ProcessState> uids = procMap.valueAt(ip); 2296 for (int iu=0; iu<uids.size(); iu++) { 2297 int uid = uids.keyAt(iu); 2298 numTotalProcs++; 2299 ProcessState proc = uids.valueAt(iu); 2300 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING 2301 && proc.mPssTableSize == 0) { 2302 continue; 2303 } 2304 if (!proc.mMultiPackage) { 2305 continue; 2306 } 2307 if (reqPackage != null && !reqPackage.equals(procName) 2308 && !reqPackage.equals(proc.mPackage)) { 2309 continue; 2310 } 2311 numShownProcs++; 2312 if (sepNeeded) { 2313 pw.println(); 2314 } 2315 sepNeeded = true; 2316 if (!printedHeader) { 2317 pw.println("Multi-Package Common Processes:"); 2318 printedHeader = true; 2319 } 2320 if (activeOnly && !proc.isInUse()) { 2321 pw.print(" (Not active: "); pw.print(procName); pw.println(")"); 2322 continue; 2323 } 2324 pw.print(" * "); pw.print(procName); pw.print(" / "); 2325 UserHandle.formatUid(pw, uid); 2326 pw.print(" ("); pw.print(proc.mDurationsTableSize); 2327 pw.print(" entries)"); pw.println(":"); 2328 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2329 ALL_PROC_STATES, now); 2330 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2331 ALL_PROC_STATES); 2332 dumpProcessInternalLocked(pw, " ", proc, dumpAll); 2333 } 2334 } 2335 if (dumpAll) { 2336 pw.println(); 2337 pw.print(" Total procs: "); pw.print(numShownProcs); 2338 pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); 2339 } 2340 2341 if (sepNeeded) { 2342 pw.println(); 2343 } 2344 if (dumpSummary) { 2345 pw.println("Summary:"); 2346 dumpSummaryLocked(pw, reqPackage, now, activeOnly); 2347 } else { 2348 dumpTotalsLocked(pw, now); 2349 } 2350 2351 if (dumpAll) { 2352 pw.println(); 2353 pw.println("Internal state:"); 2354 pw.print(" Num long arrays: "); pw.println(mLongs.size()); 2355 pw.print(" Next long entry: "); pw.println(mNextLong); 2356 pw.print(" mRunning="); pw.println(mRunning); 2357 } 2358 } 2359 2360 public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service, 2361 int serviceType, int curState, long curStartTime, long now) { 2362 long totalTime = 0; 2363 int printedScreen = -1; 2364 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) { 2365 int printedMem = -1; 2366 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) { 2367 int state = imem+iscreen; 2368 long time = service.getDuration(serviceType, curState, curStartTime, 2369 state, now); 2370 String running = ""; 2371 if (curState == state && pw != null) { 2372 running = " (running)"; 2373 } 2374 if (time != 0) { 2375 if (pw != null) { 2376 pw.print(prefix); 2377 printScreenLabel(pw, printedScreen != iscreen 2378 ? iscreen : STATE_NOTHING); 2379 printedScreen = iscreen; 2380 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0); 2381 printedMem = imem; 2382 pw.print(": "); 2383 TimeUtils.formatDuration(time, pw); pw.println(running); 2384 } 2385 totalTime += time; 2386 } 2387 } 2388 } 2389 if (totalTime != 0 && pw != null) { 2390 pw.print(prefix); 2391 pw.print(" TOTAL: "); 2392 TimeUtils.formatDuration(totalTime, pw); 2393 pw.println(); 2394 } 2395 return totalTime; 2396 } 2397 2398 void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner, 2399 String headerPrefix, String header, ServiceState service, 2400 int count, int serviceType, int state, long startTime, long now, long totalTime, 2401 boolean dumpAll) { 2402 if (count != 0) { 2403 if (dumpAll) { 2404 pw.print(prefix); pw.print(header); 2405 pw.print(" op count "); pw.print(count); pw.println(":"); 2406 dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime, 2407 now); 2408 } else { 2409 long myTime = dumpSingleServiceTime(null, null, service, serviceType, state, 2410 startTime, now); 2411 pw.print(prefix); pw.print(headerPrefix); pw.print(header); 2412 pw.print(" count "); pw.print(count); 2413 pw.print(" / time "); 2414 printPercent(pw, (double)myTime/(double)totalTime); 2415 pw.println(); 2416 } 2417 } 2418 } 2419 2420 public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) { 2421 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, 2422 mStartTime, now); 2423 dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2424 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly); 2425 pw.println(); 2426 dumpTotalsLocked(pw, now); 2427 } 2428 2429 long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, 2430 long totalTime, long curTotalMem, int samples) { 2431 if (memWeight != 0) { 2432 long mem = (long)(memWeight * 1024 / totalTime); 2433 pw.print(prefix); 2434 pw.print(label); 2435 pw.print(": "); 2436 printSizeValue(pw, mem); 2437 pw.print(" ("); 2438 pw.print(samples); 2439 pw.print(" samples)"); 2440 pw.println(); 2441 return curTotalMem + mem; 2442 } 2443 return curTotalMem; 2444 } 2445 2446 void dumpTotalsLocked(PrintWriter pw, long now) { 2447 pw.println("Run time Stats:"); 2448 dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now); 2449 pw.println(); 2450 pw.println("Memory usage:"); 2451 TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, 2452 ALL_MEM_ADJ); 2453 computeTotalMemoryUse(totalMem, now); 2454 long totalPss = 0; 2455 totalPss = printMemoryCategory(pw, " ", "Kernel ", totalMem.sysMemKernelWeight, 2456 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2457 totalPss = printMemoryCategory(pw, " ", "Native ", totalMem.sysMemNativeWeight, 2458 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2459 for (int i=0; i<STATE_COUNT; i++) { 2460 // Skip restarting service state -- that is not actually a running process. 2461 if (i != STATE_SERVICE_RESTARTING) { 2462 totalPss = printMemoryCategory(pw, " ", STATE_NAMES[i], 2463 totalMem.processStateWeight[i], totalMem.totalTime, totalPss, 2464 totalMem.processStateSamples[i]); 2465 } 2466 } 2467 totalPss = printMemoryCategory(pw, " ", "Cached ", totalMem.sysMemCachedWeight, 2468 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2469 totalPss = printMemoryCategory(pw, " ", "Free ", totalMem.sysMemFreeWeight, 2470 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2471 totalPss = printMemoryCategory(pw, " ", "Z-Ram ", totalMem.sysMemZRamWeight, 2472 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2473 pw.print(" TOTAL : "); 2474 printSizeValue(pw, totalPss); 2475 pw.println(); 2476 printMemoryCategory(pw, " ", STATE_NAMES[STATE_SERVICE_RESTARTING], 2477 totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss, 2478 totalMem.processStateSamples[STATE_SERVICE_RESTARTING]); 2479 pw.println(); 2480 pw.print(" Start time: "); 2481 pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock)); 2482 pw.println(); 2483 pw.print(" Total elapsed time: "); 2484 TimeUtils.formatDuration( 2485 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime) 2486 - mTimePeriodStartRealtime, pw); 2487 boolean partial = true; 2488 if ((mFlags&FLAG_SHUTDOWN) != 0) { 2489 pw.print(" (shutdown)"); 2490 partial = false; 2491 } 2492 if ((mFlags&FLAG_SYSPROPS) != 0) { 2493 pw.print(" (sysprops)"); 2494 partial = false; 2495 } 2496 if ((mFlags&FLAG_COMPLETE) != 0) { 2497 pw.print(" (complete)"); 2498 partial = false; 2499 } 2500 if (partial) { 2501 pw.print(" (partial)"); 2502 } 2503 pw.print(' '); 2504 pw.print(mRuntime); 2505 pw.println(); 2506 } 2507 2508 void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, 2509 int[] screenStates, int[] memStates, int[] procStates, 2510 int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) { 2511 ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates, 2512 procStates, sortProcStates, now, reqPackage, activeOnly); 2513 if (procs.size() > 0) { 2514 if (header != null) { 2515 pw.println(); 2516 pw.println(header); 2517 } 2518 dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates, 2519 sortProcStates, true, now, totalTime); 2520 } 2521 } 2522 2523 public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates, 2524 int[] procStates, int sortProcStates[], long now, String reqPackage, 2525 boolean activeOnly) { 2526 final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>(); 2527 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 2528 for (int ip=0; ip<pkgMap.size(); ip++) { 2529 final String pkgName = pkgMap.keyAt(ip); 2530 final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip); 2531 for (int iu=0; iu<procs.size(); iu++) { 2532 final SparseArray<PackageState> vpkgs = procs.valueAt(iu); 2533 final int NVERS = vpkgs.size(); 2534 for (int iv=0; iv<NVERS; iv++) { 2535 final PackageState state = vpkgs.valueAt(iv); 2536 final int NPROCS = state.mProcesses.size(); 2537 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); 2538 for (int iproc=0; iproc<NPROCS; iproc++) { 2539 final ProcessState proc = state.mProcesses.valueAt(iproc); 2540 if (!pkgMatch && !reqPackage.equals(proc.mName)) { 2541 continue; 2542 } 2543 if (activeOnly && !proc.isInUse()) { 2544 continue; 2545 } 2546 foundProcs.add(proc.mCommonProcess); 2547 } 2548 } 2549 } 2550 } 2551 ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size()); 2552 for (int i=0; i<foundProcs.size(); i++) { 2553 ProcessState proc = foundProcs.valueAt(i); 2554 if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) { 2555 outProcs.add(proc); 2556 if (procStates != sortProcStates) { 2557 computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now); 2558 } 2559 } 2560 } 2561 Collections.sort(outProcs, new Comparator<ProcessState>() { 2562 @Override 2563 public int compare(ProcessState lhs, ProcessState rhs) { 2564 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) { 2565 return -1; 2566 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) { 2567 return 1; 2568 } 2569 return 0; 2570 } 2571 }); 2572 return outProcs; 2573 } 2574 2575 String collapseString(String pkgName, String itemName) { 2576 if (itemName.startsWith(pkgName)) { 2577 final int ITEMLEN = itemName.length(); 2578 final int PKGLEN = pkgName.length(); 2579 if (ITEMLEN == PKGLEN) { 2580 return ""; 2581 } else if (ITEMLEN >= PKGLEN) { 2582 if (itemName.charAt(PKGLEN) == '.') { 2583 return itemName.substring(PKGLEN); 2584 } 2585 } 2586 } 2587 return itemName; 2588 } 2589 2590 public void dumpCheckinLocked(PrintWriter pw, String reqPackage) { 2591 final long now = SystemClock.uptimeMillis(); 2592 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 2593 pw.println("vers,5"); 2594 pw.print("period,"); pw.print(mTimePeriodStartClockStr); 2595 pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(","); 2596 pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime); 2597 boolean partial = true; 2598 if ((mFlags&FLAG_SHUTDOWN) != 0) { 2599 pw.print(",shutdown"); 2600 partial = false; 2601 } 2602 if ((mFlags&FLAG_SYSPROPS) != 0) { 2603 pw.print(",sysprops"); 2604 partial = false; 2605 } 2606 if ((mFlags&FLAG_COMPLETE) != 0) { 2607 pw.print(",complete"); 2608 partial = false; 2609 } 2610 if (partial) { 2611 pw.print(",partial"); 2612 } 2613 pw.println(); 2614 pw.print("config,"); pw.println(mRuntime); 2615 for (int ip=0; ip<pkgMap.size(); ip++) { 2616 final String pkgName = pkgMap.keyAt(ip); 2617 if (reqPackage != null && !reqPackage.equals(pkgName)) { 2618 continue; 2619 } 2620 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 2621 for (int iu=0; iu<uids.size(); iu++) { 2622 final int uid = uids.keyAt(iu); 2623 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 2624 for (int iv=0; iv<vpkgs.size(); iv++) { 2625 final int vers = vpkgs.keyAt(iv); 2626 final PackageState pkgState = vpkgs.valueAt(iv); 2627 final int NPROCS = pkgState.mProcesses.size(); 2628 final int NSRVS = pkgState.mServices.size(); 2629 for (int iproc=0; iproc<NPROCS; iproc++) { 2630 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2631 pw.print("pkgproc,"); 2632 pw.print(pkgName); 2633 pw.print(","); 2634 pw.print(uid); 2635 pw.print(","); 2636 pw.print(vers); 2637 pw.print(","); 2638 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc))); 2639 dumpAllProcessStateCheckin(pw, proc, now); 2640 pw.println(); 2641 if (proc.mPssTableSize > 0) { 2642 pw.print("pkgpss,"); 2643 pw.print(pkgName); 2644 pw.print(","); 2645 pw.print(uid); 2646 pw.print(","); 2647 pw.print(vers); 2648 pw.print(","); 2649 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc))); 2650 dumpAllProcessPssCheckin(pw, proc); 2651 pw.println(); 2652 } 2653 if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0 2654 || proc.mNumCachedKill > 0) { 2655 pw.print("pkgkills,"); 2656 pw.print(pkgName); 2657 pw.print(","); 2658 pw.print(uid); 2659 pw.print(","); 2660 pw.print(vers); 2661 pw.print(","); 2662 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc))); 2663 pw.print(","); 2664 pw.print(proc.mNumExcessiveWake); 2665 pw.print(","); 2666 pw.print(proc.mNumExcessiveCpu); 2667 pw.print(","); 2668 pw.print(proc.mNumCachedKill); 2669 pw.print(","); 2670 pw.print(proc.mMinCachedKillPss); 2671 pw.print(":"); 2672 pw.print(proc.mAvgCachedKillPss); 2673 pw.print(":"); 2674 pw.print(proc.mMaxCachedKillPss); 2675 pw.println(); 2676 } 2677 } 2678 for (int isvc=0; isvc<NSRVS; isvc++) { 2679 String serviceName = collapseString(pkgName, 2680 pkgState.mServices.keyAt(isvc)); 2681 ServiceState svc = pkgState.mServices.valueAt(isvc); 2682 dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, vers, serviceName, 2683 svc, ServiceState.SERVICE_RUN, svc.mRunCount, 2684 svc.mRunState, svc.mRunStartTime, now); 2685 dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName, 2686 svc, ServiceState.SERVICE_STARTED, svc.mStartedCount, 2687 svc.mStartedState, svc.mStartedStartTime, now); 2688 dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName, 2689 svc, ServiceState.SERVICE_BOUND, svc.mBoundCount, 2690 svc.mBoundState, svc.mBoundStartTime, now); 2691 dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName, 2692 svc, ServiceState.SERVICE_EXEC, svc.mExecCount, 2693 svc.mExecState, svc.mExecStartTime, now); 2694 } 2695 } 2696 } 2697 } 2698 2699 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 2700 for (int ip=0; ip<procMap.size(); ip++) { 2701 String procName = procMap.keyAt(ip); 2702 SparseArray<ProcessState> uids = procMap.valueAt(ip); 2703 for (int iu=0; iu<uids.size(); iu++) { 2704 int uid = uids.keyAt(iu); 2705 ProcessState procState = uids.valueAt(iu); 2706 if (procState.mDurationsTableSize > 0) { 2707 pw.print("proc,"); 2708 pw.print(procName); 2709 pw.print(","); 2710 pw.print(uid); 2711 dumpAllProcessStateCheckin(pw, procState, now); 2712 pw.println(); 2713 } 2714 if (procState.mPssTableSize > 0) { 2715 pw.print("pss,"); 2716 pw.print(procName); 2717 pw.print(","); 2718 pw.print(uid); 2719 dumpAllProcessPssCheckin(pw, procState); 2720 pw.println(); 2721 } 2722 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0 2723 || procState.mNumCachedKill > 0) { 2724 pw.print("kills,"); 2725 pw.print(procName); 2726 pw.print(","); 2727 pw.print(uid); 2728 pw.print(","); 2729 pw.print(procState.mNumExcessiveWake); 2730 pw.print(","); 2731 pw.print(procState.mNumExcessiveCpu); 2732 pw.print(","); 2733 pw.print(procState.mNumCachedKill); 2734 pw.print(","); 2735 pw.print(procState.mMinCachedKillPss); 2736 pw.print(":"); 2737 pw.print(procState.mAvgCachedKillPss); 2738 pw.print(":"); 2739 pw.print(procState.mMaxCachedKillPss); 2740 pw.println(); 2741 } 2742 } 2743 } 2744 pw.print("total"); 2745 dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor, 2746 mStartTime, now); 2747 if (mSysMemUsageTable != null) { 2748 pw.print("sysmemusage"); 2749 for (int i=0; i<mSysMemUsageTableSize; i++) { 2750 int off = mSysMemUsageTable[i]; 2751 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2752 pw.print(","); 2753 printProcStateTag(pw, type); 2754 for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) { 2755 if (j > SYS_MEM_USAGE_CACHED_MINIMUM) { 2756 pw.print(":"); 2757 } 2758 pw.print(getLong(off, j)); 2759 } 2760 } 2761 } 2762 pw.println(); 2763 TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, 2764 ALL_MEM_ADJ); 2765 computeTotalMemoryUse(totalMem, now); 2766 pw.print("weights,"); 2767 pw.print(totalMem.totalTime); 2768 pw.print(","); 2769 pw.print(totalMem.sysMemCachedWeight); 2770 pw.print(":"); 2771 pw.print(totalMem.sysMemSamples); 2772 pw.print(","); 2773 pw.print(totalMem.sysMemFreeWeight); 2774 pw.print(":"); 2775 pw.print(totalMem.sysMemSamples); 2776 pw.print(","); 2777 pw.print(totalMem.sysMemZRamWeight); 2778 pw.print(":"); 2779 pw.print(totalMem.sysMemSamples); 2780 pw.print(","); 2781 pw.print(totalMem.sysMemKernelWeight); 2782 pw.print(":"); 2783 pw.print(totalMem.sysMemSamples); 2784 pw.print(","); 2785 pw.print(totalMem.sysMemNativeWeight); 2786 pw.print(":"); 2787 pw.print(totalMem.sysMemSamples); 2788 for (int i=0; i<STATE_COUNT; i++) { 2789 pw.print(","); 2790 pw.print(totalMem.processStateWeight[i]); 2791 pw.print(":"); 2792 pw.print(totalMem.processStateSamples[i]); 2793 } 2794 pw.println(); 2795 } 2796 2797 public static class DurationsTable { 2798 public final ProcessStats mStats; 2799 public final String mName; 2800 public int[] mDurationsTable; 2801 public int mDurationsTableSize; 2802 2803 public DurationsTable(ProcessStats stats, String name) { 2804 mStats = stats; 2805 mName = name; 2806 } 2807 2808 void copyDurationsTo(DurationsTable other) { 2809 if (mDurationsTable != null) { 2810 mStats.mAddLongTable = new int[mDurationsTable.length]; 2811 mStats.mAddLongTableSize = 0; 2812 for (int i=0; i<mDurationsTableSize; i++) { 2813 int origEnt = mDurationsTable[i]; 2814 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2815 int newOff = mStats.addLongData(i, type, 1); 2816 mStats.mAddLongTable[i] = newOff | type; 2817 mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0)); 2818 } 2819 other.mDurationsTable = mStats.mAddLongTable; 2820 other.mDurationsTableSize = mStats.mAddLongTableSize; 2821 } else { 2822 other.mDurationsTable = null; 2823 other.mDurationsTableSize = 0; 2824 } 2825 } 2826 2827 void addDurations(DurationsTable other) { 2828 for (int i=0; i<other.mDurationsTableSize; i++) { 2829 int ent = other.mDurationsTable[i]; 2830 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2831 if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration " 2832 + other.mStats.getLong(ent, 0)); 2833 addDuration(state, other.mStats.getLong(ent, 0)); 2834 } 2835 } 2836 2837 void resetDurationsSafely() { 2838 mDurationsTable = null; 2839 mDurationsTableSize = 0; 2840 } 2841 2842 void writeDurationsToParcel(Parcel out) { 2843 out.writeInt(mDurationsTableSize); 2844 for (int i=0; i<mDurationsTableSize; i++) { 2845 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": " 2846 + printLongOffset(mDurationsTable[i])); 2847 out.writeInt(mDurationsTable[i]); 2848 } 2849 } 2850 2851 boolean readDurationsFromParcel(Parcel in) { 2852 mDurationsTable = mStats.readTableFromParcel(in, mName, "durations"); 2853 if (mDurationsTable == BAD_TABLE) { 2854 return false; 2855 } 2856 mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0; 2857 return true; 2858 } 2859 2860 void addDuration(int state, long dur) { 2861 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state); 2862 int off; 2863 if (idx >= 0) { 2864 off = mDurationsTable[idx]; 2865 } else { 2866 mStats.mAddLongTable = mDurationsTable; 2867 mStats.mAddLongTableSize = mDurationsTableSize; 2868 off = mStats.addLongData(~idx, state, 1); 2869 mDurationsTable = mStats.mAddLongTable; 2870 mDurationsTableSize = mStats.mAddLongTableSize; 2871 } 2872 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 2873 if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur 2874 + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]); 2875 longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur; 2876 } 2877 2878 long getDuration(int state, long now) { 2879 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state); 2880 return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0; 2881 } 2882 } 2883 2884 final public static class ProcessStateHolder { 2885 public final int appVersion; 2886 public ProcessStats.ProcessState state; 2887 2888 public ProcessStateHolder(int _appVersion) { 2889 appVersion = _appVersion; 2890 } 2891 } 2892 2893 public static final class ProcessState extends DurationsTable { 2894 public ProcessState mCommonProcess; 2895 public final String mPackage; 2896 public final int mUid; 2897 public final int mVersion; 2898 2899 //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT]; 2900 int mCurState = STATE_NOTHING; 2901 long mStartTime; 2902 2903 int mLastPssState = STATE_NOTHING; 2904 long mLastPssTime; 2905 int[] mPssTable; 2906 int mPssTableSize; 2907 2908 boolean mActive; 2909 int mNumActiveServices; 2910 int mNumStartedServices; 2911 2912 int mNumExcessiveWake; 2913 int mNumExcessiveCpu; 2914 2915 int mNumCachedKill; 2916 long mMinCachedKillPss; 2917 long mAvgCachedKillPss; 2918 long mMaxCachedKillPss; 2919 2920 boolean mMultiPackage; 2921 boolean mDead; 2922 2923 public long mTmpTotalTime; 2924 int mTmpNumInUse; 2925 ProcessState mTmpFoundSubProc; 2926 2927 /** 2928 * Create a new top-level process state, for the initial case where there is only 2929 * a single package running in a process. The initial state is not running. 2930 */ 2931 public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) { 2932 super(processStats, name); 2933 mCommonProcess = this; 2934 mPackage = pkg; 2935 mUid = uid; 2936 mVersion = vers; 2937 } 2938 2939 /** 2940 * Create a new per-package process state for an existing top-level process 2941 * state. The current running state of the top-level process is also copied, 2942 * marked as started running at 'now'. 2943 */ 2944 public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name, 2945 long now) { 2946 super(commonProcess.mStats, name); 2947 mCommonProcess = commonProcess; 2948 mPackage = pkg; 2949 mUid = uid; 2950 mVersion = vers; 2951 mCurState = commonProcess.mCurState; 2952 mStartTime = now; 2953 } 2954 2955 ProcessState clone(String pkg, long now) { 2956 ProcessState pnew = new ProcessState(this, pkg, mUid, mVersion, mName, now); 2957 copyDurationsTo(pnew); 2958 if (mPssTable != null) { 2959 mStats.mAddLongTable = new int[mPssTable.length]; 2960 mStats.mAddLongTableSize = 0; 2961 for (int i=0; i<mPssTableSize; i++) { 2962 int origEnt = mPssTable[i]; 2963 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2964 int newOff = mStats.addLongData(i, type, PSS_COUNT); 2965 mStats.mAddLongTable[i] = newOff | type; 2966 for (int j=0; j<PSS_COUNT; j++) { 2967 mStats.setLong(newOff, j, mStats.getLong(origEnt, j)); 2968 } 2969 } 2970 pnew.mPssTable = mStats.mAddLongTable; 2971 pnew.mPssTableSize = mStats.mAddLongTableSize; 2972 } 2973 pnew.mNumExcessiveWake = mNumExcessiveWake; 2974 pnew.mNumExcessiveCpu = mNumExcessiveCpu; 2975 pnew.mNumCachedKill = mNumCachedKill; 2976 pnew.mMinCachedKillPss = mMinCachedKillPss; 2977 pnew.mAvgCachedKillPss = mAvgCachedKillPss; 2978 pnew.mMaxCachedKillPss = mMaxCachedKillPss; 2979 pnew.mActive = mActive; 2980 pnew.mNumActiveServices = mNumActiveServices; 2981 pnew.mNumStartedServices = mNumStartedServices; 2982 return pnew; 2983 } 2984 2985 void add(ProcessState other) { 2986 addDurations(other); 2987 for (int i=0; i<other.mPssTableSize; i++) { 2988 int ent = other.mPssTable[i]; 2989 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2990 addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT), 2991 other.mStats.getLong(ent, PSS_MINIMUM), 2992 other.mStats.getLong(ent, PSS_AVERAGE), 2993 other.mStats.getLong(ent, PSS_MAXIMUM), 2994 other.mStats.getLong(ent, PSS_USS_MINIMUM), 2995 other.mStats.getLong(ent, PSS_USS_AVERAGE), 2996 other.mStats.getLong(ent, PSS_USS_MAXIMUM)); 2997 } 2998 mNumExcessiveWake += other.mNumExcessiveWake; 2999 mNumExcessiveCpu += other.mNumExcessiveCpu; 3000 if (other.mNumCachedKill > 0) { 3001 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss, 3002 other.mAvgCachedKillPss, other.mMaxCachedKillPss); 3003 } 3004 } 3005 3006 void resetSafely(long now) { 3007 resetDurationsSafely(); 3008 mStartTime = now; 3009 mLastPssState = STATE_NOTHING; 3010 mLastPssTime = 0; 3011 mPssTable = null; 3012 mPssTableSize = 0; 3013 mNumExcessiveWake = 0; 3014 mNumExcessiveCpu = 0; 3015 mNumCachedKill = 0; 3016 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0; 3017 } 3018 3019 void makeDead() { 3020 mDead = true; 3021 } 3022 3023 private void ensureNotDead() { 3024 if (!mDead) { 3025 return; 3026 } 3027 Slog.wtfStack(TAG, "ProcessState dead: name=" + mName 3028 + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName); 3029 } 3030 3031 void writeToParcel(Parcel out, long now) { 3032 out.writeInt(mMultiPackage ? 1 : 0); 3033 writeDurationsToParcel(out); 3034 out.writeInt(mPssTableSize); 3035 for (int i=0; i<mPssTableSize; i++) { 3036 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": " 3037 + printLongOffset(mPssTable[i])); 3038 out.writeInt(mPssTable[i]); 3039 } 3040 out.writeInt(mNumExcessiveWake); 3041 out.writeInt(mNumExcessiveCpu); 3042 out.writeInt(mNumCachedKill); 3043 if (mNumCachedKill > 0) { 3044 out.writeLong(mMinCachedKillPss); 3045 out.writeLong(mAvgCachedKillPss); 3046 out.writeLong(mMaxCachedKillPss); 3047 } 3048 } 3049 3050 boolean readFromParcel(Parcel in, boolean fully) { 3051 boolean multiPackage = in.readInt() != 0; 3052 if (fully) { 3053 mMultiPackage = multiPackage; 3054 } 3055 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table..."); 3056 if (!readDurationsFromParcel(in)) { 3057 return false; 3058 } 3059 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table..."); 3060 mPssTable = mStats.readTableFromParcel(in, mName, "pss"); 3061 if (mPssTable == BAD_TABLE) { 3062 return false; 3063 } 3064 mPssTableSize = mPssTable != null ? mPssTable.length : 0; 3065 mNumExcessiveWake = in.readInt(); 3066 mNumExcessiveCpu = in.readInt(); 3067 mNumCachedKill = in.readInt(); 3068 if (mNumCachedKill > 0) { 3069 mMinCachedKillPss = in.readLong(); 3070 mAvgCachedKillPss = in.readLong(); 3071 mMaxCachedKillPss = in.readLong(); 3072 } else { 3073 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0; 3074 } 3075 return true; 3076 } 3077 3078 public void makeActive() { 3079 ensureNotDead(); 3080 mActive = true; 3081 } 3082 3083 public void makeInactive() { 3084 mActive = false; 3085 } 3086 3087 public boolean isInUse() { 3088 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0 3089 || mCurState != STATE_NOTHING; 3090 } 3091 3092 /** 3093 * Update the current state of the given list of processes. 3094 * 3095 * @param state Current ActivityManager.PROCESS_STATE_* 3096 * @param memFactor Current mem factor constant. 3097 * @param now Current time. 3098 * @param pkgList Processes to update. 3099 */ 3100 public void setState(int state, int memFactor, long now, 3101 ArrayMap<String, ProcessStateHolder> pkgList) { 3102 if (state < 0) { 3103 state = mNumStartedServices > 0 3104 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING; 3105 } else { 3106 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT); 3107 } 3108 3109 // First update the common process. 3110 mCommonProcess.setState(state, now); 3111 3112 // If the common process is not multi-package, there is nothing else to do. 3113 if (!mCommonProcess.mMultiPackage) { 3114 return; 3115 } 3116 3117 if (pkgList != null) { 3118 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3119 pullFixedProc(pkgList, ip).setState(state, now); 3120 } 3121 } 3122 } 3123 3124 void setState(int state, long now) { 3125 ensureNotDead(); 3126 if (mCurState != state) { 3127 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state); 3128 commitStateTime(now); 3129 mCurState = state; 3130 } 3131 } 3132 3133 void commitStateTime(long now) { 3134 if (mCurState != STATE_NOTHING) { 3135 long dur = now - mStartTime; 3136 if (dur > 0) { 3137 addDuration(mCurState, dur); 3138 } 3139 } 3140 mStartTime = now; 3141 } 3142 3143 void incActiveServices(String serviceName) { 3144 if (DEBUG && "".equals(mName)) { 3145 RuntimeException here = new RuntimeException("here"); 3146 here.fillInStackTrace(); 3147 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName 3148 + " to " + (mNumActiveServices+1), here); 3149 } 3150 if (mCommonProcess != this) { 3151 mCommonProcess.incActiveServices(serviceName); 3152 } 3153 mNumActiveServices++; 3154 } 3155 3156 void decActiveServices(String serviceName) { 3157 if (DEBUG && "".equals(mName)) { 3158 RuntimeException here = new RuntimeException("here"); 3159 here.fillInStackTrace(); 3160 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName 3161 + " to " + (mNumActiveServices-1), here); 3162 } 3163 if (mCommonProcess != this) { 3164 mCommonProcess.decActiveServices(serviceName); 3165 } 3166 mNumActiveServices--; 3167 if (mNumActiveServices < 0) { 3168 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage 3169 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName); 3170 mNumActiveServices = 0; 3171 } 3172 } 3173 3174 void incStartedServices(int memFactor, long now, String serviceName) { 3175 if (false) { 3176 RuntimeException here = new RuntimeException("here"); 3177 here.fillInStackTrace(); 3178 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName 3179 + " to " + (mNumStartedServices+1), here); 3180 } 3181 if (mCommonProcess != this) { 3182 mCommonProcess.incStartedServices(memFactor, now, serviceName); 3183 } 3184 mNumStartedServices++; 3185 if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) { 3186 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now); 3187 } 3188 } 3189 3190 void decStartedServices(int memFactor, long now, String serviceName) { 3191 if (false) { 3192 RuntimeException here = new RuntimeException("here"); 3193 here.fillInStackTrace(); 3194 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName 3195 + " to " + (mNumStartedServices-1), here); 3196 } 3197 if (mCommonProcess != this) { 3198 mCommonProcess.decStartedServices(memFactor, now, serviceName); 3199 } 3200 mNumStartedServices--; 3201 if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) { 3202 setState(STATE_NOTHING, now); 3203 } else if (mNumStartedServices < 0) { 3204 Slog.wtfStack(TAG, "Proc started services underrun: pkg=" 3205 + mPackage + " uid=" + mUid + " name=" + mName); 3206 mNumStartedServices = 0; 3207 } 3208 } 3209 3210 public void addPss(long pss, long uss, boolean always, 3211 ArrayMap<String, ProcessStateHolder> pkgList) { 3212 ensureNotDead(); 3213 if (!always) { 3214 if (mLastPssState == mCurState && SystemClock.uptimeMillis() 3215 < (mLastPssTime+(30*1000))) { 3216 return; 3217 } 3218 } 3219 mLastPssState = mCurState; 3220 mLastPssTime = SystemClock.uptimeMillis(); 3221 if (mCurState != STATE_NOTHING) { 3222 // First update the common process. 3223 mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss); 3224 3225 // If the common process is not multi-package, there is nothing else to do. 3226 if (!mCommonProcess.mMultiPackage) { 3227 return; 3228 } 3229 3230 if (pkgList != null) { 3231 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3232 pullFixedProc(pkgList, ip).addPss(mCurState, 1, 3233 pss, pss, pss, uss, uss, uss); 3234 } 3235 } 3236 } 3237 } 3238 3239 void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss, 3240 long avgUss, long maxUss) { 3241 int idx = binarySearch(mPssTable, mPssTableSize, state); 3242 int off; 3243 if (idx >= 0) { 3244 off = mPssTable[idx]; 3245 } else { 3246 mStats.mAddLongTable = mPssTable; 3247 mStats.mAddLongTableSize = mPssTableSize; 3248 off = mStats.addLongData(~idx, state, PSS_COUNT); 3249 mPssTable = mStats.mAddLongTable; 3250 mPssTableSize = mStats.mAddLongTableSize; 3251 } 3252 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 3253 idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK; 3254 long count = longs[idx+PSS_SAMPLE_COUNT]; 3255 if (count == 0) { 3256 longs[idx+PSS_SAMPLE_COUNT] = inCount; 3257 longs[idx+PSS_MINIMUM] = minPss; 3258 longs[idx+PSS_AVERAGE] = avgPss; 3259 longs[idx+PSS_MAXIMUM] = maxPss; 3260 longs[idx+PSS_USS_MINIMUM] = minUss; 3261 longs[idx+PSS_USS_AVERAGE] = avgUss; 3262 longs[idx+PSS_USS_MAXIMUM] = maxUss; 3263 } else { 3264 longs[idx+PSS_SAMPLE_COUNT] = count+inCount; 3265 if (longs[idx+PSS_MINIMUM] > minPss) { 3266 longs[idx+PSS_MINIMUM] = minPss; 3267 } 3268 longs[idx+PSS_AVERAGE] = (long)( 3269 ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount)) 3270 / (count+inCount) ); 3271 if (longs[idx+PSS_MAXIMUM] < maxPss) { 3272 longs[idx+PSS_MAXIMUM] = maxPss; 3273 } 3274 if (longs[idx+PSS_USS_MINIMUM] > minUss) { 3275 longs[idx+PSS_USS_MINIMUM] = minUss; 3276 } 3277 longs[idx+PSS_USS_AVERAGE] = (long)( 3278 ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount)) 3279 / (count+inCount) ); 3280 if (longs[idx+PSS_USS_MAXIMUM] < maxUss) { 3281 longs[idx+PSS_USS_MAXIMUM] = maxUss; 3282 } 3283 } 3284 } 3285 3286 public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) { 3287 ensureNotDead(); 3288 mCommonProcess.mNumExcessiveWake++; 3289 if (!mCommonProcess.mMultiPackage) { 3290 return; 3291 } 3292 3293 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3294 pullFixedProc(pkgList, ip).mNumExcessiveWake++; 3295 } 3296 } 3297 3298 public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) { 3299 ensureNotDead(); 3300 mCommonProcess.mNumExcessiveCpu++; 3301 if (!mCommonProcess.mMultiPackage) { 3302 return; 3303 } 3304 3305 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3306 pullFixedProc(pkgList, ip).mNumExcessiveCpu++; 3307 } 3308 } 3309 3310 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) { 3311 if (mNumCachedKill <= 0) { 3312 mNumCachedKill = num; 3313 mMinCachedKillPss = minPss; 3314 mAvgCachedKillPss = avgPss; 3315 mMaxCachedKillPss = maxPss; 3316 } else { 3317 if (minPss < mMinCachedKillPss) { 3318 mMinCachedKillPss = minPss; 3319 } 3320 if (maxPss > mMaxCachedKillPss) { 3321 mMaxCachedKillPss = maxPss; 3322 } 3323 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss) 3324 / (mNumCachedKill+num) ); 3325 mNumCachedKill += num; 3326 } 3327 } 3328 3329 public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) { 3330 ensureNotDead(); 3331 mCommonProcess.addCachedKill(1, pss, pss, pss); 3332 if (!mCommonProcess.mMultiPackage) { 3333 return; 3334 } 3335 3336 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3337 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss); 3338 } 3339 } 3340 3341 ProcessState pullFixedProc(String pkgName) { 3342 if (mMultiPackage) { 3343 // The array map is still pointing to a common process state 3344 // that is now shared across packages. Update it to point to 3345 // the new per-package state. 3346 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid); 3347 if (vpkg == null) { 3348 throw new IllegalStateException("Didn't find package " + pkgName 3349 + " / " + mUid); 3350 } 3351 PackageState pkg = vpkg.get(mVersion); 3352 if (pkg == null) { 3353 throw new IllegalStateException("Didn't find package " + pkgName 3354 + " / " + mUid + " vers " + mVersion); 3355 } 3356 ProcessState proc = pkg.mProcesses.get(mName); 3357 if (proc == null) { 3358 throw new IllegalStateException("Didn't create per-package process " 3359 + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion); 3360 } 3361 return proc; 3362 } 3363 return this; 3364 } 3365 3366 private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList, 3367 int index) { 3368 ProcessStateHolder holder = pkgList.valueAt(index); 3369 ProcessState proc = holder.state; 3370 if (mDead && proc.mCommonProcess != proc) { 3371 // Somehow we are contining to use a process state that is dead, because 3372 // it was not being told it was active during the last commit. We can recover 3373 // from this by generating a fresh new state, but this is bad because we 3374 // are losing whatever data we had in the old process state. 3375 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage 3376 + " uid=" + mUid + " common.name=" + mCommonProcess.mName); 3377 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion, 3378 proc.mName); 3379 } 3380 if (proc.mMultiPackage) { 3381 // The array map is still pointing to a common process state 3382 // that is now shared across packages. Update it to point to 3383 // the new per-package state. 3384 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index), 3385 proc.mUid); 3386 if (vpkg == null) { 3387 throw new IllegalStateException("No existing package " 3388 + pkgList.keyAt(index) + "/" + proc.mUid 3389 + " for multi-proc " + proc.mName); 3390 } 3391 PackageState pkg = vpkg.get(proc.mVersion); 3392 if (pkg == null) { 3393 throw new IllegalStateException("No existing package " 3394 + pkgList.keyAt(index) + "/" + proc.mUid 3395 + " for multi-proc " + proc.mName + " version " + proc.mVersion); 3396 } 3397 proc = pkg.mProcesses.get(proc.mName); 3398 if (proc == null) { 3399 throw new IllegalStateException("Didn't create per-package process " 3400 + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid); 3401 } 3402 holder.state = proc; 3403 } 3404 return proc; 3405 } 3406 3407 long getDuration(int state, long now) { 3408 long time = super.getDuration(state, now); 3409 if (mCurState == state) { 3410 time += now - mStartTime; 3411 } 3412 return time; 3413 } 3414 3415 long getPssSampleCount(int state) { 3416 int idx = binarySearch(mPssTable, mPssTableSize, state); 3417 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0; 3418 } 3419 3420 long getPssMinimum(int state) { 3421 int idx = binarySearch(mPssTable, mPssTableSize, state); 3422 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0; 3423 } 3424 3425 long getPssAverage(int state) { 3426 int idx = binarySearch(mPssTable, mPssTableSize, state); 3427 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0; 3428 } 3429 3430 long getPssMaximum(int state) { 3431 int idx = binarySearch(mPssTable, mPssTableSize, state); 3432 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0; 3433 } 3434 3435 long getPssUssMinimum(int state) { 3436 int idx = binarySearch(mPssTable, mPssTableSize, state); 3437 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0; 3438 } 3439 3440 long getPssUssAverage(int state) { 3441 int idx = binarySearch(mPssTable, mPssTableSize, state); 3442 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0; 3443 } 3444 3445 long getPssUssMaximum(int state) { 3446 int idx = binarySearch(mPssTable, mPssTableSize, state); 3447 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0; 3448 } 3449 3450 public String toString() { 3451 StringBuilder sb = new StringBuilder(128); 3452 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this))) 3453 .append(" ").append(mName).append("/").append(mUid) 3454 .append(" pkg=").append(mPackage); 3455 if (mMultiPackage) sb.append(" (multi)"); 3456 if (mCommonProcess != this) sb.append(" (sub)"); 3457 sb.append("}"); 3458 return sb.toString(); 3459 } 3460 } 3461 3462 public static final class ServiceState extends DurationsTable { 3463 public final String mPackage; 3464 public final String mProcessName; 3465 ProcessState mProc; 3466 3467 Object mOwner; 3468 3469 public static final int SERVICE_RUN = 0; 3470 public static final int SERVICE_STARTED = 1; 3471 public static final int SERVICE_BOUND = 2; 3472 public static final int SERVICE_EXEC = 3; 3473 static final int SERVICE_COUNT = 4; 3474 3475 int mRunCount; 3476 public int mRunState = STATE_NOTHING; 3477 long mRunStartTime; 3478 3479 boolean mStarted; 3480 boolean mRestarting; 3481 int mStartedCount; 3482 public int mStartedState = STATE_NOTHING; 3483 long mStartedStartTime; 3484 3485 int mBoundCount; 3486 public int mBoundState = STATE_NOTHING; 3487 long mBoundStartTime; 3488 3489 int mExecCount; 3490 public int mExecState = STATE_NOTHING; 3491 long mExecStartTime; 3492 3493 public ServiceState(ProcessStats processStats, String pkg, String name, 3494 String processName, ProcessState proc) { 3495 super(processStats, name); 3496 mPackage = pkg; 3497 mProcessName = processName; 3498 mProc = proc; 3499 } 3500 3501 public void applyNewOwner(Object newOwner) { 3502 if (mOwner != newOwner) { 3503 if (mOwner == null) { 3504 mOwner = newOwner; 3505 mProc.incActiveServices(mName); 3506 } else { 3507 // There was already an old owner, reset this object for its 3508 // new owner. 3509 mOwner = newOwner; 3510 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { 3511 long now = SystemClock.uptimeMillis(); 3512 if (mStarted) { 3513 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner 3514 + " from " + mOwner + " while started: pkg=" 3515 + mPackage + " service=" + mName + " proc=" + mProc); 3516 setStarted(false, 0, now); 3517 } 3518 if (mBoundState != STATE_NOTHING) { 3519 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner 3520 + " from " + mOwner + " while bound: pkg=" 3521 + mPackage + " service=" + mName + " proc=" + mProc); 3522 setBound(false, 0, now); 3523 } 3524 if (mExecState != STATE_NOTHING) { 3525 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner 3526 + " from " + mOwner + " while executing: pkg=" 3527 + mPackage + " service=" + mName + " proc=" + mProc); 3528 setExecuting(false, 0, now); 3529 } 3530 } 3531 } 3532 } 3533 } 3534 3535 public void clearCurrentOwner(Object owner, boolean silently) { 3536 if (mOwner == owner) { 3537 mProc.decActiveServices(mName); 3538 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { 3539 long now = SystemClock.uptimeMillis(); 3540 if (mStarted) { 3541 if (!silently) { 3542 Slog.wtfStack(TAG, "Service owner " + owner 3543 + " cleared while started: pkg=" + mPackage + " service=" 3544 + mName + " proc=" + mProc); 3545 } 3546 setStarted(false, 0, now); 3547 } 3548 if (mBoundState != STATE_NOTHING) { 3549 if (!silently) { 3550 Slog.wtfStack(TAG, "Service owner " + owner 3551 + " cleared while bound: pkg=" + mPackage + " service=" 3552 + mName + " proc=" + mProc); 3553 } 3554 setBound(false, 0, now); 3555 } 3556 if (mExecState != STATE_NOTHING) { 3557 if (!silently) { 3558 Slog.wtfStack(TAG, "Service owner " + owner 3559 + " cleared while exec: pkg=" + mPackage + " service=" 3560 + mName + " proc=" + mProc); 3561 } 3562 setExecuting(false, 0, now); 3563 } 3564 } 3565 mOwner = null; 3566 } 3567 } 3568 3569 public boolean isInUse() { 3570 return mOwner != null || mRestarting; 3571 } 3572 3573 public boolean isRestarting() { 3574 return mRestarting; 3575 } 3576 3577 void add(ServiceState other) { 3578 addDurations(other); 3579 mRunCount += other.mRunCount; 3580 mStartedCount += other.mStartedCount; 3581 mBoundCount += other.mBoundCount; 3582 mExecCount += other.mExecCount; 3583 } 3584 3585 void resetSafely(long now) { 3586 resetDurationsSafely(); 3587 mRunCount = mRunState != STATE_NOTHING ? 1 : 0; 3588 mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0; 3589 mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0; 3590 mExecCount = mExecState != STATE_NOTHING ? 1 : 0; 3591 mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now; 3592 } 3593 3594 void writeToParcel(Parcel out, long now) { 3595 writeDurationsToParcel(out); 3596 out.writeInt(mRunCount); 3597 out.writeInt(mStartedCount); 3598 out.writeInt(mBoundCount); 3599 out.writeInt(mExecCount); 3600 } 3601 3602 boolean readFromParcel(Parcel in) { 3603 if (!readDurationsFromParcel(in)) { 3604 return false; 3605 } 3606 mRunCount = in.readInt(); 3607 mStartedCount = in.readInt(); 3608 mBoundCount = in.readInt(); 3609 mExecCount = in.readInt(); 3610 return true; 3611 } 3612 3613 void commitStateTime(long now) { 3614 if (mRunState != STATE_NOTHING) { 3615 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime); 3616 mRunStartTime = now; 3617 } 3618 if (mStartedState != STATE_NOTHING) { 3619 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT), 3620 now - mStartedStartTime); 3621 mStartedStartTime = now; 3622 } 3623 if (mBoundState != STATE_NOTHING) { 3624 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime); 3625 mBoundStartTime = now; 3626 } 3627 if (mExecState != STATE_NOTHING) { 3628 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime); 3629 mExecStartTime = now; 3630 } 3631 } 3632 3633 private void updateRunning(int memFactor, long now) { 3634 final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING 3635 || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING; 3636 if (mRunState != state) { 3637 if (mRunState != STATE_NOTHING) { 3638 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), 3639 now - mRunStartTime); 3640 } else if (state != STATE_NOTHING) { 3641 mRunCount++; 3642 } 3643 mRunState = state; 3644 mRunStartTime = now; 3645 } 3646 } 3647 3648 public void setStarted(boolean started, int memFactor, long now) { 3649 if (mOwner == null) { 3650 Slog.wtf(TAG, "Starting service " + this + " without owner"); 3651 } 3652 mStarted = started; 3653 updateStartedState(memFactor, now); 3654 } 3655 3656 public void setRestarting(boolean restarting, int memFactor, long now) { 3657 mRestarting = restarting; 3658 updateStartedState(memFactor, now); 3659 } 3660 3661 void updateStartedState(int memFactor, long now) { 3662 final boolean wasStarted = mStartedState != STATE_NOTHING; 3663 final boolean started = mStarted || mRestarting; 3664 final int state = started ? memFactor : STATE_NOTHING; 3665 if (mStartedState != state) { 3666 if (mStartedState != STATE_NOTHING) { 3667 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT), 3668 now - mStartedStartTime); 3669 } else if (started) { 3670 mStartedCount++; 3671 } 3672 mStartedState = state; 3673 mStartedStartTime = now; 3674 mProc = mProc.pullFixedProc(mPackage); 3675 if (wasStarted != started) { 3676 if (started) { 3677 mProc.incStartedServices(memFactor, now, mName); 3678 } else { 3679 mProc.decStartedServices(memFactor, now, mName); 3680 } 3681 } 3682 updateRunning(memFactor, now); 3683 } 3684 } 3685 3686 public void setBound(boolean bound, int memFactor, long now) { 3687 if (mOwner == null) { 3688 Slog.wtf(TAG, "Binding service " + this + " without owner"); 3689 } 3690 final int state = bound ? memFactor : STATE_NOTHING; 3691 if (mBoundState != state) { 3692 if (mBoundState != STATE_NOTHING) { 3693 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), 3694 now - mBoundStartTime); 3695 } else if (bound) { 3696 mBoundCount++; 3697 } 3698 mBoundState = state; 3699 mBoundStartTime = now; 3700 updateRunning(memFactor, now); 3701 } 3702 } 3703 3704 public void setExecuting(boolean executing, int memFactor, long now) { 3705 if (mOwner == null) { 3706 Slog.wtf(TAG, "Executing service " + this + " without owner"); 3707 } 3708 final int state = executing ? memFactor : STATE_NOTHING; 3709 if (mExecState != state) { 3710 if (mExecState != STATE_NOTHING) { 3711 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime); 3712 } else if (executing) { 3713 mExecCount++; 3714 } 3715 mExecState = state; 3716 mExecStartTime = now; 3717 updateRunning(memFactor, now); 3718 } 3719 } 3720 3721 private long getDuration(int opType, int curState, long startTime, int memFactor, 3722 long now) { 3723 int state = opType + (memFactor*SERVICE_COUNT); 3724 long time = getDuration(state, now); 3725 if (curState == memFactor) { 3726 time += now - startTime; 3727 } 3728 return time; 3729 } 3730 3731 public String toString() { 3732 return "ServiceState{" + Integer.toHexString(System.identityHashCode(this)) 3733 + " " + mName + " pkg=" + mPackage + " proc=" 3734 + Integer.toHexString(System.identityHashCode(this)) + "}"; 3735 } 3736 } 3737 3738 public static final class PackageState { 3739 public final ArrayMap<String, ProcessState> mProcesses 3740 = new ArrayMap<String, ProcessState>(); 3741 public final ArrayMap<String, ServiceState> mServices 3742 = new ArrayMap<String, ServiceState>(); 3743 public final String mPackageName; 3744 public final int mUid; 3745 3746 public PackageState(String packageName, int uid) { 3747 mUid = uid; 3748 mPackageName = packageName; 3749 } 3750 } 3751 3752 public static final class ProcessDataCollection { 3753 final int[] screenStates; 3754 final int[] memStates; 3755 final int[] procStates; 3756 3757 public long totalTime; 3758 public long numPss; 3759 public long minPss; 3760 public long avgPss; 3761 public long maxPss; 3762 public long minUss; 3763 public long avgUss; 3764 public long maxUss; 3765 3766 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) { 3767 screenStates = _screenStates; 3768 memStates = _memStates; 3769 procStates = _procStates; 3770 } 3771 3772 void print(PrintWriter pw, long overallTime, boolean full) { 3773 if (totalTime > overallTime) { 3774 pw.print("*"); 3775 } 3776 printPercent(pw, (double) totalTime / (double) overallTime); 3777 if (numPss > 0) { 3778 pw.print(" ("); 3779 printSizeValue(pw, minPss * 1024); 3780 pw.print("-"); 3781 printSizeValue(pw, avgPss * 1024); 3782 pw.print("-"); 3783 printSizeValue(pw, maxPss * 1024); 3784 pw.print("/"); 3785 printSizeValue(pw, minUss * 1024); 3786 pw.print("-"); 3787 printSizeValue(pw, avgUss * 1024); 3788 pw.print("-"); 3789 printSizeValue(pw, maxUss * 1024); 3790 if (full) { 3791 pw.print(" over "); 3792 pw.print(numPss); 3793 } 3794 pw.print(")"); 3795 } 3796 } 3797 } 3798 3799 public static class TotalMemoryUseCollection { 3800 final int[] screenStates; 3801 final int[] memStates; 3802 3803 public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) { 3804 screenStates = _screenStates; 3805 memStates = _memStates; 3806 } 3807 3808 public long totalTime; 3809 public long[] processStatePss = new long[STATE_COUNT]; 3810 public double[] processStateWeight = new double[STATE_COUNT]; 3811 public long[] processStateTime = new long[STATE_COUNT]; 3812 public int[] processStateSamples = new int[STATE_COUNT]; 3813 public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT]; 3814 public double sysMemCachedWeight; 3815 public double sysMemFreeWeight; 3816 public double sysMemZRamWeight; 3817 public double sysMemKernelWeight; 3818 public double sysMemNativeWeight; 3819 public int sysMemSamples; 3820 } 3821} 3822