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