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