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