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