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