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