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