1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.app.procstats; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 import android.os.SystemClock; 22 import android.os.SystemProperties; 23 import android.os.UserHandle; 24 import android.text.format.DateFormat; 25 import android.util.ArrayMap; 26 import android.util.ArraySet; 27 import android.util.DebugUtils; 28 import android.util.Log; 29 import android.util.Slog; 30 import android.util.SparseArray; 31 import android.util.TimeUtils; 32 33 import com.android.internal.app.procstats.ProcessStats; 34 import com.android.internal.app.procstats.ProcessStats.PackageState; 35 import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder; 36 import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection; 37 import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT; 38 import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM; 39 import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE; 40 import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM; 41 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM; 42 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_AVERAGE; 43 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM; 44 import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT; 45 import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING; 46 import static com.android.internal.app.procstats.ProcessStats.STATE_PERSISTENT; 47 import static com.android.internal.app.procstats.ProcessStats.STATE_TOP; 48 import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_FOREGROUND; 49 import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND; 50 import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP; 51 import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT; 52 import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE; 53 import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE_RESTARTING; 54 import static com.android.internal.app.procstats.ProcessStats.STATE_RECEIVER; 55 import static com.android.internal.app.procstats.ProcessStats.STATE_HOME; 56 import static com.android.internal.app.procstats.ProcessStats.STATE_LAST_ACTIVITY; 57 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY; 58 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY_CLIENT; 59 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY; 60 import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT; 61 62 import dalvik.system.VMRuntime; 63 import libcore.util.EmptyArray; 64 65 import java.io.IOException; 66 import java.io.InputStream; 67 import java.io.PrintWriter; 68 import java.util.ArrayList; 69 import java.util.Arrays; 70 import java.util.Collections; 71 import java.util.Comparator; 72 import java.util.Objects; 73 74 public final class ProcessState { 75 private static final String TAG = "ProcessStats"; 76 private static final boolean DEBUG = false; 77 private static final boolean DEBUG_PARCEL = false; 78 79 // Map from process states to the states we track. 80 private static final int[] PROCESS_STATE_TO_STATE = new int[] { 81 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT 82 STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI 83 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP 84 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE 85 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE 86 STATE_TOP, // ActivityManager.PROCESS_STATE_TOP_SLEEPING 87 STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND 88 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 89 STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND 90 STATE_BACKUP, // ActivityManager.PROCESS_STATE_BACKUP 91 STATE_HEAVY_WEIGHT, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT 92 STATE_SERVICE, // ActivityManager.PROCESS_STATE_SERVICE 93 STATE_RECEIVER, // ActivityManager.PROCESS_STATE_RECEIVER 94 STATE_HOME, // ActivityManager.PROCESS_STATE_HOME 95 STATE_LAST_ACTIVITY, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY 96 STATE_CACHED_ACTIVITY, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY 97 STATE_CACHED_ACTIVITY_CLIENT, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT 98 STATE_CACHED_EMPTY, // ActivityManager.PROCESS_STATE_CACHED_EMPTY 99 }; 100 101 public static final Comparator<ProcessState> COMPARATOR = new Comparator<ProcessState>() { 102 @Override 103 public int compare(ProcessState lhs, ProcessState rhs) { 104 if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) { 105 return -1; 106 } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) { 107 return 1; 108 } 109 return 0; 110 } 111 }; 112 113 static class PssAggr { 114 long pss = 0; 115 long samples = 0; 116 add(long newPss, long newSamples)117 void add(long newPss, long newSamples) { 118 pss = (long)( (pss*(double)samples) + (newPss*(double)newSamples) ) 119 / (samples+newSamples); 120 samples += newSamples; 121 } 122 } 123 124 // Used by reset to count rather than storing extra maps. Be careful. 125 public int tmpNumInUse; 126 public ProcessState tmpFoundSubProc; 127 128 private final ProcessStats mStats; 129 private final String mName; 130 private final String mPackage; 131 private final int mUid; 132 private final int mVersion; 133 private final DurationsTable mDurations; 134 private final PssTable mPssTable; 135 136 private ProcessState mCommonProcess; 137 private int mCurState = STATE_NOTHING; 138 private long mStartTime; 139 140 private int mLastPssState = STATE_NOTHING; 141 private long mLastPssTime; 142 143 private boolean mActive; 144 private int mNumActiveServices; 145 private int mNumStartedServices; 146 147 private int mNumExcessiveWake; 148 private int mNumExcessiveCpu; 149 150 private int mNumCachedKill; 151 private long mMinCachedKillPss; 152 private long mAvgCachedKillPss; 153 private long mMaxCachedKillPss; 154 155 private boolean mMultiPackage; 156 private boolean mDead; 157 158 // Set in computeProcessTimeLocked and used by COMPARATOR to sort. Be careful. 159 private long mTmpTotalTime; 160 161 /** 162 * Create a new top-level process state, for the initial case where there is only 163 * a single package running in a process. The initial state is not running. 164 */ ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name)165 public ProcessState(ProcessStats processStats, String pkg, int uid, int vers, String name) { 166 mStats = processStats; 167 mName = name; 168 mCommonProcess = this; 169 mPackage = pkg; 170 mUid = uid; 171 mVersion = vers; 172 mDurations = new DurationsTable(processStats.mTableData); 173 mPssTable = new PssTable(processStats.mTableData); 174 } 175 176 /** 177 * Create a new per-package process state for an existing top-level process 178 * state. The current running state of the top-level process is also copied, 179 * marked as started running at 'now'. 180 */ ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name, long now)181 public ProcessState(ProcessState commonProcess, String pkg, int uid, int vers, String name, 182 long now) { 183 mStats = commonProcess.mStats; 184 mName = name; 185 mCommonProcess = commonProcess; 186 mPackage = pkg; 187 mUid = uid; 188 mVersion = vers; 189 mCurState = commonProcess.mCurState; 190 mStartTime = now; 191 mDurations = new DurationsTable(commonProcess.mStats.mTableData); 192 mPssTable = new PssTable(commonProcess.mStats.mTableData); 193 } 194 clone(long now)195 public ProcessState clone(long now) { 196 ProcessState pnew = new ProcessState(this, mPackage, mUid, mVersion, mName, now); 197 pnew.mDurations.addDurations(mDurations); 198 pnew.mPssTable.copyFrom(mPssTable, PSS_COUNT); 199 pnew.mNumExcessiveWake = mNumExcessiveWake; 200 pnew.mNumExcessiveCpu = mNumExcessiveCpu; 201 pnew.mNumCachedKill = mNumCachedKill; 202 pnew.mMinCachedKillPss = mMinCachedKillPss; 203 pnew.mAvgCachedKillPss = mAvgCachedKillPss; 204 pnew.mMaxCachedKillPss = mMaxCachedKillPss; 205 pnew.mActive = mActive; 206 pnew.mNumActiveServices = mNumActiveServices; 207 pnew.mNumStartedServices = mNumStartedServices; 208 return pnew; 209 } 210 getName()211 public String getName() { 212 return mName; 213 } 214 getCommonProcess()215 public ProcessState getCommonProcess() { 216 return mCommonProcess; 217 } 218 219 /** 220 * Say that we are not part of a shared process, so mCommonProcess = this. 221 */ makeStandalone()222 public void makeStandalone() { 223 mCommonProcess = this; 224 } 225 getPackage()226 public String getPackage() { 227 return mPackage; 228 } 229 getUid()230 public int getUid() { 231 return mUid; 232 } 233 getVersion()234 public int getVersion() { 235 return mVersion; 236 } 237 isMultiPackage()238 public boolean isMultiPackage() { 239 return mMultiPackage; 240 } 241 setMultiPackage(boolean val)242 public void setMultiPackage(boolean val) { 243 mMultiPackage = val; 244 } 245 getDurationsBucketCount()246 public int getDurationsBucketCount() { 247 return mDurations.getKeyCount(); 248 } 249 add(ProcessState other)250 public void add(ProcessState other) { 251 mDurations.addDurations(other.mDurations); 252 mPssTable.mergeStats(other.mPssTable); 253 mNumExcessiveWake += other.mNumExcessiveWake; 254 mNumExcessiveCpu += other.mNumExcessiveCpu; 255 if (other.mNumCachedKill > 0) { 256 addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss, 257 other.mAvgCachedKillPss, other.mMaxCachedKillPss); 258 } 259 } 260 resetSafely(long now)261 public void resetSafely(long now) { 262 mDurations.resetTable(); 263 mPssTable.resetTable(); 264 mStartTime = now; 265 mLastPssState = STATE_NOTHING; 266 mLastPssTime = 0; 267 mNumExcessiveWake = 0; 268 mNumExcessiveCpu = 0; 269 mNumCachedKill = 0; 270 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0; 271 } 272 makeDead()273 public void makeDead() { 274 mDead = true; 275 } 276 ensureNotDead()277 private void ensureNotDead() { 278 if (!mDead) { 279 return; 280 } 281 Slog.w(TAG, "ProcessState dead: name=" + mName 282 + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName); 283 } 284 writeToParcel(Parcel out, long now)285 public void writeToParcel(Parcel out, long now) { 286 out.writeInt(mMultiPackage ? 1 : 0); 287 mDurations.writeToParcel(out); 288 mPssTable.writeToParcel(out); 289 out.writeInt(mNumExcessiveWake); 290 out.writeInt(mNumExcessiveCpu); 291 out.writeInt(mNumCachedKill); 292 if (mNumCachedKill > 0) { 293 out.writeLong(mMinCachedKillPss); 294 out.writeLong(mAvgCachedKillPss); 295 out.writeLong(mMaxCachedKillPss); 296 } 297 } 298 readFromParcel(Parcel in, boolean fully)299 public boolean readFromParcel(Parcel in, boolean fully) { 300 boolean multiPackage = in.readInt() != 0; 301 if (fully) { 302 mMultiPackage = multiPackage; 303 } 304 if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table..."); 305 if (!mDurations.readFromParcel(in)) { 306 return false; 307 } 308 if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table..."); 309 if (!mPssTable.readFromParcel(in)) { 310 return false; 311 } 312 mNumExcessiveWake = in.readInt(); 313 mNumExcessiveCpu = in.readInt(); 314 mNumCachedKill = in.readInt(); 315 if (mNumCachedKill > 0) { 316 mMinCachedKillPss = in.readLong(); 317 mAvgCachedKillPss = in.readLong(); 318 mMaxCachedKillPss = in.readLong(); 319 } else { 320 mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0; 321 } 322 return true; 323 } 324 makeActive()325 public void makeActive() { 326 ensureNotDead(); 327 mActive = true; 328 } 329 makeInactive()330 public void makeInactive() { 331 mActive = false; 332 } 333 isInUse()334 public boolean isInUse() { 335 return mActive || mNumActiveServices > 0 || mNumStartedServices > 0 336 || mCurState != STATE_NOTHING; 337 } 338 isActive()339 public boolean isActive() { 340 return mActive; 341 } 342 hasAnyData()343 public boolean hasAnyData() { 344 return !(mDurations.getKeyCount() == 0 345 && mCurState == STATE_NOTHING 346 && mPssTable.getKeyCount() == 0); 347 } 348 349 /** 350 * Update the current state of the given list of processes. 351 * 352 * @param state Current ActivityManager.PROCESS_STATE_* 353 * @param memFactor Current mem factor constant. 354 * @param now Current time. 355 * @param pkgList Processes to update. 356 */ setState(int state, int memFactor, long now, ArrayMap<String, ProcessStateHolder> pkgList)357 public void setState(int state, int memFactor, long now, 358 ArrayMap<String, ProcessStateHolder> pkgList) { 359 if (state < 0) { 360 state = mNumStartedServices > 0 361 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING; 362 } else { 363 state = PROCESS_STATE_TO_STATE[state] + (memFactor*STATE_COUNT); 364 } 365 366 // First update the common process. 367 mCommonProcess.setState(state, now); 368 369 // If the common process is not multi-package, there is nothing else to do. 370 if (!mCommonProcess.mMultiPackage) { 371 return; 372 } 373 374 if (pkgList != null) { 375 for (int ip=pkgList.size()-1; ip>=0; ip--) { 376 pullFixedProc(pkgList, ip).setState(state, now); 377 } 378 } 379 } 380 setState(int state, long now)381 public void setState(int state, long now) { 382 ensureNotDead(); 383 if (!mDead && (mCurState != state)) { 384 //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state); 385 commitStateTime(now); 386 mCurState = state; 387 } 388 } 389 commitStateTime(long now)390 public void commitStateTime(long now) { 391 if (mCurState != STATE_NOTHING) { 392 long dur = now - mStartTime; 393 if (dur > 0) { 394 mDurations.addDuration(mCurState, dur); 395 } 396 } 397 mStartTime = now; 398 } 399 incActiveServices(String serviceName)400 public void incActiveServices(String serviceName) { 401 if (DEBUG && "".equals(mName)) { 402 RuntimeException here = new RuntimeException("here"); 403 here.fillInStackTrace(); 404 Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName 405 + " to " + (mNumActiveServices+1), here); 406 } 407 if (mCommonProcess != this) { 408 mCommonProcess.incActiveServices(serviceName); 409 } 410 mNumActiveServices++; 411 } 412 decActiveServices(String serviceName)413 public void decActiveServices(String serviceName) { 414 if (DEBUG && "".equals(mName)) { 415 RuntimeException here = new RuntimeException("here"); 416 here.fillInStackTrace(); 417 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName 418 + " to " + (mNumActiveServices-1), here); 419 } 420 if (mCommonProcess != this) { 421 mCommonProcess.decActiveServices(serviceName); 422 } 423 mNumActiveServices--; 424 if (mNumActiveServices < 0) { 425 Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage 426 + " uid=" + mUid + " proc=" + mName + " service=" + serviceName); 427 mNumActiveServices = 0; 428 } 429 } 430 incStartedServices(int memFactor, long now, String serviceName)431 public void incStartedServices(int memFactor, long now, String serviceName) { 432 if (false) { 433 RuntimeException here = new RuntimeException("here"); 434 here.fillInStackTrace(); 435 Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName 436 + " to " + (mNumStartedServices+1), here); 437 } 438 if (mCommonProcess != this) { 439 mCommonProcess.incStartedServices(memFactor, now, serviceName); 440 } 441 mNumStartedServices++; 442 if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) { 443 setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now); 444 } 445 } 446 decStartedServices(int memFactor, long now, String serviceName)447 public void decStartedServices(int memFactor, long now, String serviceName) { 448 if (false) { 449 RuntimeException here = new RuntimeException("here"); 450 here.fillInStackTrace(); 451 Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName 452 + " to " + (mNumStartedServices-1), here); 453 } 454 if (mCommonProcess != this) { 455 mCommonProcess.decStartedServices(memFactor, now, serviceName); 456 } 457 mNumStartedServices--; 458 if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) { 459 setState(STATE_NOTHING, now); 460 } else if (mNumStartedServices < 0) { 461 Slog.wtfStack(TAG, "Proc started services underrun: pkg=" 462 + mPackage + " uid=" + mUid + " name=" + mName); 463 mNumStartedServices = 0; 464 } 465 } 466 addPss(long pss, long uss, boolean always, ArrayMap<String, ProcessStateHolder> pkgList)467 public void addPss(long pss, long uss, boolean always, 468 ArrayMap<String, ProcessStateHolder> pkgList) { 469 ensureNotDead(); 470 if (!always) { 471 if (mLastPssState == mCurState && SystemClock.uptimeMillis() 472 < (mLastPssTime+(30*1000))) { 473 return; 474 } 475 } 476 mLastPssState = mCurState; 477 mLastPssTime = SystemClock.uptimeMillis(); 478 if (mCurState != STATE_NOTHING) { 479 // First update the common process. 480 mCommonProcess.mPssTable.mergeStats(mCurState, 1, pss, pss, pss, uss, uss, uss); 481 482 // If the common process is not multi-package, there is nothing else to do. 483 if (!mCommonProcess.mMultiPackage) { 484 return; 485 } 486 487 if (pkgList != null) { 488 for (int ip=pkgList.size()-1; ip>=0; ip--) { 489 pullFixedProc(pkgList, ip).mPssTable.mergeStats(mCurState, 1, 490 pss, pss, pss, uss, uss, uss); 491 } 492 } 493 } 494 } 495 reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList)496 public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) { 497 ensureNotDead(); 498 mCommonProcess.mNumExcessiveWake++; 499 if (!mCommonProcess.mMultiPackage) { 500 return; 501 } 502 503 for (int ip=pkgList.size()-1; ip>=0; ip--) { 504 pullFixedProc(pkgList, ip).mNumExcessiveWake++; 505 } 506 } 507 reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList)508 public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) { 509 ensureNotDead(); 510 mCommonProcess.mNumExcessiveCpu++; 511 if (!mCommonProcess.mMultiPackage) { 512 return; 513 } 514 515 for (int ip=pkgList.size()-1; ip>=0; ip--) { 516 pullFixedProc(pkgList, ip).mNumExcessiveCpu++; 517 } 518 } 519 addCachedKill(int num, long minPss, long avgPss, long maxPss)520 private void addCachedKill(int num, long minPss, long avgPss, long maxPss) { 521 if (mNumCachedKill <= 0) { 522 mNumCachedKill = num; 523 mMinCachedKillPss = minPss; 524 mAvgCachedKillPss = avgPss; 525 mMaxCachedKillPss = maxPss; 526 } else { 527 if (minPss < mMinCachedKillPss) { 528 mMinCachedKillPss = minPss; 529 } 530 if (maxPss > mMaxCachedKillPss) { 531 mMaxCachedKillPss = maxPss; 532 } 533 mAvgCachedKillPss = (long)( ((mAvgCachedKillPss*(double)mNumCachedKill) + avgPss) 534 / (mNumCachedKill+num) ); 535 mNumCachedKill += num; 536 } 537 } 538 reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss)539 public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) { 540 ensureNotDead(); 541 mCommonProcess.addCachedKill(1, pss, pss, pss); 542 if (!mCommonProcess.mMultiPackage) { 543 return; 544 } 545 546 for (int ip=pkgList.size()-1; ip>=0; ip--) { 547 pullFixedProc(pkgList, ip).addCachedKill(1, pss, pss, pss); 548 } 549 } 550 pullFixedProc(String pkgName)551 public ProcessState pullFixedProc(String pkgName) { 552 if (mMultiPackage) { 553 // The array map is still pointing to a common process state 554 // that is now shared across packages. Update it to point to 555 // the new per-package state. 556 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgName, mUid); 557 if (vpkg == null) { 558 throw new IllegalStateException("Didn't find package " + pkgName 559 + " / " + mUid); 560 } 561 PackageState pkg = vpkg.get(mVersion); 562 if (pkg == null) { 563 throw new IllegalStateException("Didn't find package " + pkgName 564 + " / " + mUid + " vers " + mVersion); 565 } 566 ProcessState proc = pkg.mProcesses.get(mName); 567 if (proc == null) { 568 throw new IllegalStateException("Didn't create per-package process " 569 + mName + " in pkg " + pkgName + " / " + mUid + " vers " + mVersion); 570 } 571 return proc; 572 } 573 return this; 574 } 575 pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList, int index)576 private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList, 577 int index) { 578 ProcessStateHolder holder = pkgList.valueAt(index); 579 ProcessState proc = holder.state; 580 if (mDead && proc.mCommonProcess != proc) { 581 // Somehow we are contining to use a process state that is dead, because 582 // it was not being told it was active during the last commit. We can recover 583 // from this by generating a fresh new state, but this is bad because we 584 // are losing whatever data we had in the old process state. 585 Log.wtf(TAG, "Pulling dead proc: name=" + mName + " pkg=" + mPackage 586 + " uid=" + mUid + " common.name=" + mCommonProcess.mName); 587 proc = mStats.getProcessStateLocked(proc.mPackage, proc.mUid, proc.mVersion, 588 proc.mName); 589 } 590 if (proc.mMultiPackage) { 591 // The array map is still pointing to a common process state 592 // that is now shared across packages. Update it to point to 593 // the new per-package state. 594 SparseArray<PackageState> vpkg = mStats.mPackages.get(pkgList.keyAt(index), 595 proc.mUid); 596 if (vpkg == null) { 597 throw new IllegalStateException("No existing package " 598 + pkgList.keyAt(index) + "/" + proc.mUid 599 + " for multi-proc " + proc.mName); 600 } 601 PackageState pkg = vpkg.get(proc.mVersion); 602 if (pkg == null) { 603 throw new IllegalStateException("No existing package " 604 + pkgList.keyAt(index) + "/" + proc.mUid 605 + " for multi-proc " + proc.mName + " version " + proc.mVersion); 606 } 607 String savedName = proc.mName; 608 proc = pkg.mProcesses.get(proc.mName); 609 if (proc == null) { 610 throw new IllegalStateException("Didn't create per-package process " 611 + savedName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid); 612 } 613 holder.state = proc; 614 } 615 return proc; 616 } 617 getDuration(int state, long now)618 public long getDuration(int state, long now) { 619 long time = mDurations.getValueForId((byte)state); 620 if (mCurState == state) { 621 time += now - mStartTime; 622 } 623 return time; 624 } 625 getPssSampleCount(int state)626 public long getPssSampleCount(int state) { 627 return mPssTable.getValueForId((byte)state, PSS_SAMPLE_COUNT); 628 } 629 getPssMinimum(int state)630 public long getPssMinimum(int state) { 631 return mPssTable.getValueForId((byte)state, PSS_MINIMUM); 632 } 633 getPssAverage(int state)634 public long getPssAverage(int state) { 635 return mPssTable.getValueForId((byte)state, PSS_AVERAGE); 636 } 637 getPssMaximum(int state)638 public long getPssMaximum(int state) { 639 return mPssTable.getValueForId((byte)state, PSS_MAXIMUM); 640 } 641 getPssUssMinimum(int state)642 public long getPssUssMinimum(int state) { 643 return mPssTable.getValueForId((byte)state, PSS_USS_MINIMUM); 644 } 645 getPssUssAverage(int state)646 public long getPssUssAverage(int state) { 647 return mPssTable.getValueForId((byte)state, PSS_USS_AVERAGE); 648 } 649 getPssUssMaximum(int state)650 public long getPssUssMaximum(int state) { 651 return mPssTable.getValueForId((byte)state, PSS_USS_MAXIMUM); 652 } 653 654 /** 655 * Sums up the PSS data and adds it to 'data'. 656 * 657 * @param data The aggregate data is added here. 658 * @param now SystemClock.uptimeMillis() 659 */ aggregatePss(TotalMemoryUseCollection data, long now)660 public void aggregatePss(TotalMemoryUseCollection data, long now) { 661 final PssAggr fgPss = new PssAggr(); 662 final PssAggr bgPss = new PssAggr(); 663 final PssAggr cachedPss = new PssAggr(); 664 boolean havePss = false; 665 for (int i=0; i<mDurations.getKeyCount(); i++) { 666 final int key = mDurations.getKeyAt(i); 667 int type = SparseMappingTable.getIdFromKey(key); 668 int procState = type % STATE_COUNT; 669 long samples = getPssSampleCount(type); 670 if (samples > 0) { 671 long avg = getPssAverage(type); 672 havePss = true; 673 if (procState <= STATE_IMPORTANT_FOREGROUND) { 674 fgPss.add(avg, samples); 675 } else if (procState <= STATE_RECEIVER) { 676 bgPss.add(avg, samples); 677 } else { 678 cachedPss.add(avg, samples); 679 } 680 } 681 } 682 if (!havePss) { 683 return; 684 } 685 boolean fgHasBg = false; 686 boolean fgHasCached = false; 687 boolean bgHasCached = false; 688 if (fgPss.samples < 3 && bgPss.samples > 0) { 689 fgHasBg = true; 690 fgPss.add(bgPss.pss, bgPss.samples); 691 } 692 if (fgPss.samples < 3 && cachedPss.samples > 0) { 693 fgHasCached = true; 694 fgPss.add(cachedPss.pss, cachedPss.samples); 695 } 696 if (bgPss.samples < 3 && cachedPss.samples > 0) { 697 bgHasCached = true; 698 bgPss.add(cachedPss.pss, cachedPss.samples); 699 } 700 if (bgPss.samples < 3 && !fgHasBg && fgPss.samples > 0) { 701 bgPss.add(fgPss.pss, fgPss.samples); 702 } 703 if (cachedPss.samples < 3 && !bgHasCached && bgPss.samples > 0) { 704 cachedPss.add(bgPss.pss, bgPss.samples); 705 } 706 if (cachedPss.samples < 3 && !fgHasCached && fgPss.samples > 0) { 707 cachedPss.add(fgPss.pss, fgPss.samples); 708 } 709 for (int i=0; i<mDurations.getKeyCount(); i++) { 710 final int key = mDurations.getKeyAt(i); 711 final int type = SparseMappingTable.getIdFromKey(key); 712 long time = mDurations.getValue(key); 713 if (mCurState == type) { 714 time += now - mStartTime; 715 } 716 final int procState = type % STATE_COUNT; 717 data.processStateTime[procState] += time; 718 long samples = getPssSampleCount(type); 719 long avg; 720 if (samples > 0) { 721 avg = getPssAverage(type); 722 } else if (procState <= STATE_IMPORTANT_FOREGROUND) { 723 samples = fgPss.samples; 724 avg = fgPss.pss; 725 } else if (procState <= STATE_RECEIVER) { 726 samples = bgPss.samples; 727 avg = bgPss.pss; 728 } else { 729 samples = cachedPss.samples; 730 avg = cachedPss.pss; 731 } 732 double newAvg = ( (data.processStatePss[procState] 733 * (double)data.processStateSamples[procState]) 734 + (avg*(double)samples) 735 ) / (data.processStateSamples[procState]+samples); 736 data.processStatePss[procState] = (long)newAvg; 737 data.processStateSamples[procState] += samples; 738 data.processStateWeight[procState] += avg * (double)time; 739 } 740 } 741 computeProcessTimeLocked(int[] screenStates, int[] memStates, int[] procStates, long now)742 public long computeProcessTimeLocked(int[] screenStates, int[] memStates, 743 int[] procStates, long now) { 744 long totalTime = 0; 745 for (int is=0; is<screenStates.length; is++) { 746 for (int im=0; im<memStates.length; im++) { 747 for (int ip=0; ip<procStates.length; ip++) { 748 int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT) 749 + procStates[ip]; 750 totalTime += getDuration(bucket, now); 751 } 752 } 753 } 754 mTmpTotalTime = totalTime; 755 return totalTime; 756 } 757 dumpSummary(PrintWriter pw, String prefix, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime)758 public void dumpSummary(PrintWriter pw, String prefix, 759 int[] screenStates, int[] memStates, int[] procStates, 760 long now, long totalTime) { 761 pw.print(prefix); 762 pw.print("* "); 763 pw.print(mName); 764 pw.print(" / "); 765 UserHandle.formatUid(pw, mUid); 766 pw.print(" / v"); 767 pw.print(mVersion); 768 pw.println(":"); 769 dumpProcessSummaryDetails(pw, prefix, " TOTAL: ", screenStates, memStates, 770 procStates, now, totalTime, true); 771 dumpProcessSummaryDetails(pw, prefix, " Persistent: ", screenStates, memStates, 772 new int[] { STATE_PERSISTENT }, now, totalTime, true); 773 dumpProcessSummaryDetails(pw, prefix, " Top: ", screenStates, memStates, 774 new int[] {STATE_TOP}, now, totalTime, true); 775 dumpProcessSummaryDetails(pw, prefix, " Imp Fg: ", screenStates, memStates, 776 new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true); 777 dumpProcessSummaryDetails(pw, prefix, " Imp Bg: ", screenStates, memStates, 778 new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true); 779 dumpProcessSummaryDetails(pw, prefix, " Backup: ", screenStates, memStates, 780 new int[] {STATE_BACKUP}, now, totalTime, true); 781 dumpProcessSummaryDetails(pw, prefix, " Heavy Wgt: ", screenStates, memStates, 782 new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true); 783 dumpProcessSummaryDetails(pw, prefix, " Service: ", screenStates, memStates, 784 new int[] {STATE_SERVICE}, now, totalTime, true); 785 dumpProcessSummaryDetails(pw, prefix, " Service Rs: ", screenStates, memStates, 786 new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true); 787 dumpProcessSummaryDetails(pw, prefix, " Receiver: ", screenStates, memStates, 788 new int[] {STATE_RECEIVER}, now, totalTime, true); 789 dumpProcessSummaryDetails(pw, prefix, " (Home): ", screenStates, memStates, 790 new int[] {STATE_HOME}, now, totalTime, true); 791 dumpProcessSummaryDetails(pw, prefix, " (Last Act): ", screenStates, memStates, 792 new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true); 793 dumpProcessSummaryDetails(pw, prefix, " (Cached): ", screenStates, memStates, 794 new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT, 795 STATE_CACHED_EMPTY}, now, totalTime, true); 796 } 797 dumpProcessState(PrintWriter pw, String prefix, int[] screenStates, int[] memStates, int[] procStates, long now)798 public void dumpProcessState(PrintWriter pw, String prefix, 799 int[] screenStates, int[] memStates, int[] procStates, long now) { 800 long totalTime = 0; 801 int printedScreen = -1; 802 for (int is=0; is<screenStates.length; is++) { 803 int printedMem = -1; 804 for (int im=0; im<memStates.length; im++) { 805 for (int ip=0; ip<procStates.length; ip++) { 806 final int iscreen = screenStates[is]; 807 final int imem = memStates[im]; 808 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip]; 809 long time = mDurations.getValueForId((byte)bucket); 810 String running = ""; 811 if (mCurState == bucket) { 812 running = " (running)"; 813 } 814 if (time != 0) { 815 pw.print(prefix); 816 if (screenStates.length > 1) { 817 DumpUtils.printScreenLabel(pw, printedScreen != iscreen 818 ? iscreen : STATE_NOTHING); 819 printedScreen = iscreen; 820 } 821 if (memStates.length > 1) { 822 DumpUtils.printMemLabel(pw, 823 printedMem != imem ? imem : STATE_NOTHING, '/'); 824 printedMem = imem; 825 } 826 pw.print(DumpUtils.STATE_NAMES[procStates[ip]]); pw.print(": "); 827 TimeUtils.formatDuration(time, pw); pw.println(running); 828 totalTime += time; 829 } 830 } 831 } 832 } 833 if (totalTime != 0) { 834 pw.print(prefix); 835 if (screenStates.length > 1) { 836 DumpUtils.printScreenLabel(pw, STATE_NOTHING); 837 } 838 if (memStates.length > 1) { 839 DumpUtils.printMemLabel(pw, STATE_NOTHING, '/'); 840 } 841 pw.print("TOTAL : "); 842 TimeUtils.formatDuration(totalTime, pw); 843 pw.println(); 844 } 845 } 846 dumpPss(PrintWriter pw, String prefix, int[] screenStates, int[] memStates, int[] procStates)847 public void dumpPss(PrintWriter pw, String prefix, 848 int[] screenStates, int[] memStates, int[] procStates) { 849 boolean printedHeader = false; 850 int printedScreen = -1; 851 for (int is=0; is<screenStates.length; is++) { 852 int printedMem = -1; 853 for (int im=0; im<memStates.length; im++) { 854 for (int ip=0; ip<procStates.length; ip++) { 855 final int iscreen = screenStates[is]; 856 final int imem = memStates[im]; 857 final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip]; 858 long count = getPssSampleCount(bucket); 859 if (count > 0) { 860 if (!printedHeader) { 861 pw.print(prefix); 862 pw.print("PSS/USS ("); 863 pw.print(mPssTable.getKeyCount()); 864 pw.println(" entries):"); 865 printedHeader = true; 866 } 867 pw.print(prefix); 868 pw.print(" "); 869 if (screenStates.length > 1) { 870 DumpUtils.printScreenLabel(pw, 871 printedScreen != iscreen ? iscreen : STATE_NOTHING); 872 printedScreen = iscreen; 873 } 874 if (memStates.length > 1) { 875 DumpUtils.printMemLabel(pw, 876 printedMem != imem ? imem : STATE_NOTHING, '/'); 877 printedMem = imem; 878 } 879 pw.print(DumpUtils.STATE_NAMES[procStates[ip]]); pw.print(": "); 880 pw.print(count); 881 pw.print(" samples "); 882 DebugUtils.printSizeValue(pw, getPssMinimum(bucket) * 1024); 883 pw.print(" "); 884 DebugUtils.printSizeValue(pw, getPssAverage(bucket) * 1024); 885 pw.print(" "); 886 DebugUtils.printSizeValue(pw, getPssMaximum(bucket) * 1024); 887 pw.print(" / "); 888 DebugUtils.printSizeValue(pw, getPssUssMinimum(bucket) * 1024); 889 pw.print(" "); 890 DebugUtils.printSizeValue(pw, getPssUssAverage(bucket) * 1024); 891 pw.print(" "); 892 DebugUtils.printSizeValue(pw, getPssUssMaximum(bucket) * 1024); 893 pw.println(); 894 } 895 } 896 } 897 } 898 if (mNumExcessiveWake != 0) { 899 pw.print(prefix); pw.print("Killed for excessive wake locks: "); 900 pw.print(mNumExcessiveWake); pw.println(" times"); 901 } 902 if (mNumExcessiveCpu != 0) { 903 pw.print(prefix); pw.print("Killed for excessive CPU use: "); 904 pw.print(mNumExcessiveCpu); pw.println(" times"); 905 } 906 if (mNumCachedKill != 0) { 907 pw.print(prefix); pw.print("Killed from cached state: "); 908 pw.print(mNumCachedKill); pw.print(" times from pss "); 909 DebugUtils.printSizeValue(pw, mMinCachedKillPss * 1024); pw.print("-"); 910 DebugUtils.printSizeValue(pw, mAvgCachedKillPss * 1024); pw.print("-"); 911 DebugUtils.printSizeValue(pw, mMaxCachedKillPss * 1024); pw.println(); 912 } 913 } 914 dumpProcessSummaryDetails(PrintWriter pw, String prefix, String label, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime, boolean full)915 private void dumpProcessSummaryDetails(PrintWriter pw, String prefix, 916 String label, int[] screenStates, int[] memStates, int[] procStates, 917 long now, long totalTime, boolean full) { 918 ProcessStats.ProcessDataCollection totals = new ProcessStats.ProcessDataCollection( 919 screenStates, memStates, procStates); 920 computeProcessData(totals, now); 921 final double percentage = (double) totals.totalTime / (double) totalTime * 100; 922 // We don't print percentages < .01, so just drop those. 923 if (percentage >= 0.005 || totals.numPss != 0) { 924 if (prefix != null) { 925 pw.print(prefix); 926 } 927 if (label != null) { 928 pw.print(label); 929 } 930 totals.print(pw, totalTime, full); 931 if (prefix != null) { 932 pw.println(); 933 } 934 } 935 } 936 dumpInternalLocked(PrintWriter pw, String prefix, boolean dumpAll)937 public void dumpInternalLocked(PrintWriter pw, String prefix, boolean dumpAll) { 938 if (dumpAll) { 939 pw.print(prefix); pw.print("myID="); 940 pw.print(Integer.toHexString(System.identityHashCode(this))); 941 pw.print(" mCommonProcess="); 942 pw.print(Integer.toHexString(System.identityHashCode(mCommonProcess))); 943 pw.print(" mPackage="); pw.println(mPackage); 944 if (mMultiPackage) { 945 pw.print(prefix); pw.print("mMultiPackage="); pw.println(mMultiPackage); 946 } 947 if (this != mCommonProcess) { 948 pw.print(prefix); pw.print("Common Proc: "); pw.print(mCommonProcess.mName); 949 pw.print("/"); pw.print(mCommonProcess.mUid); 950 pw.print(" pkg="); pw.println(mCommonProcess.mPackage); 951 } 952 } 953 if (mActive) { 954 pw.print(prefix); pw.print("mActive="); pw.println(mActive); 955 } 956 if (mDead) { 957 pw.print(prefix); pw.print("mDead="); pw.println(mDead); 958 } 959 if (mNumActiveServices != 0 || mNumStartedServices != 0) { 960 pw.print(prefix); pw.print("mNumActiveServices="); pw.print(mNumActiveServices); 961 pw.print(" mNumStartedServices="); 962 pw.println(mNumStartedServices); 963 } 964 } 965 computeProcessData(ProcessStats.ProcessDataCollection data, long now)966 public void computeProcessData(ProcessStats.ProcessDataCollection data, long now) { 967 data.totalTime = 0; 968 data.numPss = data.minPss = data.avgPss = data.maxPss = 969 data.minUss = data.avgUss = data.maxUss = 0; 970 for (int is=0; is<data.screenStates.length; is++) { 971 for (int im=0; im<data.memStates.length; im++) { 972 for (int ip=0; ip<data.procStates.length; ip++) { 973 int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT) 974 + data.procStates[ip]; 975 data.totalTime += getDuration(bucket, now); 976 long samples = getPssSampleCount(bucket); 977 if (samples > 0) { 978 long minPss = getPssMinimum(bucket); 979 long avgPss = getPssAverage(bucket); 980 long maxPss = getPssMaximum(bucket); 981 long minUss = getPssUssMinimum(bucket); 982 long avgUss = getPssUssAverage(bucket); 983 long maxUss = getPssUssMaximum(bucket); 984 if (data.numPss == 0) { 985 data.minPss = minPss; 986 data.avgPss = avgPss; 987 data.maxPss = maxPss; 988 data.minUss = minUss; 989 data.avgUss = avgUss; 990 data.maxUss = maxUss; 991 } else { 992 if (minPss < data.minPss) { 993 data.minPss = minPss; 994 } 995 data.avgPss = (long)( ((data.avgPss*(double)data.numPss) 996 + (avgPss*(double)samples)) / (data.numPss+samples) ); 997 if (maxPss > data.maxPss) { 998 data.maxPss = maxPss; 999 } 1000 if (minUss < data.minUss) { 1001 data.minUss = minUss; 1002 } 1003 data.avgUss = (long)( ((data.avgUss*(double)data.numPss) 1004 + (avgUss*(double)samples)) / (data.numPss+samples) ); 1005 if (maxUss > data.maxUss) { 1006 data.maxUss = maxUss; 1007 } 1008 } 1009 data.numPss += samples; 1010 } 1011 } 1012 } 1013 } 1014 } 1015 dumpCsv(PrintWriter pw, boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, boolean sepProcStates, int[] procStates, long now)1016 public void dumpCsv(PrintWriter pw, 1017 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, 1018 int[] memStates, boolean sepProcStates, int[] procStates, long now) { 1019 final int NSS = sepScreenStates ? screenStates.length : 1; 1020 final int NMS = sepMemStates ? memStates.length : 1; 1021 final int NPS = sepProcStates ? procStates.length : 1; 1022 for (int iss=0; iss<NSS; iss++) { 1023 for (int ims=0; ims<NMS; ims++) { 1024 for (int ips=0; ips<NPS; ips++) { 1025 final int vsscreen = sepScreenStates ? screenStates[iss] : 0; 1026 final int vsmem = sepMemStates ? memStates[ims] : 0; 1027 final int vsproc = sepProcStates ? procStates[ips] : 0; 1028 final int NSA = sepScreenStates ? 1 : screenStates.length; 1029 final int NMA = sepMemStates ? 1 : memStates.length; 1030 final int NPA = sepProcStates ? 1 : procStates.length; 1031 long totalTime = 0; 1032 for (int isa=0; isa<NSA; isa++) { 1033 for (int ima=0; ima<NMA; ima++) { 1034 for (int ipa=0; ipa<NPA; ipa++) { 1035 final int vascreen = sepScreenStates ? 0 : screenStates[isa]; 1036 final int vamem = sepMemStates ? 0 : memStates[ima]; 1037 final int vaproc = sepProcStates ? 0 : procStates[ipa]; 1038 final int bucket = ((vsscreen + vascreen + vsmem + vamem) 1039 * STATE_COUNT) + vsproc + vaproc; 1040 totalTime += getDuration(bucket, now); 1041 } 1042 } 1043 } 1044 pw.print(DumpUtils.CSV_SEP); 1045 pw.print(totalTime); 1046 } 1047 } 1048 } 1049 } 1050 dumpPackageProcCheckin(PrintWriter pw, String pkgName, int uid, int vers, String itemName, long now)1051 public void dumpPackageProcCheckin(PrintWriter pw, String pkgName, int uid, int vers, 1052 String itemName, long now) { 1053 pw.print("pkgproc,"); 1054 pw.print(pkgName); 1055 pw.print(","); 1056 pw.print(uid); 1057 pw.print(","); 1058 pw.print(vers); 1059 pw.print(","); 1060 pw.print(DumpUtils.collapseString(pkgName, itemName)); 1061 dumpAllStateCheckin(pw, now); 1062 pw.println(); 1063 if (mPssTable.getKeyCount() > 0) { 1064 pw.print("pkgpss,"); 1065 pw.print(pkgName); 1066 pw.print(","); 1067 pw.print(uid); 1068 pw.print(","); 1069 pw.print(vers); 1070 pw.print(","); 1071 pw.print(DumpUtils.collapseString(pkgName, itemName)); 1072 dumpAllPssCheckin(pw); 1073 pw.println(); 1074 } 1075 if (mNumExcessiveWake > 0 || mNumExcessiveCpu > 0 || mNumCachedKill > 0) { 1076 pw.print("pkgkills,"); 1077 pw.print(pkgName); 1078 pw.print(","); 1079 pw.print(uid); 1080 pw.print(","); 1081 pw.print(vers); 1082 pw.print(","); 1083 pw.print(DumpUtils.collapseString(pkgName, itemName)); 1084 pw.print(","); 1085 pw.print(mNumExcessiveWake); 1086 pw.print(","); 1087 pw.print(mNumExcessiveCpu); 1088 pw.print(","); 1089 pw.print(mNumCachedKill); 1090 pw.print(","); 1091 pw.print(mMinCachedKillPss); 1092 pw.print(":"); 1093 pw.print(mAvgCachedKillPss); 1094 pw.print(":"); 1095 pw.print(mMaxCachedKillPss); 1096 pw.println(); 1097 } 1098 } 1099 dumpProcCheckin(PrintWriter pw, String procName, int uid, long now)1100 public void dumpProcCheckin(PrintWriter pw, String procName, int uid, long now) { 1101 if (mDurations.getKeyCount() > 0) { 1102 pw.print("proc,"); 1103 pw.print(procName); 1104 pw.print(","); 1105 pw.print(uid); 1106 dumpAllStateCheckin(pw, now); 1107 pw.println(); 1108 } 1109 if (mPssTable.getKeyCount() > 0) { 1110 pw.print("pss,"); 1111 pw.print(procName); 1112 pw.print(","); 1113 pw.print(uid); 1114 dumpAllPssCheckin(pw); 1115 pw.println(); 1116 } 1117 if (mNumExcessiveWake > 0 || mNumExcessiveCpu > 0 || mNumCachedKill > 0) { 1118 pw.print("kills,"); 1119 pw.print(procName); 1120 pw.print(","); 1121 pw.print(uid); 1122 pw.print(","); 1123 pw.print(mNumExcessiveWake); 1124 pw.print(","); 1125 pw.print(mNumExcessiveCpu); 1126 pw.print(","); 1127 pw.print(mNumCachedKill); 1128 pw.print(","); 1129 pw.print(mMinCachedKillPss); 1130 pw.print(":"); 1131 pw.print(mAvgCachedKillPss); 1132 pw.print(":"); 1133 pw.print(mMaxCachedKillPss); 1134 pw.println(); 1135 } 1136 } 1137 dumpAllStateCheckin(PrintWriter pw, long now)1138 public void dumpAllStateCheckin(PrintWriter pw, long now) { 1139 boolean didCurState = false; 1140 for (int i=0; i<mDurations.getKeyCount(); i++) { 1141 final int key = mDurations.getKeyAt(i); 1142 final int type = SparseMappingTable.getIdFromKey(key); 1143 long time = mDurations.getValue(key); 1144 if (mCurState == type) { 1145 didCurState = true; 1146 time += now - mStartTime; 1147 } 1148 DumpUtils.printProcStateTagAndValue(pw, type, time); 1149 } 1150 if (!didCurState && mCurState != STATE_NOTHING) { 1151 DumpUtils.printProcStateTagAndValue(pw, mCurState, now - mStartTime); 1152 } 1153 } 1154 dumpAllPssCheckin(PrintWriter pw)1155 public void dumpAllPssCheckin(PrintWriter pw) { 1156 final int N = mPssTable.getKeyCount(); 1157 for (int i=0; i<N; i++) { 1158 final int key = mPssTable.getKeyAt(i); 1159 final int type = SparseMappingTable.getIdFromKey(key); 1160 pw.print(','); 1161 DumpUtils.printProcStateTag(pw, type); 1162 pw.print(':'); 1163 pw.print(mPssTable.getValue(key, PSS_SAMPLE_COUNT)); 1164 pw.print(':'); 1165 pw.print(mPssTable.getValue(key, PSS_MINIMUM)); 1166 pw.print(':'); 1167 pw.print(mPssTable.getValue(key, PSS_AVERAGE)); 1168 pw.print(':'); 1169 pw.print(mPssTable.getValue(key, PSS_MAXIMUM)); 1170 pw.print(':'); 1171 pw.print(mPssTable.getValue(key, PSS_USS_MINIMUM)); 1172 pw.print(':'); 1173 pw.print(mPssTable.getValue(key, PSS_USS_AVERAGE)); 1174 pw.print(':'); 1175 pw.print(mPssTable.getValue(key, PSS_USS_MAXIMUM)); 1176 } 1177 } 1178 toString()1179 public String toString() { 1180 StringBuilder sb = new StringBuilder(128); 1181 sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this))) 1182 .append(" ").append(mName).append("/").append(mUid) 1183 .append(" pkg=").append(mPackage); 1184 if (mMultiPackage) sb.append(" (multi)"); 1185 if (mCommonProcess != this) sb.append(" (sub)"); 1186 sb.append("}"); 1187 return sb.toString(); 1188 } 1189 } 1190