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