1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.app; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 import android.os.SystemClock; 22 import android.os.SystemProperties; 23 import android.os.UserHandle; 24 import android.text.format.DateFormat; 25 import android.util.ArrayMap; 26 import android.util.ArraySet; 27 import android.util.Log; 28 import android.util.Slog; 29 import android.util.SparseArray; 30 import android.util.TimeUtils; 31 32 import com.android.internal.util.GrowingArrayUtils; 33 34 import dalvik.system.VMRuntime; 35 import libcore.util.EmptyArray; 36 37 import java.io.IOException; 38 import java.io.InputStream; 39 import java.io.PrintWriter; 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.Collections; 43 import java.util.Comparator; 44 import java.util.Objects; 45 46 public 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 double percentage = (double) totals.totalTime / (double) totalTime * 100; 1083 // We don't print percentages < .01, so just drop those. 1084 if (percentage >= 0.005 || totals.numPss != 0) { 1085 if (prefix != null) { 1086 pw.print(prefix); 1087 } 1088 if (label != null) { 1089 pw.print(label); 1090 } 1091 totals.print(pw, totalTime, full); 1092 if (prefix != null) { 1093 pw.println(); 1094 } 1095 } 1096 } 1097 1098 static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, 1099 ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates, 1100 boolean inclUidVers, long now, long totalTime) { 1101 for (int i=procs.size()-1; i>=0; i--) { 1102 ProcessState proc = procs.get(i); 1103 pw.print(prefix); 1104 pw.print("* "); 1105 pw.print(proc.mName); 1106 pw.print(" / "); 1107 UserHandle.formatUid(pw, proc.mUid); 1108 pw.print(" / v"); 1109 pw.print(proc.mVersion); 1110 pw.println(":"); 1111 dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates, 1112 procStates, now, totalTime, true); 1113 dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates, 1114 new int[] { STATE_PERSISTENT }, now, totalTime, true); 1115 dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates, 1116 new int[] {STATE_TOP}, now, totalTime, true); 1117 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Fg: ", screenStates, memStates, 1118 new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true); 1119 dumpProcessSummaryDetails(pw, proc, prefix, " Imp Bg: ", screenStates, memStates, 1120 new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true); 1121 dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates, 1122 new int[] {STATE_BACKUP}, now, totalTime, true); 1123 dumpProcessSummaryDetails(pw, proc, prefix, " Heavy Wgt: ", screenStates, memStates, 1124 new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true); 1125 dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates, 1126 new int[] {STATE_SERVICE}, now, totalTime, true); 1127 dumpProcessSummaryDetails(pw, proc, prefix, " Service Rs: ", screenStates, memStates, 1128 new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true); 1129 dumpProcessSummaryDetails(pw, proc, prefix, " Receiver: ", screenStates, memStates, 1130 new int[] {STATE_RECEIVER}, now, totalTime, true); 1131 dumpProcessSummaryDetails(pw, proc, prefix, " (Home): ", screenStates, memStates, 1132 new int[] {STATE_HOME}, now, totalTime, true); 1133 dumpProcessSummaryDetails(pw, proc, prefix, " (Last Act): ", screenStates, memStates, 1134 new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true); 1135 dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates, 1136 new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT, 1137 STATE_CACHED_EMPTY}, now, totalTime, true); 1138 } 1139 } 1140 1141 static void printPercent(PrintWriter pw, double fraction) { 1142 fraction *= 100; 1143 if (fraction < 1) { 1144 pw.print(String.format("%.2f", fraction)); 1145 } else if (fraction < 10) { 1146 pw.print(String.format("%.1f", fraction)); 1147 } else { 1148 pw.print(String.format("%.0f", fraction)); 1149 } 1150 pw.print("%"); 1151 } 1152 1153 static void printSizeValue(PrintWriter pw, long number) { 1154 float result = number; 1155 String suffix = ""; 1156 if (result > 900) { 1157 suffix = "KB"; 1158 result = result / 1024; 1159 } 1160 if (result > 900) { 1161 suffix = "MB"; 1162 result = result / 1024; 1163 } 1164 if (result > 900) { 1165 suffix = "GB"; 1166 result = result / 1024; 1167 } 1168 if (result > 900) { 1169 suffix = "TB"; 1170 result = result / 1024; 1171 } 1172 if (result > 900) { 1173 suffix = "PB"; 1174 result = result / 1024; 1175 } 1176 String value; 1177 if (result < 1) { 1178 value = String.format("%.2f", result); 1179 } else if (result < 10) { 1180 value = String.format("%.1f", result); 1181 } else if (result < 100) { 1182 value = String.format("%.0f", result); 1183 } else { 1184 value = String.format("%.0f", result); 1185 } 1186 pw.print(value); 1187 pw.print(suffix); 1188 } 1189 1190 public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs, 1191 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, 1192 boolean sepProcStates, int[] procStates, long now) { 1193 pw.print("process"); 1194 pw.print(CSV_SEP); 1195 pw.print("uid"); 1196 pw.print(CSV_SEP); 1197 pw.print("vers"); 1198 dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null, 1199 sepMemStates ? memStates : null, 1200 sepProcStates ? procStates : null); 1201 pw.println(); 1202 for (int i=procs.size()-1; i>=0; i--) { 1203 ProcessState proc = procs.get(i); 1204 pw.print(proc.mName); 1205 pw.print(CSV_SEP); 1206 UserHandle.formatUid(pw, proc.mUid); 1207 pw.print(CSV_SEP); 1208 pw.print(proc.mVersion); 1209 dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates, 1210 sepMemStates, memStates, sepProcStates, procStates, now); 1211 pw.println(); 1212 } 1213 } 1214 1215 static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) { 1216 int index = value/mod; 1217 if (index >= 0 && index < array.length) { 1218 pw.print(array[index]); 1219 } else { 1220 pw.print('?'); 1221 } 1222 return value - index*mod; 1223 } 1224 1225 static void printProcStateTag(PrintWriter pw, int state) { 1226 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT); 1227 state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT); 1228 printArrayEntry(pw, STATE_TAGS, state, 1); 1229 } 1230 1231 static void printAdjTag(PrintWriter pw, int state) { 1232 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD); 1233 printArrayEntry(pw, ADJ_MEM_TAGS, state, 1); 1234 } 1235 1236 static void printProcStateTagAndValue(PrintWriter pw, int state, long value) { 1237 pw.print(','); 1238 printProcStateTag(pw, state); 1239 pw.print(':'); 1240 pw.print(value); 1241 } 1242 1243 static void printAdjTagAndValue(PrintWriter pw, int state, long value) { 1244 pw.print(','); 1245 printAdjTag(pw, state); 1246 pw.print(':'); 1247 pw.print(value); 1248 } 1249 1250 static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) { 1251 boolean didCurState = false; 1252 for (int i=0; i<proc.mDurationsTableSize; i++) { 1253 int off = proc.mDurationsTable[i]; 1254 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 1255 long time = proc.mStats.getLong(off, 0); 1256 if (proc.mCurState == type) { 1257 didCurState = true; 1258 time += now - proc.mStartTime; 1259 } 1260 printProcStateTagAndValue(pw, type, time); 1261 } 1262 if (!didCurState && proc.mCurState != STATE_NOTHING) { 1263 printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime); 1264 } 1265 } 1266 1267 static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) { 1268 for (int i=0; i<proc.mPssTableSize; i++) { 1269 int off = proc.mPssTable[i]; 1270 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 1271 long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT); 1272 long min = proc.mStats.getLong(off, PSS_MINIMUM); 1273 long avg = proc.mStats.getLong(off, PSS_AVERAGE); 1274 long max = proc.mStats.getLong(off, PSS_MAXIMUM); 1275 long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM); 1276 long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE); 1277 long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM); 1278 pw.print(','); 1279 printProcStateTag(pw, type); 1280 pw.print(':'); 1281 pw.print(count); 1282 pw.print(':'); 1283 pw.print(min); 1284 pw.print(':'); 1285 pw.print(avg); 1286 pw.print(':'); 1287 pw.print(max); 1288 pw.print(':'); 1289 pw.print(umin); 1290 pw.print(':'); 1291 pw.print(uavg); 1292 pw.print(':'); 1293 pw.print(umax); 1294 } 1295 } 1296 1297 public void reset() { 1298 if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr); 1299 resetCommon(); 1300 mPackages.getMap().clear(); 1301 mProcesses.getMap().clear(); 1302 mMemFactor = STATE_NOTHING; 1303 mStartTime = 0; 1304 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr); 1305 } 1306 1307 public void resetSafely() { 1308 if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr); 1309 resetCommon(); 1310 1311 // First initialize use count of all common processes. 1312 final long now = SystemClock.uptimeMillis(); 1313 final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 1314 for (int ip=procMap.size()-1; ip>=0; ip--) { 1315 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 1316 for (int iu=uids.size()-1; iu>=0; iu--) { 1317 uids.valueAt(iu).mTmpNumInUse = 0; 1318 } 1319 } 1320 1321 // Next reset or prune all per-package processes, and for the ones that are reset 1322 // track this back to the common processes. 1323 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1324 for (int ip=pkgMap.size()-1; ip>=0; ip--) { 1325 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1326 for (int iu=uids.size()-1; iu>=0; iu--) { 1327 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1328 for (int iv=vpkgs.size()-1; iv>=0; iv--) { 1329 final PackageState pkgState = vpkgs.valueAt(iv); 1330 for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) { 1331 final ProcessState ps = pkgState.mProcesses.valueAt(iproc); 1332 if (ps.isInUse()) { 1333 ps.resetSafely(now); 1334 ps.mCommonProcess.mTmpNumInUse++; 1335 ps.mCommonProcess.mTmpFoundSubProc = ps; 1336 } else { 1337 pkgState.mProcesses.valueAt(iproc).makeDead(); 1338 pkgState.mProcesses.removeAt(iproc); 1339 } 1340 } 1341 for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) { 1342 final ServiceState ss = pkgState.mServices.valueAt(isvc); 1343 if (ss.isInUse()) { 1344 ss.resetSafely(now); 1345 } else { 1346 pkgState.mServices.removeAt(isvc); 1347 } 1348 } 1349 if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) { 1350 vpkgs.removeAt(iv); 1351 } 1352 } 1353 if (vpkgs.size() <= 0) { 1354 uids.removeAt(iu); 1355 } 1356 } 1357 if (uids.size() <= 0) { 1358 pkgMap.removeAt(ip); 1359 } 1360 } 1361 1362 // Finally prune out any common processes that are no longer in use. 1363 for (int ip=procMap.size()-1; ip>=0; ip--) { 1364 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 1365 for (int iu=uids.size()-1; iu>=0; iu--) { 1366 ProcessState ps = uids.valueAt(iu); 1367 if (ps.isInUse() || ps.mTmpNumInUse > 0) { 1368 // If this is a process for multiple packages, we could at this point 1369 // be back down to one package. In that case, we want to revert back 1370 // to a single shared ProcessState. We can do this by converting the 1371 // current package-specific ProcessState up to the shared ProcessState, 1372 // throwing away the current one we have here (because nobody else is 1373 // using it). 1374 if (!ps.mActive && ps.mMultiPackage && ps.mTmpNumInUse == 1) { 1375 // Here we go... 1376 ps = ps.mTmpFoundSubProc; 1377 ps.mCommonProcess = ps; 1378 uids.setValueAt(iu, ps); 1379 } else { 1380 ps.resetSafely(now); 1381 } 1382 } else { 1383 ps.makeDead(); 1384 uids.removeAt(iu); 1385 } 1386 } 1387 if (uids.size() <= 0) { 1388 procMap.removeAt(ip); 1389 } 1390 } 1391 1392 mStartTime = now; 1393 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr); 1394 } 1395 1396 private void resetCommon() { 1397 mTimePeriodStartClock = System.currentTimeMillis(); 1398 buildTimePeriodStartClockStr(); 1399 mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); 1400 mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis(); 1401 mLongs.clear(); 1402 mLongs.add(new long[LONGS_SIZE]); 1403 mNextLong = 0; 1404 Arrays.fill(mMemFactorDurations, 0); 1405 mSysMemUsageTable = null; 1406 mSysMemUsageTableSize = 0; 1407 mStartTime = 0; 1408 mReadError = null; 1409 mFlags = 0; 1410 evaluateSystemProperties(true); 1411 } 1412 1413 public boolean evaluateSystemProperties(boolean update) { 1414 boolean changed = false; 1415 String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2", 1416 VMRuntime.getRuntime().vmLibrary()); 1417 if (!Objects.equals(runtime, mRuntime)) { 1418 changed = true; 1419 if (update) { 1420 mRuntime = runtime; 1421 } 1422 } 1423 return changed; 1424 } 1425 1426 private void buildTimePeriodStartClockStr() { 1427 mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss", 1428 mTimePeriodStartClock).toString(); 1429 } 1430 1431 static final int[] BAD_TABLE = new int[0]; 1432 1433 private int[] readTableFromParcel(Parcel in, String name, String what) { 1434 final int size = in.readInt(); 1435 if (size < 0) { 1436 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table size: " + size); 1437 return BAD_TABLE; 1438 } 1439 if (size == 0) { 1440 return null; 1441 } 1442 final int[] table = new int[size]; 1443 for (int i=0; i<size; i++) { 1444 table[i] = in.readInt(); 1445 if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": " 1446 + ProcessStats.printLongOffset(table[i])); 1447 if (!validateLongOffset(table[i])) { 1448 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: " 1449 + ProcessStats.printLongOffset(table[i])); 1450 return null; 1451 } 1452 } 1453 return table; 1454 } 1455 1456 private void writeCompactedLongArray(Parcel out, long[] array, int num) { 1457 for (int i=0; i<num; i++) { 1458 long val = array[i]; 1459 if (val < 0) { 1460 Slog.w(TAG, "Time val negative: " + val); 1461 val = 0; 1462 } 1463 if (val <= Integer.MAX_VALUE) { 1464 out.writeInt((int)val); 1465 } else { 1466 int top = ~((int)((val>>32)&0x7fffffff)); 1467 int bottom = (int)(val&0xfffffff); 1468 out.writeInt(top); 1469 out.writeInt(bottom); 1470 } 1471 } 1472 } 1473 1474 private void readCompactedLongArray(Parcel in, int version, long[] array, int num) { 1475 if (version <= 10) { 1476 in.readLongArray(array); 1477 return; 1478 } 1479 final int alen = array.length; 1480 if (num > alen) { 1481 throw new RuntimeException("bad array lengths: got " + num + " array is " + alen); 1482 } 1483 int i; 1484 for (i=0; i<num; i++) { 1485 int val = in.readInt(); 1486 if (val >= 0) { 1487 array[i] = val; 1488 } else { 1489 int bottom = in.readInt(); 1490 array[i] = (((long)~val)<<32) | bottom; 1491 } 1492 } 1493 while (i < alen) { 1494 array[i] = 0; 1495 i++; 1496 } 1497 } 1498 1499 private void writeCommonString(Parcel out, String name) { 1500 Integer index = mCommonStringToIndex.get(name); 1501 if (index != null) { 1502 out.writeInt(index); 1503 return; 1504 } 1505 index = mCommonStringToIndex.size(); 1506 mCommonStringToIndex.put(name, index); 1507 out.writeInt(~index); 1508 out.writeString(name); 1509 } 1510 1511 private String readCommonString(Parcel in, int version) { 1512 if (version <= 9) { 1513 return in.readString(); 1514 } 1515 int index = in.readInt(); 1516 if (index >= 0) { 1517 return mIndexToCommonString.get(index); 1518 } 1519 index = ~index; 1520 String name = in.readString(); 1521 while (mIndexToCommonString.size() <= index) { 1522 mIndexToCommonString.add(null); 1523 } 1524 mIndexToCommonString.set(index, name); 1525 return name; 1526 } 1527 1528 @Override 1529 public int describeContents() { 1530 return 0; 1531 } 1532 1533 @Override 1534 public void writeToParcel(Parcel out, int flags) { 1535 writeToParcel(out, SystemClock.uptimeMillis(), flags); 1536 } 1537 1538 /** @hide */ 1539 public void writeToParcel(Parcel out, long now, int flags) { 1540 out.writeInt(MAGIC); 1541 out.writeInt(PARCEL_VERSION); 1542 out.writeInt(STATE_COUNT); 1543 out.writeInt(ADJ_COUNT); 1544 out.writeInt(PSS_COUNT); 1545 out.writeInt(SYS_MEM_USAGE_COUNT); 1546 out.writeInt(LONGS_SIZE); 1547 1548 mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size()); 1549 1550 // First commit all running times. 1551 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 1552 final int NPROC = procMap.size(); 1553 for (int ip=0; ip<NPROC; ip++) { 1554 SparseArray<ProcessState> uids = procMap.valueAt(ip); 1555 final int NUID = uids.size(); 1556 for (int iu=0; iu<NUID; iu++) { 1557 uids.valueAt(iu).commitStateTime(now); 1558 } 1559 } 1560 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1561 final int NPKG = pkgMap.size(); 1562 for (int ip=0; ip<NPKG; ip++) { 1563 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1564 final int NUID = uids.size(); 1565 for (int iu=0; iu<NUID; iu++) { 1566 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1567 final int NVERS = vpkgs.size(); 1568 for (int iv=0; iv<NVERS; iv++) { 1569 PackageState pkgState = vpkgs.valueAt(iv); 1570 final int NPROCS = pkgState.mProcesses.size(); 1571 for (int iproc=0; iproc<NPROCS; iproc++) { 1572 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1573 if (proc.mCommonProcess != proc) { 1574 proc.commitStateTime(now); 1575 } 1576 } 1577 final int NSRVS = pkgState.mServices.size(); 1578 for (int isvc=0; isvc<NSRVS; isvc++) { 1579 pkgState.mServices.valueAt(isvc).commitStateTime(now); 1580 } 1581 } 1582 } 1583 } 1584 1585 out.writeLong(mTimePeriodStartClock); 1586 out.writeLong(mTimePeriodStartRealtime); 1587 out.writeLong(mTimePeriodEndRealtime); 1588 out.writeLong(mTimePeriodStartUptime); 1589 out.writeLong(mTimePeriodEndUptime); 1590 out.writeString(mRuntime); 1591 out.writeInt(mFlags); 1592 1593 out.writeInt(mLongs.size()); 1594 out.writeInt(mNextLong); 1595 for (int i=0; i<(mLongs.size()-1); i++) { 1596 long[] array = mLongs.get(i); 1597 writeCompactedLongArray(out, array, array.length); 1598 } 1599 long[] lastLongs = mLongs.get(mLongs.size() - 1); 1600 writeCompactedLongArray(out, lastLongs, mNextLong); 1601 1602 if (mMemFactor != STATE_NOTHING) { 1603 mMemFactorDurations[mMemFactor] += now - mStartTime; 1604 mStartTime = now; 1605 } 1606 writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length); 1607 1608 out.writeInt(mSysMemUsageTableSize); 1609 for (int i=0; i<mSysMemUsageTableSize; i++) { 1610 if (DEBUG_PARCEL) Slog.i(TAG, "Writing sys mem usage #" + i + ": " 1611 + printLongOffset(mSysMemUsageTable[i])); 1612 out.writeInt(mSysMemUsageTable[i]); 1613 } 1614 1615 out.writeInt(NPROC); 1616 for (int ip=0; ip<NPROC; ip++) { 1617 writeCommonString(out, procMap.keyAt(ip)); 1618 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 1619 final int NUID = uids.size(); 1620 out.writeInt(NUID); 1621 for (int iu=0; iu<NUID; iu++) { 1622 out.writeInt(uids.keyAt(iu)); 1623 final ProcessState proc = uids.valueAt(iu); 1624 writeCommonString(out, proc.mPackage); 1625 out.writeInt(proc.mVersion); 1626 proc.writeToParcel(out, now); 1627 } 1628 } 1629 out.writeInt(NPKG); 1630 for (int ip=0; ip<NPKG; ip++) { 1631 writeCommonString(out, pkgMap.keyAt(ip)); 1632 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1633 final int NUID = uids.size(); 1634 out.writeInt(NUID); 1635 for (int iu=0; iu<NUID; iu++) { 1636 out.writeInt(uids.keyAt(iu)); 1637 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1638 final int NVERS = vpkgs.size(); 1639 out.writeInt(NVERS); 1640 for (int iv=0; iv<NVERS; iv++) { 1641 out.writeInt(vpkgs.keyAt(iv)); 1642 final PackageState pkgState = vpkgs.valueAt(iv); 1643 final int NPROCS = pkgState.mProcesses.size(); 1644 out.writeInt(NPROCS); 1645 for (int iproc=0; iproc<NPROCS; iproc++) { 1646 writeCommonString(out, pkgState.mProcesses.keyAt(iproc)); 1647 final ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1648 if (proc.mCommonProcess == proc) { 1649 // This is the same as the common process we wrote above. 1650 out.writeInt(0); 1651 } else { 1652 // There is separate data for this package's process. 1653 out.writeInt(1); 1654 proc.writeToParcel(out, now); 1655 } 1656 } 1657 final int NSRVS = pkgState.mServices.size(); 1658 out.writeInt(NSRVS); 1659 for (int isvc=0; isvc<NSRVS; isvc++) { 1660 out.writeString(pkgState.mServices.keyAt(isvc)); 1661 final ServiceState svc = pkgState.mServices.valueAt(isvc); 1662 writeCommonString(out, svc.mProcessName); 1663 svc.writeToParcel(out, now); 1664 } 1665 } 1666 } 1667 } 1668 1669 mCommonStringToIndex = null; 1670 } 1671 1672 private boolean readCheckedInt(Parcel in, int val, String what) { 1673 int got; 1674 if ((got=in.readInt()) != val) { 1675 mReadError = "bad " + what + ": " + got; 1676 return false; 1677 } 1678 return true; 1679 } 1680 1681 static byte[] readFully(InputStream stream, int[] outLen) throws IOException { 1682 int pos = 0; 1683 final int initialAvail = stream.available(); 1684 byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384]; 1685 while (true) { 1686 int amt = stream.read(data, pos, data.length-pos); 1687 if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos 1688 + " of avail " + data.length); 1689 if (amt < 0) { 1690 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos 1691 + " len=" + data.length); 1692 outLen[0] = pos; 1693 return data; 1694 } 1695 pos += amt; 1696 if (pos >= data.length) { 1697 byte[] newData = new byte[pos+16384]; 1698 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len " 1699 + newData.length); 1700 System.arraycopy(data, 0, newData, 0, pos); 1701 data = newData; 1702 } 1703 } 1704 } 1705 1706 public void read(InputStream stream) { 1707 try { 1708 int[] len = new int[1]; 1709 byte[] raw = readFully(stream, len); 1710 Parcel in = Parcel.obtain(); 1711 in.unmarshall(raw, 0, len[0]); 1712 in.setDataPosition(0); 1713 stream.close(); 1714 1715 readFromParcel(in); 1716 } catch (IOException e) { 1717 mReadError = "caught exception: " + e; 1718 } 1719 } 1720 1721 public void readFromParcel(Parcel in) { 1722 final boolean hadData = mPackages.getMap().size() > 0 1723 || mProcesses.getMap().size() > 0; 1724 if (hadData) { 1725 resetSafely(); 1726 } 1727 1728 if (!readCheckedInt(in, MAGIC, "magic number")) { 1729 return; 1730 } 1731 int version = in.readInt(); 1732 if (version != PARCEL_VERSION) { 1733 mReadError = "bad version: " + version; 1734 return; 1735 } 1736 if (!readCheckedInt(in, STATE_COUNT, "state count")) { 1737 return; 1738 } 1739 if (!readCheckedInt(in, ADJ_COUNT, "adj count")) { 1740 return; 1741 } 1742 if (!readCheckedInt(in, PSS_COUNT, "pss count")) { 1743 return; 1744 } 1745 if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) { 1746 return; 1747 } 1748 if (!readCheckedInt(in, LONGS_SIZE, "longs size")) { 1749 return; 1750 } 1751 1752 mIndexToCommonString = new ArrayList<String>(); 1753 1754 mTimePeriodStartClock = in.readLong(); 1755 buildTimePeriodStartClockStr(); 1756 mTimePeriodStartRealtime = in.readLong(); 1757 mTimePeriodEndRealtime = in.readLong(); 1758 mTimePeriodStartUptime = in.readLong(); 1759 mTimePeriodEndUptime = in.readLong(); 1760 mRuntime = in.readString(); 1761 mFlags = in.readInt(); 1762 1763 final int NLONGS = in.readInt(); 1764 final int NEXTLONG = in.readInt(); 1765 mLongs.clear(); 1766 for (int i=0; i<(NLONGS-1); i++) { 1767 while (i >= mLongs.size()) { 1768 mLongs.add(new long[LONGS_SIZE]); 1769 } 1770 readCompactedLongArray(in, version, mLongs.get(i), LONGS_SIZE); 1771 } 1772 long[] longs = new long[LONGS_SIZE]; 1773 mNextLong = NEXTLONG; 1774 readCompactedLongArray(in, version, longs, NEXTLONG); 1775 mLongs.add(longs); 1776 1777 readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length); 1778 1779 mSysMemUsageTable = readTableFromParcel(in, TAG, "sys mem usage"); 1780 if (mSysMemUsageTable == BAD_TABLE) { 1781 return; 1782 } 1783 mSysMemUsageTableSize = mSysMemUsageTable != null ? mSysMemUsageTable.length : 0; 1784 1785 int NPROC = in.readInt(); 1786 if (NPROC < 0) { 1787 mReadError = "bad process count: " + NPROC; 1788 return; 1789 } 1790 while (NPROC > 0) { 1791 NPROC--; 1792 final String procName = readCommonString(in, version); 1793 if (procName == null) { 1794 mReadError = "bad process name"; 1795 return; 1796 } 1797 int NUID = in.readInt(); 1798 if (NUID < 0) { 1799 mReadError = "bad uid count: " + NUID; 1800 return; 1801 } 1802 while (NUID > 0) { 1803 NUID--; 1804 final int uid = in.readInt(); 1805 if (uid < 0) { 1806 mReadError = "bad uid: " + uid; 1807 return; 1808 } 1809 final String pkgName = readCommonString(in, version); 1810 if (pkgName == null) { 1811 mReadError = "bad process package name"; 1812 return; 1813 } 1814 final int vers = in.readInt(); 1815 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null; 1816 if (proc != null) { 1817 if (!proc.readFromParcel(in, false)) { 1818 return; 1819 } 1820 } else { 1821 proc = new ProcessState(this, pkgName, uid, vers, procName); 1822 if (!proc.readFromParcel(in, true)) { 1823 return; 1824 } 1825 } 1826 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid 1827 + " " + proc); 1828 mProcesses.put(procName, uid, proc); 1829 } 1830 } 1831 1832 if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes"); 1833 1834 int NPKG = in.readInt(); 1835 if (NPKG < 0) { 1836 mReadError = "bad package count: " + NPKG; 1837 return; 1838 } 1839 while (NPKG > 0) { 1840 NPKG--; 1841 final String pkgName = readCommonString(in, version); 1842 if (pkgName == null) { 1843 mReadError = "bad package name"; 1844 return; 1845 } 1846 int NUID = in.readInt(); 1847 if (NUID < 0) { 1848 mReadError = "bad uid count: " + NUID; 1849 return; 1850 } 1851 while (NUID > 0) { 1852 NUID--; 1853 final int uid = in.readInt(); 1854 if (uid < 0) { 1855 mReadError = "bad uid: " + uid; 1856 return; 1857 } 1858 int NVERS = in.readInt(); 1859 if (NVERS < 0) { 1860 mReadError = "bad versions count: " + NVERS; 1861 return; 1862 } 1863 while (NVERS > 0) { 1864 NVERS--; 1865 final int vers = in.readInt(); 1866 PackageState pkgState = new PackageState(pkgName, uid); 1867 SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid); 1868 if (vpkg == null) { 1869 vpkg = new SparseArray<PackageState>(); 1870 mPackages.put(pkgName, uid, vpkg); 1871 } 1872 vpkg.put(vers, pkgState); 1873 int NPROCS = in.readInt(); 1874 if (NPROCS < 0) { 1875 mReadError = "bad package process count: " + NPROCS; 1876 return; 1877 } 1878 while (NPROCS > 0) { 1879 NPROCS--; 1880 String procName = readCommonString(in, version); 1881 if (procName == null) { 1882 mReadError = "bad package process name"; 1883 return; 1884 } 1885 int hasProc = in.readInt(); 1886 if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid 1887 + " process " + procName + " hasProc=" + hasProc); 1888 ProcessState commonProc = mProcesses.get(procName, uid); 1889 if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid 1890 + ": " + commonProc); 1891 if (commonProc == null) { 1892 mReadError = "no common proc: " + procName; 1893 return; 1894 } 1895 if (hasProc != 0) { 1896 // The process for this package is unique to the package; we 1897 // need to load it. We don't need to do anything about it if 1898 // it is not unique because if someone later looks for it 1899 // they will find and use it from the global procs. 1900 ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null; 1901 if (proc != null) { 1902 if (!proc.readFromParcel(in, false)) { 1903 return; 1904 } 1905 } else { 1906 proc = new ProcessState(commonProc, pkgName, uid, vers, procName, 1907 0); 1908 if (!proc.readFromParcel(in, true)) { 1909 return; 1910 } 1911 } 1912 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: " 1913 + procName + " " + uid + " " + proc); 1914 pkgState.mProcesses.put(procName, proc); 1915 } else { 1916 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: " 1917 + procName + " " + uid + " " + commonProc); 1918 pkgState.mProcesses.put(procName, commonProc); 1919 } 1920 } 1921 int NSRVS = in.readInt(); 1922 if (NSRVS < 0) { 1923 mReadError = "bad package service count: " + NSRVS; 1924 return; 1925 } 1926 while (NSRVS > 0) { 1927 NSRVS--; 1928 String serviceName = in.readString(); 1929 if (serviceName == null) { 1930 mReadError = "bad package service name"; 1931 return; 1932 } 1933 String processName = version > 9 ? readCommonString(in, version) : null; 1934 ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null; 1935 if (serv == null) { 1936 serv = new ServiceState(this, pkgName, serviceName, processName, null); 1937 } 1938 if (!serv.readFromParcel(in)) { 1939 return; 1940 } 1941 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: " 1942 + serviceName + " " + uid + " " + serv); 1943 pkgState.mServices.put(serviceName, serv); 1944 } 1945 } 1946 } 1947 } 1948 1949 mIndexToCommonString = null; 1950 1951 if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!"); 1952 } 1953 1954 int addLongData(int index, int type, int num) { 1955 int off = allocLongData(num); 1956 mAddLongTable = GrowingArrayUtils.insert( 1957 mAddLongTable != null ? mAddLongTable : EmptyArray.INT, 1958 mAddLongTableSize, index, type | off); 1959 mAddLongTableSize++; 1960 return off; 1961 } 1962 1963 int allocLongData(int num) { 1964 int whichLongs = mLongs.size()-1; 1965 long[] longs = mLongs.get(whichLongs); 1966 if (mNextLong + num > longs.length) { 1967 longs = new long[LONGS_SIZE]; 1968 mLongs.add(longs); 1969 whichLongs++; 1970 mNextLong = 0; 1971 } 1972 int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT); 1973 mNextLong += num; 1974 return off; 1975 } 1976 1977 boolean validateLongOffset(int off) { 1978 int arr = (off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK; 1979 if (arr >= mLongs.size()) { 1980 return false; 1981 } 1982 int idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK; 1983 if (idx >= LONGS_SIZE) { 1984 return false; 1985 } 1986 if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off) 1987 + ": " + getLong(off, 0)); 1988 return true; 1989 } 1990 1991 static String printLongOffset(int off) { 1992 StringBuilder sb = new StringBuilder(16); 1993 sb.append("a"); sb.append((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 1994 sb.append("i"); sb.append((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK); 1995 sb.append("t"); sb.append((off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK); 1996 return sb.toString(); 1997 } 1998 1999 void setLong(int off, int index, long value) { 2000 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 2001 longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value; 2002 } 2003 2004 long getLong(int off, int index) { 2005 long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 2006 return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)]; 2007 } 2008 2009 static int binarySearch(int[] array, int size, int value) { 2010 int lo = 0; 2011 int hi = size - 1; 2012 2013 while (lo <= hi) { 2014 int mid = (lo + hi) >>> 1; 2015 int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK; 2016 2017 if (midVal < value) { 2018 lo = mid + 1; 2019 } else if (midVal > value) { 2020 hi = mid - 1; 2021 } else { 2022 return mid; // value found 2023 } 2024 } 2025 return ~lo; // value not present 2026 } 2027 2028 public PackageState getPackageStateLocked(String packageName, int uid, int vers) { 2029 SparseArray<PackageState> vpkg = mPackages.get(packageName, uid); 2030 if (vpkg == null) { 2031 vpkg = new SparseArray<PackageState>(); 2032 mPackages.put(packageName, uid, vpkg); 2033 } 2034 PackageState as = vpkg.get(vers); 2035 if (as != null) { 2036 return as; 2037 } 2038 as = new PackageState(packageName, uid); 2039 vpkg.put(vers, as); 2040 return as; 2041 } 2042 2043 public ProcessState getProcessStateLocked(String packageName, int uid, int vers, 2044 String processName) { 2045 final PackageState pkgState = getPackageStateLocked(packageName, uid, vers); 2046 ProcessState ps = pkgState.mProcesses.get(processName); 2047 if (ps != null) { 2048 return ps; 2049 } 2050 ProcessState commonProc = mProcesses.get(processName, uid); 2051 if (commonProc == null) { 2052 commonProc = new ProcessState(this, packageName, uid, vers, processName); 2053 mProcesses.put(processName, uid, commonProc); 2054 if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc); 2055 } 2056 if (!commonProc.mMultiPackage) { 2057 if (packageName.equals(commonProc.mPackage) && vers == commonProc.mVersion) { 2058 // This common process is not in use by multiple packages, and 2059 // is for the calling package, so we can just use it directly. 2060 ps = commonProc; 2061 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc); 2062 } else { 2063 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!"); 2064 // This common process has not been in use by multiple packages, 2065 // but it was created for a different package than the caller. 2066 // We need to convert it to a multi-package process. 2067 commonProc.mMultiPackage = true; 2068 // To do this, we need to make two new process states, one a copy 2069 // of the current state for the process under the original package 2070 // name, and the second a free new process state for it as the 2071 // new package name. 2072 long now = SystemClock.uptimeMillis(); 2073 // First let's make a copy of the current process state and put 2074 // that under the now unique state for its original package name. 2075 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage, 2076 uid, commonProc.mVersion); 2077 if (commonPkgState != null) { 2078 ProcessState cloned = commonProc.clone(commonProc.mPackage, now); 2079 if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage 2080 + ": " + cloned); 2081 commonPkgState.mProcesses.put(commonProc.mName, cloned); 2082 // If this has active services, we need to update their process pointer 2083 // to point to the new package-specific process state. 2084 for (int i=commonPkgState.mServices.size()-1; i>=0; i--) { 2085 ServiceState ss = commonPkgState.mServices.valueAt(i); 2086 if (ss.mProc == commonProc) { 2087 if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: " 2088 + ss); 2089 ss.mProc = cloned; 2090 } else if (DEBUG) { 2091 Slog.d(TAG, "GETPROC leaving proc of " + ss); 2092 } 2093 } 2094 } else { 2095 Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage 2096 + "/" + uid + " for proc " + commonProc.mName); 2097 } 2098 // And now make a fresh new process state for the new package name. 2099 ps = new ProcessState(commonProc, packageName, uid, vers, processName, now); 2100 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps); 2101 } 2102 } else { 2103 // The common process is for multiple packages, we need to create a 2104 // separate object for the per-package data. 2105 ps = new ProcessState(commonProc, packageName, uid, vers, processName, 2106 SystemClock.uptimeMillis()); 2107 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps); 2108 } 2109 pkgState.mProcesses.put(processName, ps); 2110 if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps); 2111 return ps; 2112 } 2113 2114 public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid, int vers, 2115 String processName, String className) { 2116 final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers); 2117 ProcessStats.ServiceState ss = as.mServices.get(className); 2118 if (ss != null) { 2119 if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss); 2120 return ss; 2121 } 2122 final ProcessStats.ProcessState ps = processName != null 2123 ? getProcessStateLocked(packageName, uid, vers, processName) : null; 2124 ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps); 2125 as.mServices.put(className, ss); 2126 if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps); 2127 return ss; 2128 } 2129 2130 private void dumpProcessInternalLocked(PrintWriter pw, String prefix, ProcessState proc, 2131 boolean dumpAll) { 2132 if (dumpAll) { 2133 pw.print(prefix); pw.print("myID="); 2134 pw.print(Integer.toHexString(System.identityHashCode(proc))); 2135 pw.print(" mCommonProcess="); 2136 pw.print(Integer.toHexString(System.identityHashCode(proc.mCommonProcess))); 2137 pw.print(" mPackage="); pw.println(proc.mPackage); 2138 if (proc.mMultiPackage) { 2139 pw.print(prefix); pw.print("mMultiPackage="); pw.println(proc.mMultiPackage); 2140 } 2141 if (proc != proc.mCommonProcess) { 2142 pw.print(prefix); pw.print("Common Proc: "); pw.print(proc.mCommonProcess.mName); 2143 pw.print("/"); pw.print(proc.mCommonProcess.mUid); 2144 pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage); 2145 } 2146 } 2147 if (proc.mActive) { 2148 pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive); 2149 } 2150 if (proc.mDead) { 2151 pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead); 2152 } 2153 if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) { 2154 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices); 2155 pw.print(" mNumStartedServices="); 2156 pw.println(proc.mNumStartedServices); 2157 } 2158 } 2159 2160 public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, 2161 boolean dumpAll, boolean activeOnly) { 2162 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, 2163 mStartTime, now); 2164 boolean sepNeeded = false; 2165 if (mSysMemUsageTable != null) { 2166 pw.println("System memory usage:"); 2167 dumpSysMemUsage(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ); 2168 sepNeeded = true; 2169 } 2170 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 2171 boolean printedHeader = false; 2172 for (int ip=0; ip<pkgMap.size(); ip++) { 2173 final String pkgName = pkgMap.keyAt(ip); 2174 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 2175 for (int iu=0; iu<uids.size(); iu++) { 2176 final int uid = uids.keyAt(iu); 2177 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 2178 for (int iv=0; iv<vpkgs.size(); iv++) { 2179 final int vers = vpkgs.keyAt(iv); 2180 final PackageState pkgState = vpkgs.valueAt(iv); 2181 final int NPROCS = pkgState.mProcesses.size(); 2182 final int NSRVS = pkgState.mServices.size(); 2183 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); 2184 if (!pkgMatch) { 2185 boolean procMatch = false; 2186 for (int iproc=0; iproc<NPROCS; iproc++) { 2187 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2188 if (reqPackage.equals(proc.mName)) { 2189 procMatch = true; 2190 break; 2191 } 2192 } 2193 if (!procMatch) { 2194 continue; 2195 } 2196 } 2197 if (NPROCS > 0 || NSRVS > 0) { 2198 if (!printedHeader) { 2199 if (sepNeeded) pw.println(); 2200 pw.println("Per-Package Stats:"); 2201 printedHeader = true; 2202 sepNeeded = true; 2203 } 2204 pw.print(" * "); pw.print(pkgName); pw.print(" / "); 2205 UserHandle.formatUid(pw, uid); pw.print(" / v"); 2206 pw.print(vers); pw.println(":"); 2207 } 2208 if (!dumpSummary || dumpAll) { 2209 for (int iproc=0; iproc<NPROCS; iproc++) { 2210 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2211 if (!pkgMatch && !reqPackage.equals(proc.mName)) { 2212 continue; 2213 } 2214 if (activeOnly && !proc.isInUse()) { 2215 pw.print(" (Not active: "); 2216 pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")"); 2217 continue; 2218 } 2219 pw.print(" Process "); 2220 pw.print(pkgState.mProcesses.keyAt(iproc)); 2221 if (proc.mCommonProcess.mMultiPackage) { 2222 pw.print(" (multi, "); 2223 } else { 2224 pw.print(" (unique, "); 2225 } 2226 pw.print(proc.mDurationsTableSize); 2227 pw.print(" entries)"); 2228 pw.println(":"); 2229 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2230 ALL_PROC_STATES, now); 2231 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2232 ALL_PROC_STATES); 2233 dumpProcessInternalLocked(pw, " ", proc, dumpAll); 2234 } 2235 } else { 2236 ArrayList<ProcessState> procs = new ArrayList<ProcessState>(); 2237 for (int iproc=0; iproc<NPROCS; iproc++) { 2238 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2239 if (!pkgMatch && !reqPackage.equals(proc.mName)) { 2240 continue; 2241 } 2242 if (activeOnly && !proc.isInUse()) { 2243 continue; 2244 } 2245 procs.add(proc); 2246 } 2247 dumpProcessSummaryLocked(pw, " ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2248 NON_CACHED_PROC_STATES, false, now, totalTime); 2249 } 2250 for (int isvc=0; isvc<NSRVS; isvc++) { 2251 ServiceState svc = pkgState.mServices.valueAt(isvc); 2252 if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) { 2253 continue; 2254 } 2255 if (activeOnly && !svc.isInUse()) { 2256 pw.print(" (Not active: "); 2257 pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")"); 2258 continue; 2259 } 2260 if (dumpAll) { 2261 pw.print(" Service "); 2262 } else { 2263 pw.print(" * "); 2264 } 2265 pw.print(pkgState.mServices.keyAt(isvc)); 2266 pw.println(":"); 2267 pw.print(" Process: "); pw.println(svc.mProcessName); 2268 dumpServiceStats(pw, " ", " ", " ", "Running", svc, 2269 svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState, 2270 svc.mRunStartTime, now, totalTime, !dumpSummary || dumpAll); 2271 dumpServiceStats(pw, " ", " ", " ", "Started", svc, 2272 svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState, 2273 svc.mStartedStartTime, now, totalTime, !dumpSummary || dumpAll); 2274 dumpServiceStats(pw, " ", " ", " ", "Bound", svc, 2275 svc.mBoundCount, ServiceState.SERVICE_BOUND, svc.mBoundState, 2276 svc.mBoundStartTime, now, totalTime, !dumpSummary || dumpAll); 2277 dumpServiceStats(pw, " ", " ", " ", "Executing", svc, 2278 svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState, 2279 svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll); 2280 if (dumpAll) { 2281 if (svc.mOwner != null) { 2282 pw.print(" mOwner="); pw.println(svc.mOwner); 2283 } 2284 if (svc.mStarted || svc.mRestarting) { 2285 pw.print(" mStarted="); pw.print(svc.mStarted); 2286 pw.print(" mRestarting="); pw.println(svc.mRestarting); 2287 } 2288 } 2289 } 2290 } 2291 } 2292 } 2293 2294 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 2295 printedHeader = false; 2296 int numShownProcs = 0, numTotalProcs = 0; 2297 for (int ip=0; ip<procMap.size(); ip++) { 2298 String procName = procMap.keyAt(ip); 2299 SparseArray<ProcessState> uids = procMap.valueAt(ip); 2300 for (int iu=0; iu<uids.size(); iu++) { 2301 int uid = uids.keyAt(iu); 2302 numTotalProcs++; 2303 ProcessState proc = uids.valueAt(iu); 2304 if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING 2305 && proc.mPssTableSize == 0) { 2306 continue; 2307 } 2308 if (!proc.mMultiPackage) { 2309 continue; 2310 } 2311 if (reqPackage != null && !reqPackage.equals(procName) 2312 && !reqPackage.equals(proc.mPackage)) { 2313 continue; 2314 } 2315 numShownProcs++; 2316 if (sepNeeded) { 2317 pw.println(); 2318 } 2319 sepNeeded = true; 2320 if (!printedHeader) { 2321 pw.println("Multi-Package Common Processes:"); 2322 printedHeader = true; 2323 } 2324 if (activeOnly && !proc.isInUse()) { 2325 pw.print(" (Not active: "); pw.print(procName); pw.println(")"); 2326 continue; 2327 } 2328 pw.print(" * "); pw.print(procName); pw.print(" / "); 2329 UserHandle.formatUid(pw, uid); 2330 pw.print(" ("); pw.print(proc.mDurationsTableSize); 2331 pw.print(" entries)"); pw.println(":"); 2332 dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2333 ALL_PROC_STATES, now); 2334 dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2335 ALL_PROC_STATES); 2336 dumpProcessInternalLocked(pw, " ", proc, dumpAll); 2337 } 2338 } 2339 if (dumpAll) { 2340 pw.println(); 2341 pw.print(" Total procs: "); pw.print(numShownProcs); 2342 pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); 2343 } 2344 2345 if (sepNeeded) { 2346 pw.println(); 2347 } 2348 if (dumpSummary) { 2349 pw.println("Summary:"); 2350 dumpSummaryLocked(pw, reqPackage, now, activeOnly); 2351 } else { 2352 dumpTotalsLocked(pw, now); 2353 } 2354 2355 if (dumpAll) { 2356 pw.println(); 2357 pw.println("Internal state:"); 2358 pw.print(" Num long arrays: "); pw.println(mLongs.size()); 2359 pw.print(" Next long entry: "); pw.println(mNextLong); 2360 pw.print(" mRunning="); pw.println(mRunning); 2361 } 2362 } 2363 2364 public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service, 2365 int serviceType, int curState, long curStartTime, long now) { 2366 long totalTime = 0; 2367 int printedScreen = -1; 2368 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) { 2369 int printedMem = -1; 2370 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) { 2371 int state = imem+iscreen; 2372 long time = service.getDuration(serviceType, curState, curStartTime, 2373 state, now); 2374 String running = ""; 2375 if (curState == state && pw != null) { 2376 running = " (running)"; 2377 } 2378 if (time != 0) { 2379 if (pw != null) { 2380 pw.print(prefix); 2381 printScreenLabel(pw, printedScreen != iscreen 2382 ? iscreen : STATE_NOTHING); 2383 printedScreen = iscreen; 2384 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0); 2385 printedMem = imem; 2386 pw.print(": "); 2387 TimeUtils.formatDuration(time, pw); pw.println(running); 2388 } 2389 totalTime += time; 2390 } 2391 } 2392 } 2393 if (totalTime != 0 && pw != null) { 2394 pw.print(prefix); 2395 pw.print(" TOTAL: "); 2396 TimeUtils.formatDuration(totalTime, pw); 2397 pw.println(); 2398 } 2399 return totalTime; 2400 } 2401 2402 void dumpServiceStats(PrintWriter pw, String prefix, String prefixInner, 2403 String headerPrefix, String header, ServiceState service, 2404 int count, int serviceType, int state, long startTime, long now, long totalTime, 2405 boolean dumpAll) { 2406 if (count != 0) { 2407 if (dumpAll) { 2408 pw.print(prefix); pw.print(header); 2409 pw.print(" op count "); pw.print(count); pw.println(":"); 2410 dumpSingleServiceTime(pw, prefixInner, service, serviceType, state, startTime, 2411 now); 2412 } else { 2413 long myTime = dumpSingleServiceTime(null, null, service, serviceType, state, 2414 startTime, now); 2415 pw.print(prefix); pw.print(headerPrefix); pw.print(header); 2416 pw.print(" count "); pw.print(count); 2417 pw.print(" / time "); 2418 printPercent(pw, (double)myTime/(double)totalTime); 2419 pw.println(); 2420 } 2421 } 2422 } 2423 2424 public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) { 2425 long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, 2426 mStartTime, now); 2427 dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, 2428 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly); 2429 pw.println(); 2430 dumpTotalsLocked(pw, now); 2431 } 2432 2433 long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, 2434 long totalTime, long curTotalMem, int samples) { 2435 if (memWeight != 0) { 2436 long mem = (long)(memWeight * 1024 / totalTime); 2437 pw.print(prefix); 2438 pw.print(label); 2439 pw.print(": "); 2440 printSizeValue(pw, mem); 2441 pw.print(" ("); 2442 pw.print(samples); 2443 pw.print(" samples)"); 2444 pw.println(); 2445 return curTotalMem + mem; 2446 } 2447 return curTotalMem; 2448 } 2449 2450 void dumpTotalsLocked(PrintWriter pw, long now) { 2451 pw.println("Run time Stats:"); 2452 dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now); 2453 pw.println(); 2454 pw.println("Memory usage:"); 2455 TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, 2456 ALL_MEM_ADJ); 2457 computeTotalMemoryUse(totalMem, now); 2458 long totalPss = 0; 2459 totalPss = printMemoryCategory(pw, " ", "Kernel ", totalMem.sysMemKernelWeight, 2460 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2461 totalPss = printMemoryCategory(pw, " ", "Native ", totalMem.sysMemNativeWeight, 2462 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2463 for (int i=0; i<STATE_COUNT; i++) { 2464 // Skip restarting service state -- that is not actually a running process. 2465 if (i != STATE_SERVICE_RESTARTING) { 2466 totalPss = printMemoryCategory(pw, " ", STATE_NAMES[i], 2467 totalMem.processStateWeight[i], totalMem.totalTime, totalPss, 2468 totalMem.processStateSamples[i]); 2469 } 2470 } 2471 totalPss = printMemoryCategory(pw, " ", "Cached ", totalMem.sysMemCachedWeight, 2472 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2473 totalPss = printMemoryCategory(pw, " ", "Free ", totalMem.sysMemFreeWeight, 2474 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2475 totalPss = printMemoryCategory(pw, " ", "Z-Ram ", totalMem.sysMemZRamWeight, 2476 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 2477 pw.print(" TOTAL : "); 2478 printSizeValue(pw, totalPss); 2479 pw.println(); 2480 printMemoryCategory(pw, " ", STATE_NAMES[STATE_SERVICE_RESTARTING], 2481 totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss, 2482 totalMem.processStateSamples[STATE_SERVICE_RESTARTING]); 2483 pw.println(); 2484 pw.print(" Start time: "); 2485 pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock)); 2486 pw.println(); 2487 pw.print(" Total elapsed time: "); 2488 TimeUtils.formatDuration( 2489 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime) 2490 - mTimePeriodStartRealtime, pw); 2491 boolean partial = true; 2492 if ((mFlags&FLAG_SHUTDOWN) != 0) { 2493 pw.print(" (shutdown)"); 2494 partial = false; 2495 } 2496 if ((mFlags&FLAG_SYSPROPS) != 0) { 2497 pw.print(" (sysprops)"); 2498 partial = false; 2499 } 2500 if ((mFlags&FLAG_COMPLETE) != 0) { 2501 pw.print(" (complete)"); 2502 partial = false; 2503 } 2504 if (partial) { 2505 pw.print(" (partial)"); 2506 } 2507 pw.print(' '); 2508 pw.print(mRuntime); 2509 pw.println(); 2510 } 2511 2512 void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, 2513 int[] screenStates, int[] memStates, int[] procStates, 2514 int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) { 2515 ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates, 2516 procStates, sortProcStates, now, reqPackage, activeOnly); 2517 if (procs.size() > 0) { 2518 if (header != null) { 2519 pw.println(); 2520 pw.println(header); 2521 } 2522 dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates, 2523 sortProcStates, true, now, totalTime); 2524 } 2525 } 2526 2527 public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates, 2528 int[] procStates, int sortProcStates[], long now, String reqPackage, 2529 boolean activeOnly) { 2530 final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>(); 2531 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 2532 for (int ip=0; ip<pkgMap.size(); ip++) { 2533 final String pkgName = pkgMap.keyAt(ip); 2534 final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip); 2535 for (int iu=0; iu<procs.size(); iu++) { 2536 final SparseArray<PackageState> vpkgs = procs.valueAt(iu); 2537 final int NVERS = vpkgs.size(); 2538 for (int iv=0; iv<NVERS; iv++) { 2539 final PackageState state = vpkgs.valueAt(iv); 2540 final int NPROCS = state.mProcesses.size(); 2541 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); 2542 for (int iproc=0; iproc<NPROCS; iproc++) { 2543 final ProcessState proc = state.mProcesses.valueAt(iproc); 2544 if (!pkgMatch && !reqPackage.equals(proc.mName)) { 2545 continue; 2546 } 2547 if (activeOnly && !proc.isInUse()) { 2548 continue; 2549 } 2550 foundProcs.add(proc.mCommonProcess); 2551 } 2552 } 2553 } 2554 } 2555 ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size()); 2556 for (int i=0; i<foundProcs.size(); i++) { 2557 ProcessState proc = foundProcs.valueAt(i); 2558 if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) { 2559 outProcs.add(proc); 2560 if (procStates != sortProcStates) { 2561 computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now); 2562 } 2563 } 2564 } 2565 Collections.sort(outProcs, new Comparator<ProcessState>() { 2566 @Override 2567 public int compare(ProcessState lhs, ProcessState rhs) { 2568 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) { 2569 return -1; 2570 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) { 2571 return 1; 2572 } 2573 return 0; 2574 } 2575 }); 2576 return outProcs; 2577 } 2578 2579 String collapseString(String pkgName, String itemName) { 2580 if (itemName.startsWith(pkgName)) { 2581 final int ITEMLEN = itemName.length(); 2582 final int PKGLEN = pkgName.length(); 2583 if (ITEMLEN == PKGLEN) { 2584 return ""; 2585 } else if (ITEMLEN >= PKGLEN) { 2586 if (itemName.charAt(PKGLEN) == '.') { 2587 return itemName.substring(PKGLEN); 2588 } 2589 } 2590 } 2591 return itemName; 2592 } 2593 2594 public void dumpCheckinLocked(PrintWriter pw, String reqPackage) { 2595 final long now = SystemClock.uptimeMillis(); 2596 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 2597 pw.println("vers,5"); 2598 pw.print("period,"); pw.print(mTimePeriodStartClockStr); 2599 pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(","); 2600 pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime); 2601 boolean partial = true; 2602 if ((mFlags&FLAG_SHUTDOWN) != 0) { 2603 pw.print(",shutdown"); 2604 partial = false; 2605 } 2606 if ((mFlags&FLAG_SYSPROPS) != 0) { 2607 pw.print(",sysprops"); 2608 partial = false; 2609 } 2610 if ((mFlags&FLAG_COMPLETE) != 0) { 2611 pw.print(",complete"); 2612 partial = false; 2613 } 2614 if (partial) { 2615 pw.print(",partial"); 2616 } 2617 pw.println(); 2618 pw.print("config,"); pw.println(mRuntime); 2619 for (int ip=0; ip<pkgMap.size(); ip++) { 2620 final String pkgName = pkgMap.keyAt(ip); 2621 if (reqPackage != null && !reqPackage.equals(pkgName)) { 2622 continue; 2623 } 2624 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 2625 for (int iu=0; iu<uids.size(); iu++) { 2626 final int uid = uids.keyAt(iu); 2627 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 2628 for (int iv=0; iv<vpkgs.size(); iv++) { 2629 final int vers = vpkgs.keyAt(iv); 2630 final PackageState pkgState = vpkgs.valueAt(iv); 2631 final int NPROCS = pkgState.mProcesses.size(); 2632 final int NSRVS = pkgState.mServices.size(); 2633 for (int iproc=0; iproc<NPROCS; iproc++) { 2634 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 2635 pw.print("pkgproc,"); 2636 pw.print(pkgName); 2637 pw.print(","); 2638 pw.print(uid); 2639 pw.print(","); 2640 pw.print(vers); 2641 pw.print(","); 2642 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc))); 2643 dumpAllProcessStateCheckin(pw, proc, now); 2644 pw.println(); 2645 if (proc.mPssTableSize > 0) { 2646 pw.print("pkgpss,"); 2647 pw.print(pkgName); 2648 pw.print(","); 2649 pw.print(uid); 2650 pw.print(","); 2651 pw.print(vers); 2652 pw.print(","); 2653 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc))); 2654 dumpAllProcessPssCheckin(pw, proc); 2655 pw.println(); 2656 } 2657 if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0 2658 || proc.mNumCachedKill > 0) { 2659 pw.print("pkgkills,"); 2660 pw.print(pkgName); 2661 pw.print(","); 2662 pw.print(uid); 2663 pw.print(","); 2664 pw.print(vers); 2665 pw.print(","); 2666 pw.print(collapseString(pkgName, pkgState.mProcesses.keyAt(iproc))); 2667 pw.print(","); 2668 pw.print(proc.mNumExcessiveWake); 2669 pw.print(","); 2670 pw.print(proc.mNumExcessiveCpu); 2671 pw.print(","); 2672 pw.print(proc.mNumCachedKill); 2673 pw.print(","); 2674 pw.print(proc.mMinCachedKillPss); 2675 pw.print(":"); 2676 pw.print(proc.mAvgCachedKillPss); 2677 pw.print(":"); 2678 pw.print(proc.mMaxCachedKillPss); 2679 pw.println(); 2680 } 2681 } 2682 for (int isvc=0; isvc<NSRVS; isvc++) { 2683 String serviceName = collapseString(pkgName, 2684 pkgState.mServices.keyAt(isvc)); 2685 ServiceState svc = pkgState.mServices.valueAt(isvc); 2686 dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, vers, serviceName, 2687 svc, ServiceState.SERVICE_RUN, svc.mRunCount, 2688 svc.mRunState, svc.mRunStartTime, now); 2689 dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName, 2690 svc, ServiceState.SERVICE_STARTED, svc.mStartedCount, 2691 svc.mStartedState, svc.mStartedStartTime, now); 2692 dumpServiceTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName, 2693 svc, ServiceState.SERVICE_BOUND, svc.mBoundCount, 2694 svc.mBoundState, svc.mBoundStartTime, now); 2695 dumpServiceTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName, 2696 svc, ServiceState.SERVICE_EXEC, svc.mExecCount, 2697 svc.mExecState, svc.mExecStartTime, now); 2698 } 2699 } 2700 } 2701 } 2702 2703 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 2704 for (int ip=0; ip<procMap.size(); ip++) { 2705 String procName = procMap.keyAt(ip); 2706 SparseArray<ProcessState> uids = procMap.valueAt(ip); 2707 for (int iu=0; iu<uids.size(); iu++) { 2708 int uid = uids.keyAt(iu); 2709 ProcessState procState = uids.valueAt(iu); 2710 if (procState.mDurationsTableSize > 0) { 2711 pw.print("proc,"); 2712 pw.print(procName); 2713 pw.print(","); 2714 pw.print(uid); 2715 dumpAllProcessStateCheckin(pw, procState, now); 2716 pw.println(); 2717 } 2718 if (procState.mPssTableSize > 0) { 2719 pw.print("pss,"); 2720 pw.print(procName); 2721 pw.print(","); 2722 pw.print(uid); 2723 dumpAllProcessPssCheckin(pw, procState); 2724 pw.println(); 2725 } 2726 if (procState.mNumExcessiveWake > 0 || procState.mNumExcessiveCpu > 0 2727 || procState.mNumCachedKill > 0) { 2728 pw.print("kills,"); 2729 pw.print(procName); 2730 pw.print(","); 2731 pw.print(uid); 2732 pw.print(","); 2733 pw.print(procState.mNumExcessiveWake); 2734 pw.print(","); 2735 pw.print(procState.mNumExcessiveCpu); 2736 pw.print(","); 2737 pw.print(procState.mNumCachedKill); 2738 pw.print(","); 2739 pw.print(procState.mMinCachedKillPss); 2740 pw.print(":"); 2741 pw.print(procState.mAvgCachedKillPss); 2742 pw.print(":"); 2743 pw.print(procState.mMaxCachedKillPss); 2744 pw.println(); 2745 } 2746 } 2747 } 2748 pw.print("total"); 2749 dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor, 2750 mStartTime, now); 2751 pw.println(); 2752 if (mSysMemUsageTable != null) { 2753 pw.print("sysmemusage"); 2754 for (int i=0; i<mSysMemUsageTableSize; i++) { 2755 int off = mSysMemUsageTable[i]; 2756 int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2757 pw.print(","); 2758 printProcStateTag(pw, type); 2759 for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) { 2760 if (j > SYS_MEM_USAGE_CACHED_MINIMUM) { 2761 pw.print(":"); 2762 } 2763 pw.print(getLong(off, j)); 2764 } 2765 } 2766 } 2767 pw.println(); 2768 TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, 2769 ALL_MEM_ADJ); 2770 computeTotalMemoryUse(totalMem, now); 2771 pw.print("weights,"); 2772 pw.print(totalMem.totalTime); 2773 pw.print(","); 2774 pw.print(totalMem.sysMemCachedWeight); 2775 pw.print(":"); 2776 pw.print(totalMem.sysMemSamples); 2777 pw.print(","); 2778 pw.print(totalMem.sysMemFreeWeight); 2779 pw.print(":"); 2780 pw.print(totalMem.sysMemSamples); 2781 pw.print(","); 2782 pw.print(totalMem.sysMemZRamWeight); 2783 pw.print(":"); 2784 pw.print(totalMem.sysMemSamples); 2785 pw.print(","); 2786 pw.print(totalMem.sysMemKernelWeight); 2787 pw.print(":"); 2788 pw.print(totalMem.sysMemSamples); 2789 pw.print(","); 2790 pw.print(totalMem.sysMemNativeWeight); 2791 pw.print(":"); 2792 pw.print(totalMem.sysMemSamples); 2793 for (int i=0; i<STATE_COUNT; i++) { 2794 pw.print(","); 2795 pw.print(totalMem.processStateWeight[i]); 2796 pw.print(":"); 2797 pw.print(totalMem.processStateSamples[i]); 2798 } 2799 pw.println(); 2800 } 2801 2802 public static class DurationsTable { 2803 public final ProcessStats mStats; 2804 public final String mName; 2805 public int[] mDurationsTable; 2806 public int mDurationsTableSize; 2807 2808 public DurationsTable(ProcessStats stats, String name) { 2809 mStats = stats; 2810 mName = name; 2811 } 2812 2813 void copyDurationsTo(DurationsTable other) { 2814 if (mDurationsTable != null) { 2815 mStats.mAddLongTable = new int[mDurationsTable.length]; 2816 mStats.mAddLongTableSize = 0; 2817 for (int i=0; i<mDurationsTableSize; i++) { 2818 int origEnt = mDurationsTable[i]; 2819 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2820 int newOff = mStats.addLongData(i, type, 1); 2821 mStats.mAddLongTable[i] = newOff | type; 2822 mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0)); 2823 } 2824 other.mDurationsTable = mStats.mAddLongTable; 2825 other.mDurationsTableSize = mStats.mAddLongTableSize; 2826 } else { 2827 other.mDurationsTable = null; 2828 other.mDurationsTableSize = 0; 2829 } 2830 } 2831 2832 void addDurations(DurationsTable other) { 2833 for (int i=0; i<other.mDurationsTableSize; i++) { 2834 int ent = other.mDurationsTable[i]; 2835 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2836 if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration " 2837 + other.mStats.getLong(ent, 0)); 2838 addDuration(state, other.mStats.getLong(ent, 0)); 2839 } 2840 } 2841 2842 void resetDurationsSafely() { 2843 mDurationsTable = null; 2844 mDurationsTableSize = 0; 2845 } 2846 2847 void writeDurationsToParcel(Parcel out) { 2848 out.writeInt(mDurationsTableSize); 2849 for (int i=0; i<mDurationsTableSize; i++) { 2850 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": " 2851 + printLongOffset(mDurationsTable[i])); 2852 out.writeInt(mDurationsTable[i]); 2853 } 2854 } 2855 2856 boolean readDurationsFromParcel(Parcel in) { 2857 mDurationsTable = mStats.readTableFromParcel(in, mName, "durations"); 2858 if (mDurationsTable == BAD_TABLE) { 2859 return false; 2860 } 2861 mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0; 2862 return true; 2863 } 2864 2865 void addDuration(int state, long dur) { 2866 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state); 2867 int off; 2868 if (idx >= 0) { 2869 off = mDurationsTable[idx]; 2870 } else { 2871 mStats.mAddLongTable = mDurationsTable; 2872 mStats.mAddLongTableSize = mDurationsTableSize; 2873 off = mStats.addLongData(~idx, state, 1); 2874 mDurationsTable = mStats.mAddLongTable; 2875 mDurationsTableSize = mStats.mAddLongTableSize; 2876 } 2877 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 2878 if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur 2879 + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]); 2880 longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur; 2881 } 2882 2883 long getDuration(int state, long now) { 2884 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state); 2885 return idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0; 2886 } 2887 } 2888 2889 final public static class ProcessStateHolder { 2890 public final int appVersion; 2891 public ProcessStats.ProcessState state; 2892 2893 public ProcessStateHolder(int _appVersion) { 2894 appVersion = _appVersion; 2895 } 2896 } 2897 2898 public static final class ProcessState extends DurationsTable { 2899 public ProcessState mCommonProcess; 2900 public final String mPackage; 2901 public final int mUid; 2902 public final int mVersion; 2903 2904 //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT]; 2905 int mCurState = STATE_NOTHING; 2906 long mStartTime; 2907 2908 int mLastPssState = STATE_NOTHING; 2909 long mLastPssTime; 2910 int[] mPssTable; 2911 int mPssTableSize; 2912 2913 boolean mActive; 2914 int mNumActiveServices; 2915 int mNumStartedServices; 2916 2917 int mNumExcessiveWake; 2918 int mNumExcessiveCpu; 2919 2920 int mNumCachedKill; 2921 long mMinCachedKillPss; 2922 long mAvgCachedKillPss; 2923 long mMaxCachedKillPss; 2924 2925 boolean mMultiPackage; 2926 boolean mDead; 2927 2928 public long mTmpTotalTime; 2929 int mTmpNumInUse; 2930 ProcessState mTmpFoundSubProc; 2931 2932 /** 2933 * Create a new top-level process state, for the initial case where there is only 2934 * a single package running in a process. The initial state is not running. 2935 */ 2936 public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) { 2937 super(processStats, name); 2938 mCommonProcess = this; 2939 mPackage = pkg; 2940 mUid = uid; 2941 mVersion = vers; 2942 } 2943 2944 /** 2945 * Create a new per-package process state for an existing top-level process 2946 * state. The current running state of the top-level process is also copied, 2947 * marked as started running at 'now'. 2948 */ 2949 public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name, 2950 long now) { 2951 super(commonProcess.mStats, name); 2952 mCommonProcess = commonProcess; 2953 mPackage = pkg; 2954 mUid = uid; 2955 mVersion = vers; 2956 mCurState = commonProcess.mCurState; 2957 mStartTime = now; 2958 } 2959 2960 ProcessState clone(String pkg, long now) { 2961 ProcessState pnew = new ProcessState(this, pkg, mUid, mVersion, mName, now); 2962 copyDurationsTo(pnew); 2963 if (mPssTable != null) { 2964 mStats.mAddLongTable = new int[mPssTable.length]; 2965 mStats.mAddLongTableSize = 0; 2966 for (int i=0; i<mPssTableSize; i++) { 2967 int origEnt = mPssTable[i]; 2968 int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2969 int newOff = mStats.addLongData(i, type, PSS_COUNT); 2970 mStats.mAddLongTable[i] = newOff | type; 2971 for (int j=0; j<PSS_COUNT; j++) { 2972 mStats.setLong(newOff, j, mStats.getLong(origEnt, j)); 2973 } 2974 } 2975 pnew.mPssTable = mStats.mAddLongTable; 2976 pnew.mPssTableSize = mStats.mAddLongTableSize; 2977 } 2978 pnew.mNumExcessiveWake = mNumExcessiveWake; 2979 pnew.mNumExcessiveCpu = mNumExcessiveCpu; 2980 pnew.mNumCachedKill = mNumCachedKill; 2981 pnew.mMinCachedKillPss = mMinCachedKillPss; 2982 pnew.mAvgCachedKillPss = mAvgCachedKillPss; 2983 pnew.mMaxCachedKillPss = mMaxCachedKillPss; 2984 pnew.mActive = mActive; 2985 pnew.mNumActiveServices = mNumActiveServices; 2986 pnew.mNumStartedServices = mNumStartedServices; 2987 return pnew; 2988 } 2989 2990 void add(ProcessState other) { 2991 addDurations(other); 2992 for (int i=0; i<other.mPssTableSize; i++) { 2993 int ent = other.mPssTable[i]; 2994 int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; 2995 addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT), 2996 other.mStats.getLong(ent, PSS_MINIMUM), 2997 other.mStats.getLong(ent, PSS_AVERAGE), 2998 other.mStats.getLong(ent, PSS_MAXIMUM), 2999 other.mStats.getLong(ent, PSS_USS_MINIMUM), 3000 other.mStats.getLong(ent, PSS_USS_AVERAGE), 3001 other.mStats.getLong(ent, PSS_USS_MAXIMUM)); 3002 } 3003 mNumExcessiveWake += other.mNumExcessiveWake; 3004 mNumExcessiveCpu += other.mNumExcessiveCpu; 3005 if (other.mNumCachedKill > 0) { 3006 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss, 3007 other.mAvgCachedKillPss, other.mMaxCachedKillPss); 3008 } 3009 } 3010 3011 void resetSafely(long now) { 3012 resetDurationsSafely(); 3013 mStartTime = now; 3014 mLastPssState = STATE_NOTHING; 3015 mLastPssTime = 0; 3016 mPssTable = null; 3017 mPssTableSize = 0; 3018 mNumExcessiveWake = 0; 3019 mNumExcessiveCpu = 0; 3020 mNumCachedKill = 0; 3021 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0; 3022 } 3023 3024 void makeDead() { 3025 mDead = true; 3026 } 3027 3028 private void ensureNotDead() { 3029 if (!mDead) { 3030 return; 3031 } 3032 Slog.wtfStack(TAG, "ProcessState dead: name=" + mName 3033 + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName); 3034 } 3035 3036 void writeToParcel(Parcel out, long now) { 3037 out.writeInt(mMultiPackage ? 1 : 0); 3038 writeDurationsToParcel(out); 3039 out.writeInt(mPssTableSize); 3040 for (int i=0; i<mPssTableSize; i++) { 3041 if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": " 3042 + printLongOffset(mPssTable[i])); 3043 out.writeInt(mPssTable[i]); 3044 } 3045 out.writeInt(mNumExcessiveWake); 3046 out.writeInt(mNumExcessiveCpu); 3047 out.writeInt(mNumCachedKill); 3048 if (mNumCachedKill > 0) { 3049 out.writeLong(mMinCachedKillPss); 3050 out.writeLong(mAvgCachedKillPss); 3051 out.writeLong(mMaxCachedKillPss); 3052 } 3053 } 3054 3055 boolean readFromParcel(Parcel in, boolean fully) { 3056 boolean multiPackage = in.readInt() != 0; 3057 if (fully) { 3058 mMultiPackage = multiPackage; 3059 } 3060 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table..."); 3061 if (!readDurationsFromParcel(in)) { 3062 return false; 3063 } 3064 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table..."); 3065 mPssTable = mStats.readTableFromParcel(in, mName, "pss"); 3066 if (mPssTable == BAD_TABLE) { 3067 return false; 3068 } 3069 mPssTableSize = mPssTable != null ? mPssTable.length : 0; 3070 mNumExcessiveWake = in.readInt(); 3071 mNumExcessiveCpu = in.readInt(); 3072 mNumCachedKill = in.readInt(); 3073 if (mNumCachedKill > 0) { 3074 mMinCachedKillPss = in.readLong(); 3075 mAvgCachedKillPss = in.readLong(); 3076 mMaxCachedKillPss = in.readLong(); 3077 } else { 3078 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0; 3079 } 3080 return true; 3081 } 3082 3083 public void makeActive() { 3084 ensureNotDead(); 3085 mActive = true; 3086 } 3087 3088 public void makeInactive() { 3089 mActive = false; 3090 } 3091 3092 public boolean isInUse() { 3093 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0 3094 || mCurState != STATE_NOTHING; 3095 } 3096 3097 /** 3098 * Update the current state of the given list of processes. 3099 * 3100 * @param state Current ActivityManager.PROCESS_STATE_* 3101 * @param memFactor Current mem factor constant. 3102 * @param now Current time. 3103 * @param pkgList Processes to update. 3104 */ 3105 public void setState(int state, int memFactor, long now, 3106 ArrayMap<String, ProcessStateHolder> pkgList) { 3107 if (state < 0) { 3108 state = mNumStartedServices > 0 3109 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING; 3110 } else { 3111 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT); 3112 } 3113 3114 // First update the common process. 3115 mCommonProcess.setState(state, now); 3116 3117 // If the common process is not multi-package, there is nothing else to do. 3118 if (!mCommonProcess.mMultiPackage) { 3119 return; 3120 } 3121 3122 if (pkgList != null) { 3123 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3124 pullFixedProc(pkgList, ip).setState(state, now); 3125 } 3126 } 3127 } 3128 3129 void setState(int state, long now) { 3130 ensureNotDead(); 3131 if (mCurState != state) { 3132 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state); 3133 commitStateTime(now); 3134 mCurState = state; 3135 } 3136 } 3137 3138 void commitStateTime(long now) { 3139 if (mCurState != STATE_NOTHING) { 3140 long dur = now - mStartTime; 3141 if (dur > 0) { 3142 addDuration(mCurState, dur); 3143 } 3144 } 3145 mStartTime = now; 3146 } 3147 3148 void incActiveServices(String serviceName) { 3149 if (DEBUG && "".equals(mName)) { 3150 RuntimeException here = new RuntimeException("here"); 3151 here.fillInStackTrace(); 3152 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName 3153 + " to " + (mNumActiveServices+1), here); 3154 } 3155 if (mCommonProcess != this) { 3156 mCommonProcess.incActiveServices(serviceName); 3157 } 3158 mNumActiveServices++; 3159 } 3160 3161 void decActiveServices(String serviceName) { 3162 if (DEBUG && "".equals(mName)) { 3163 RuntimeException here = new RuntimeException("here"); 3164 here.fillInStackTrace(); 3165 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName 3166 + " to " + (mNumActiveServices-1), here); 3167 } 3168 if (mCommonProcess != this) { 3169 mCommonProcess.decActiveServices(serviceName); 3170 } 3171 mNumActiveServices--; 3172 if (mNumActiveServices < 0) { 3173 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage 3174 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName); 3175 mNumActiveServices = 0; 3176 } 3177 } 3178 3179 void incStartedServices(int memFactor, long now, String serviceName) { 3180 if (false) { 3181 RuntimeException here = new RuntimeException("here"); 3182 here.fillInStackTrace(); 3183 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName 3184 + " to " + (mNumStartedServices+1), here); 3185 } 3186 if (mCommonProcess != this) { 3187 mCommonProcess.incStartedServices(memFactor, now, serviceName); 3188 } 3189 mNumStartedServices++; 3190 if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) { 3191 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now); 3192 } 3193 } 3194 3195 void decStartedServices(int memFactor, long now, String serviceName) { 3196 if (false) { 3197 RuntimeException here = new RuntimeException("here"); 3198 here.fillInStackTrace(); 3199 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName 3200 + " to " + (mNumStartedServices-1), here); 3201 } 3202 if (mCommonProcess != this) { 3203 mCommonProcess.decStartedServices(memFactor, now, serviceName); 3204 } 3205 mNumStartedServices--; 3206 if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) { 3207 setState(STATE_NOTHING, now); 3208 } else if (mNumStartedServices < 0) { 3209 Slog.wtfStack(TAG, "Proc started services underrun: pkg=" 3210 + mPackage + " uid=" + mUid + " name=" + mName); 3211 mNumStartedServices = 0; 3212 } 3213 } 3214 3215 public void addPss(long pss, long uss, boolean always, 3216 ArrayMap<String, ProcessStateHolder> pkgList) { 3217 ensureNotDead(); 3218 if (!always) { 3219 if (mLastPssState == mCurState && SystemClock.uptimeMillis() 3220 < (mLastPssTime+(30*1000))) { 3221 return; 3222 } 3223 } 3224 mLastPssState = mCurState; 3225 mLastPssTime = SystemClock.uptimeMillis(); 3226 if (mCurState != STATE_NOTHING) { 3227 // First update the common process. 3228 mCommonProcess.addPss(mCurState, 1, pss, pss, pss, uss, uss, uss); 3229 3230 // If the common process is not multi-package, there is nothing else to do. 3231 if (!mCommonProcess.mMultiPackage) { 3232 return; 3233 } 3234 3235 if (pkgList != null) { 3236 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3237 pullFixedProc(pkgList, ip).addPss(mCurState, 1, 3238 pss, pss, pss, uss, uss, uss); 3239 } 3240 } 3241 } 3242 } 3243 3244 void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss, 3245 long avgUss, long maxUss) { 3246 int idx = binarySearch(mPssTable, mPssTableSize, state); 3247 int off; 3248 if (idx >= 0) { 3249 off = mPssTable[idx]; 3250 } else { 3251 mStats.mAddLongTable = mPssTable; 3252 mStats.mAddLongTableSize = mPssTableSize; 3253 off = mStats.addLongData(~idx, state, PSS_COUNT); 3254 mPssTable = mStats.mAddLongTable; 3255 mPssTableSize = mStats.mAddLongTableSize; 3256 } 3257 long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); 3258 idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK; 3259 long count = longs[idx+PSS_SAMPLE_COUNT]; 3260 if (count == 0) { 3261 longs[idx+PSS_SAMPLE_COUNT] = inCount; 3262 longs[idx+PSS_MINIMUM] = minPss; 3263 longs[idx+PSS_AVERAGE] = avgPss; 3264 longs[idx+PSS_MAXIMUM] = maxPss; 3265 longs[idx+PSS_USS_MINIMUM] = minUss; 3266 longs[idx+PSS_USS_AVERAGE] = avgUss; 3267 longs[idx+PSS_USS_MAXIMUM] = maxUss; 3268 } else { 3269 longs[idx+PSS_SAMPLE_COUNT] = count+inCount; 3270 if (longs[idx+PSS_MINIMUM] > minPss) { 3271 longs[idx+PSS_MINIMUM] = minPss; 3272 } 3273 longs[idx+PSS_AVERAGE] = (long)( 3274 ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount)) 3275 / (count+inCount) ); 3276 if (longs[idx+PSS_MAXIMUM] < maxPss) { 3277 longs[idx+PSS_MAXIMUM] = maxPss; 3278 } 3279 if (longs[idx+PSS_USS_MINIMUM] > minUss) { 3280 longs[idx+PSS_USS_MINIMUM] = minUss; 3281 } 3282 longs[idx+PSS_USS_AVERAGE] = (long)( 3283 ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount)) 3284 / (count+inCount) ); 3285 if (longs[idx+PSS_USS_MAXIMUM] < maxUss) { 3286 longs[idx+PSS_USS_MAXIMUM] = maxUss; 3287 } 3288 } 3289 } 3290 3291 public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) { 3292 ensureNotDead(); 3293 mCommonProcess.mNumExcessiveWake++; 3294 if (!mCommonProcess.mMultiPackage) { 3295 return; 3296 } 3297 3298 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3299 pullFixedProc(pkgList, ip).mNumExcessiveWake++; 3300 } 3301 } 3302 3303 public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) { 3304 ensureNotDead(); 3305 mCommonProcess.mNumExcessiveCpu++; 3306 if (!mCommonProcess.mMultiPackage) { 3307 return; 3308 } 3309 3310 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3311 pullFixedProc(pkgList, ip).mNumExcessiveCpu++; 3312 } 3313 } 3314 3315 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) { 3316 if (mNumCachedKill <= 0) { 3317 mNumCachedKill = num; 3318 mMinCachedKillPss = minPss; 3319 mAvgCachedKillPss = avgPss; 3320 mMaxCachedKillPss = maxPss; 3321 } else { 3322 if (minPss < mMinCachedKillPss) { 3323 mMinCachedKillPss = minPss; 3324 } 3325 if (maxPss > mMaxCachedKillPss) { 3326 mMaxCachedKillPss = maxPss; 3327 } 3328 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss) 3329 / (mNumCachedKill+num) ); 3330 mNumCachedKill += num; 3331 } 3332 } 3333 3334 public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) { 3335 ensureNotDead(); 3336 mCommonProcess.addCachedKill(1, pss, pss, pss); 3337 if (!mCommonProcess.mMultiPackage) { 3338 return; 3339 } 3340 3341 for (int ip=pkgList.size()-1; ip>=0; ip--) { 3342 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss); 3343 } 3344 } 3345 3346 ProcessState pullFixedProc(String pkgName) { 3347 if (mMultiPackage) { 3348 // The array map is still pointing to a common process state 3349 // that is now shared across packages. Update it to point to 3350 // the new per-package state. 3351 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid); 3352 if (vpkg == null) { 3353 throw new IllegalStateException("Didn't find package " + pkgName 3354 + " / " + mUid); 3355 } 3356 PackageState pkg = vpkg.get(mVersion); 3357 if (pkg == null) { 3358 throw new IllegalStateException("Didn't find package " + pkgName 3359 + " / " + mUid + " vers " + mVersion); 3360 } 3361 ProcessState proc = pkg.mProcesses.get(mName); 3362 if (proc == null) { 3363 throw new IllegalStateException("Didn't create per-package process " 3364 + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion); 3365 } 3366 return proc; 3367 } 3368 return this; 3369 } 3370 3371 private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList, 3372 int index) { 3373 ProcessStateHolder holder = pkgList.valueAt(index); 3374 ProcessState proc = holder.state; 3375 if (mDead && proc.mCommonProcess != proc) { 3376 // Somehow we are contining to use a process state that is dead, because 3377 // it was not being told it was active during the last commit. We can recover 3378 // from this by generating a fresh new state, but this is bad because we 3379 // are losing whatever data we had in the old process state. 3380 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage 3381 + " uid=" + mUid + " common.name=" + mCommonProcess.mName); 3382 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion, 3383 proc.mName); 3384 } 3385 if (proc.mMultiPackage) { 3386 // The array map is still pointing to a common process state 3387 // that is now shared across packages. Update it to point to 3388 // the new per-package state. 3389 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index), 3390 proc.mUid); 3391 if (vpkg == null) { 3392 throw new IllegalStateException("No existing package " 3393 + pkgList.keyAt(index) + "/" + proc.mUid 3394 + " for multi-proc " + proc.mName); 3395 } 3396 PackageState pkg = vpkg.get(proc.mVersion); 3397 if (pkg == null) { 3398 throw new IllegalStateException("No existing package " 3399 + pkgList.keyAt(index) + "/" + proc.mUid 3400 + " for multi-proc " + proc.mName + " version " + proc.mVersion); 3401 } 3402 proc = pkg.mProcesses.get(proc.mName); 3403 if (proc == null) { 3404 throw new IllegalStateException("Didn't create per-package process " 3405 + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid); 3406 } 3407 holder.state = proc; 3408 } 3409 return proc; 3410 } 3411 3412 long getDuration(int state, long now) { 3413 long time = super.getDuration(state, now); 3414 if (mCurState == state) { 3415 time += now - mStartTime; 3416 } 3417 return time; 3418 } 3419 3420 long getPssSampleCount(int state) { 3421 int idx = binarySearch(mPssTable, mPssTableSize, state); 3422 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0; 3423 } 3424 3425 long getPssMinimum(int state) { 3426 int idx = binarySearch(mPssTable, mPssTableSize, state); 3427 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0; 3428 } 3429 3430 long getPssAverage(int state) { 3431 int idx = binarySearch(mPssTable, mPssTableSize, state); 3432 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0; 3433 } 3434 3435 long getPssMaximum(int state) { 3436 int idx = binarySearch(mPssTable, mPssTableSize, state); 3437 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0; 3438 } 3439 3440 long getPssUssMinimum(int state) { 3441 int idx = binarySearch(mPssTable, mPssTableSize, state); 3442 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0; 3443 } 3444 3445 long getPssUssAverage(int state) { 3446 int idx = binarySearch(mPssTable, mPssTableSize, state); 3447 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0; 3448 } 3449 3450 long getPssUssMaximum(int state) { 3451 int idx = binarySearch(mPssTable, mPssTableSize, state); 3452 return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0; 3453 } 3454 3455 public String toString() { 3456 StringBuilder sb = new StringBuilder(128); 3457 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this))) 3458 .append(" ").append(mName).append("/").append(mUid) 3459 .append(" pkg=").append(mPackage); 3460 if (mMultiPackage) sb.append(" (multi)"); 3461 if (mCommonProcess != this) sb.append(" (sub)"); 3462 sb.append("}"); 3463 return sb.toString(); 3464 } 3465 } 3466 3467 public static final class ServiceState extends DurationsTable { 3468 public final String mPackage; 3469 public final String mProcessName; 3470 ProcessState mProc; 3471 3472 Object mOwner; 3473 3474 public static final int SERVICE_RUN = 0; 3475 public static final int SERVICE_STARTED = 1; 3476 public static final int SERVICE_BOUND = 2; 3477 public static final int SERVICE_EXEC = 3; 3478 static final int SERVICE_COUNT = 4; 3479 3480 int mRunCount; 3481 public int mRunState = STATE_NOTHING; 3482 long mRunStartTime; 3483 3484 boolean mStarted; 3485 boolean mRestarting; 3486 int mStartedCount; 3487 public int mStartedState = STATE_NOTHING; 3488 long mStartedStartTime; 3489 3490 int mBoundCount; 3491 public int mBoundState = STATE_NOTHING; 3492 long mBoundStartTime; 3493 3494 int mExecCount; 3495 public int mExecState = STATE_NOTHING; 3496 long mExecStartTime; 3497 3498 public ServiceState(ProcessStats processStats, String pkg, String name, 3499 String processName, ProcessState proc) { 3500 super(processStats, name); 3501 mPackage = pkg; 3502 mProcessName = processName; 3503 mProc = proc; 3504 } 3505 3506 public void applyNewOwner(Object newOwner) { 3507 if (mOwner != newOwner) { 3508 if (mOwner == null) { 3509 mOwner = newOwner; 3510 mProc.incActiveServices(mName); 3511 } else { 3512 // There was already an old owner, reset this object for its 3513 // new owner. 3514 mOwner = newOwner; 3515 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { 3516 long now = SystemClock.uptimeMillis(); 3517 if (mStarted) { 3518 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner 3519 + " from " + mOwner + " while started: pkg=" 3520 + mPackage + " service=" + mName + " proc=" + mProc); 3521 setStarted(false, 0, now); 3522 } 3523 if (mBoundState != STATE_NOTHING) { 3524 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner 3525 + " from " + mOwner + " while bound: pkg=" 3526 + mPackage + " service=" + mName + " proc=" + mProc); 3527 setBound(false, 0, now); 3528 } 3529 if (mExecState != STATE_NOTHING) { 3530 if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner 3531 + " from " + mOwner + " while executing: pkg=" 3532 + mPackage + " service=" + mName + " proc=" + mProc); 3533 setExecuting(false, 0, now); 3534 } 3535 } 3536 } 3537 } 3538 } 3539 3540 public void clearCurrentOwner(Object owner, boolean silently) { 3541 if (mOwner == owner) { 3542 mProc.decActiveServices(mName); 3543 if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { 3544 long now = SystemClock.uptimeMillis(); 3545 if (mStarted) { 3546 if (!silently) { 3547 Slog.wtfStack(TAG, "Service owner " + owner 3548 + " cleared while started: pkg=" + mPackage + " service=" 3549 + mName + " proc=" + mProc); 3550 } 3551 setStarted(false, 0, now); 3552 } 3553 if (mBoundState != STATE_NOTHING) { 3554 if (!silently) { 3555 Slog.wtfStack(TAG, "Service owner " + owner 3556 + " cleared while bound: pkg=" + mPackage + " service=" 3557 + mName + " proc=" + mProc); 3558 } 3559 setBound(false, 0, now); 3560 } 3561 if (mExecState != STATE_NOTHING) { 3562 if (!silently) { 3563 Slog.wtfStack(TAG, "Service owner " + owner 3564 + " cleared while exec: pkg=" + mPackage + " service=" 3565 + mName + " proc=" + mProc); 3566 } 3567 setExecuting(false, 0, now); 3568 } 3569 } 3570 mOwner = null; 3571 } 3572 } 3573 3574 public boolean isInUse() { 3575 return mOwner != null || mRestarting; 3576 } 3577 3578 public boolean isRestarting() { 3579 return mRestarting; 3580 } 3581 3582 void add(ServiceState other) { 3583 addDurations(other); 3584 mRunCount += other.mRunCount; 3585 mStartedCount += other.mStartedCount; 3586 mBoundCount += other.mBoundCount; 3587 mExecCount += other.mExecCount; 3588 } 3589 3590 void resetSafely(long now) { 3591 resetDurationsSafely(); 3592 mRunCount = mRunState != STATE_NOTHING ? 1 : 0; 3593 mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0; 3594 mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0; 3595 mExecCount = mExecState != STATE_NOTHING ? 1 : 0; 3596 mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now; 3597 } 3598 3599 void writeToParcel(Parcel out, long now) { 3600 writeDurationsToParcel(out); 3601 out.writeInt(mRunCount); 3602 out.writeInt(mStartedCount); 3603 out.writeInt(mBoundCount); 3604 out.writeInt(mExecCount); 3605 } 3606 3607 boolean readFromParcel(Parcel in) { 3608 if (!readDurationsFromParcel(in)) { 3609 return false; 3610 } 3611 mRunCount = in.readInt(); 3612 mStartedCount = in.readInt(); 3613 mBoundCount = in.readInt(); 3614 mExecCount = in.readInt(); 3615 return true; 3616 } 3617 3618 void commitStateTime(long now) { 3619 if (mRunState != STATE_NOTHING) { 3620 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime); 3621 mRunStartTime = now; 3622 } 3623 if (mStartedState != STATE_NOTHING) { 3624 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT), 3625 now - mStartedStartTime); 3626 mStartedStartTime = now; 3627 } 3628 if (mBoundState != STATE_NOTHING) { 3629 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime); 3630 mBoundStartTime = now; 3631 } 3632 if (mExecState != STATE_NOTHING) { 3633 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime); 3634 mExecStartTime = now; 3635 } 3636 } 3637 3638 private void updateRunning(int memFactor, long now) { 3639 final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING 3640 || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING; 3641 if (mRunState != state) { 3642 if (mRunState != STATE_NOTHING) { 3643 addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), 3644 now - mRunStartTime); 3645 } else if (state != STATE_NOTHING) { 3646 mRunCount++; 3647 } 3648 mRunState = state; 3649 mRunStartTime = now; 3650 } 3651 } 3652 3653 public void setStarted(boolean started, int memFactor, long now) { 3654 if (mOwner == null) { 3655 Slog.wtf(TAG, "Starting service " + this + " without owner"); 3656 } 3657 mStarted = started; 3658 updateStartedState(memFactor, now); 3659 } 3660 3661 public void setRestarting(boolean restarting, int memFactor, long now) { 3662 mRestarting = restarting; 3663 updateStartedState(memFactor, now); 3664 } 3665 3666 void updateStartedState(int memFactor, long now) { 3667 final boolean wasStarted = mStartedState != STATE_NOTHING; 3668 final boolean started = mStarted || mRestarting; 3669 final int state = started ? memFactor : STATE_NOTHING; 3670 if (mStartedState != state) { 3671 if (mStartedState != STATE_NOTHING) { 3672 addDuration(SERVICE_STARTED + (mStartedState*SERVICE_COUNT), 3673 now - mStartedStartTime); 3674 } else if (started) { 3675 mStartedCount++; 3676 } 3677 mStartedState = state; 3678 mStartedStartTime = now; 3679 mProc = mProc.pullFixedProc(mPackage); 3680 if (wasStarted != started) { 3681 if (started) { 3682 mProc.incStartedServices(memFactor, now, mName); 3683 } else { 3684 mProc.decStartedServices(memFactor, now, mName); 3685 } 3686 } 3687 updateRunning(memFactor, now); 3688 } 3689 } 3690 3691 public void setBound(boolean bound, int memFactor, long now) { 3692 if (mOwner == null) { 3693 Slog.wtf(TAG, "Binding service " + this + " without owner"); 3694 } 3695 final int state = bound ? memFactor : STATE_NOTHING; 3696 if (mBoundState != state) { 3697 if (mBoundState != STATE_NOTHING) { 3698 addDuration(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), 3699 now - mBoundStartTime); 3700 } else if (bound) { 3701 mBoundCount++; 3702 } 3703 mBoundState = state; 3704 mBoundStartTime = now; 3705 updateRunning(memFactor, now); 3706 } 3707 } 3708 3709 public void setExecuting(boolean executing, int memFactor, long now) { 3710 if (mOwner == null) { 3711 Slog.wtf(TAG, "Executing service " + this + " without owner"); 3712 } 3713 final int state = executing ? memFactor : STATE_NOTHING; 3714 if (mExecState != state) { 3715 if (mExecState != STATE_NOTHING) { 3716 addDuration(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime); 3717 } else if (executing) { 3718 mExecCount++; 3719 } 3720 mExecState = state; 3721 mExecStartTime = now; 3722 updateRunning(memFactor, now); 3723 } 3724 } 3725 3726 private long getDuration(int opType, int curState, long startTime, int memFactor, 3727 long now) { 3728 int state = opType + (memFactor*SERVICE_COUNT); 3729 long time = getDuration(state, now); 3730 if (curState == memFactor) { 3731 time += now - startTime; 3732 } 3733 return time; 3734 } 3735 3736 public String toString() { 3737 return "ServiceState{" + Integer.toHexString(System.identityHashCode(this)) 3738 + " " + mName + " pkg=" + mPackage + " proc=" 3739 + Integer.toHexString(System.identityHashCode(this)) + "}"; 3740 } 3741 } 3742 3743 public static final class PackageState { 3744 public final ArrayMap<String, ProcessState> mProcesses 3745 = new ArrayMap<String, ProcessState>(); 3746 public final ArrayMap<String, ServiceState> mServices 3747 = new ArrayMap<String, ServiceState>(); 3748 public final String mPackageName; 3749 public final int mUid; 3750 3751 public PackageState(String packageName, int uid) { 3752 mUid = uid; 3753 mPackageName = packageName; 3754 } 3755 } 3756 3757 public static final class ProcessDataCollection { 3758 final int[] screenStates; 3759 final int[] memStates; 3760 final int[] procStates; 3761 3762 public long totalTime; 3763 public long numPss; 3764 public long minPss; 3765 public long avgPss; 3766 public long maxPss; 3767 public long minUss; 3768 public long avgUss; 3769 public long maxUss; 3770 3771 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) { 3772 screenStates = _screenStates; 3773 memStates = _memStates; 3774 procStates = _procStates; 3775 } 3776 3777 void print(PrintWriter pw, long overallTime, boolean full) { 3778 if (totalTime > overallTime) { 3779 pw.print("*"); 3780 } 3781 printPercent(pw, (double) totalTime / (double) overallTime); 3782 if (numPss > 0) { 3783 pw.print(" ("); 3784 printSizeValue(pw, minPss * 1024); 3785 pw.print("-"); 3786 printSizeValue(pw, avgPss * 1024); 3787 pw.print("-"); 3788 printSizeValue(pw, maxPss * 1024); 3789 pw.print("/"); 3790 printSizeValue(pw, minUss * 1024); 3791 pw.print("-"); 3792 printSizeValue(pw, avgUss * 1024); 3793 pw.print("-"); 3794 printSizeValue(pw, maxUss * 1024); 3795 if (full) { 3796 pw.print(" over "); 3797 pw.print(numPss); 3798 } 3799 pw.print(")"); 3800 } 3801 } 3802 } 3803 3804 public static class TotalMemoryUseCollection { 3805 final int[] screenStates; 3806 final int[] memStates; 3807 3808 public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) { 3809 screenStates = _screenStates; 3810 memStates = _memStates; 3811 } 3812 3813 public long totalTime; 3814 public long[] processStatePss = new long[STATE_COUNT]; 3815 public double[] processStateWeight = new double[STATE_COUNT]; 3816 public long[] processStateTime = new long[STATE_COUNT]; 3817 public int[] processStateSamples = new int[STATE_COUNT]; 3818 public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT]; 3819 public double sysMemCachedWeight; 3820 public double sysMemFreeWeight; 3821 public double sysMemZRamWeight; 3822 public double sysMemKernelWeight; 3823 public double sysMemNativeWeight; 3824 public int sysMemSamples; 3825 } 3826 } 3827