ProcessStats.java revision ef0a402f5811d326e4e8d35758ab5c348297f9f4
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.app.procstats; 18 19import android.os.Debug; 20import android.os.Parcel; 21import android.os.Parcelable; 22import android.os.SystemClock; 23import android.os.SystemProperties; 24import android.os.UserHandle; 25import android.text.format.DateFormat; 26import android.util.ArrayMap; 27import android.util.ArraySet; 28import android.util.DebugUtils; 29import android.util.Log; 30import android.util.Slog; 31import android.util.SparseArray; 32import android.util.TimeUtils; 33 34import com.android.internal.app.ProcessMap; 35import com.android.internal.app.procstats.DurationsTable; 36import com.android.internal.app.procstats.ProcessState; 37import com.android.internal.app.procstats.PssTable; 38import com.android.internal.app.procstats.ServiceState; 39import com.android.internal.app.procstats.SparseMappingTable; 40import com.android.internal.app.procstats.SysMemUsageTable; 41import com.android.internal.app.procstats.DumpUtils.*; 42 43import dalvik.system.VMRuntime; 44import libcore.util.EmptyArray; 45 46import java.io.IOException; 47import java.io.InputStream; 48import java.io.PrintWriter; 49import java.util.ArrayList; 50import java.util.Arrays; 51import java.util.Collections; 52import java.util.Comparator; 53import java.util.Objects; 54 55public final class ProcessStats implements Parcelable { 56 public static final String TAG = "ProcessStats"; 57 static final boolean DEBUG = false; 58 static final boolean DEBUG_PARCEL = false; 59 60 public static final String SERVICE_NAME = "procstats"; 61 62 // How often the service commits its data, giving the minimum batching 63 // that is done. 64 public static long COMMIT_PERIOD = 3*60*60*1000; // Commit current stats every 3 hours 65 66 // Minimum uptime period before committing. If the COMMIT_PERIOD has elapsed but 67 // the total uptime has not exceeded this amount, then the commit will be held until 68 // it is reached. 69 public static long COMMIT_UPTIME_PERIOD = 60*60*1000; // Must have at least 1 hour elapsed 70 71 public static final int STATE_NOTHING = -1; 72 public static final int STATE_PERSISTENT = 0; 73 public static final int STATE_TOP = 1; 74 public static final int STATE_IMPORTANT_FOREGROUND = 2; 75 public static final int STATE_IMPORTANT_BACKGROUND = 3; 76 public static final int STATE_BACKUP = 4; 77 public static final int STATE_HEAVY_WEIGHT = 5; 78 public static final int STATE_SERVICE = 6; 79 public static final int STATE_SERVICE_RESTARTING = 7; 80 public static final int STATE_RECEIVER = 8; 81 public static final int STATE_HOME = 9; 82 public static final int STATE_LAST_ACTIVITY = 10; 83 public static final int STATE_CACHED_ACTIVITY = 11; 84 public static final int STATE_CACHED_ACTIVITY_CLIENT = 12; 85 public static final int STATE_CACHED_EMPTY = 13; 86 public static final int STATE_COUNT = STATE_CACHED_EMPTY+1; 87 88 public static final int PSS_SAMPLE_COUNT = 0; 89 public static final int PSS_MINIMUM = 1; 90 public static final int PSS_AVERAGE = 2; 91 public static final int PSS_MAXIMUM = 3; 92 public static final int PSS_USS_MINIMUM = 4; 93 public static final int PSS_USS_AVERAGE = 5; 94 public static final int PSS_USS_MAXIMUM = 6; 95 public static final int PSS_COUNT = PSS_USS_MAXIMUM+1; 96 97 public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0; 98 public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1; 99 public static final int SYS_MEM_USAGE_CACHED_AVERAGE = 2; 100 public static final int SYS_MEM_USAGE_CACHED_MAXIMUM = 3; 101 public static final int SYS_MEM_USAGE_FREE_MINIMUM = 4; 102 public static final int SYS_MEM_USAGE_FREE_AVERAGE = 5; 103 public static final int SYS_MEM_USAGE_FREE_MAXIMUM = 6; 104 public static final int SYS_MEM_USAGE_ZRAM_MINIMUM = 7; 105 public static final int SYS_MEM_USAGE_ZRAM_AVERAGE = 8; 106 public static final int SYS_MEM_USAGE_ZRAM_MAXIMUM = 9; 107 public static final int SYS_MEM_USAGE_KERNEL_MINIMUM = 10; 108 public static final int SYS_MEM_USAGE_KERNEL_AVERAGE = 11; 109 public static final int SYS_MEM_USAGE_KERNEL_MAXIMUM = 12; 110 public static final int SYS_MEM_USAGE_NATIVE_MINIMUM = 13; 111 public static final int SYS_MEM_USAGE_NATIVE_AVERAGE = 14; 112 public static final int SYS_MEM_USAGE_NATIVE_MAXIMUM = 15; 113 public static final int SYS_MEM_USAGE_COUNT = SYS_MEM_USAGE_NATIVE_MAXIMUM+1; 114 115 public static final int ADJ_NOTHING = -1; 116 public static final int ADJ_MEM_FACTOR_NORMAL = 0; 117 public static final int ADJ_MEM_FACTOR_MODERATE = 1; 118 public static final int ADJ_MEM_FACTOR_LOW = 2; 119 public static final int ADJ_MEM_FACTOR_CRITICAL = 3; 120 public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1; 121 public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT; 122 public static final int ADJ_SCREEN_OFF = 0; 123 public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD; 124 public static final int ADJ_COUNT = ADJ_SCREEN_ON*2; 125 126 public static final int FLAG_COMPLETE = 1<<0; 127 public static final int FLAG_SHUTDOWN = 1<<1; 128 public static final int FLAG_SYSPROPS = 1<<2; 129 130 public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL, 131 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL }; 132 133 public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON }; 134 135 public static final int[] NON_CACHED_PROC_STATES = new int[] { 136 STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND, 137 STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT, 138 STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER 139 }; 140 141 public static final int[] BACKGROUND_PROC_STATES = new int[] { 142 STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, 143 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER 144 }; 145 146 public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT, 147 STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, 148 STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER, 149 STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY, 150 STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY 151 }; 152 153 // Current version of the parcel format. 154 private static final int PARCEL_VERSION = 20; 155 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 156 private static final int MAGIC = 0x50535454; 157 158 public String mReadError; 159 public String mTimePeriodStartClockStr; 160 public int mFlags; 161 162 public final ProcessMap<SparseArray<PackageState>> mPackages 163 = new ProcessMap<SparseArray<PackageState>>(); 164 public final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>(); 165 166 public final long[] mMemFactorDurations = new long[ADJ_COUNT]; 167 public int mMemFactor = STATE_NOTHING; 168 public long mStartTime; 169 170 public long mTimePeriodStartClock; 171 public long mTimePeriodStartRealtime; 172 public long mTimePeriodEndRealtime; 173 public long mTimePeriodStartUptime; 174 public long mTimePeriodEndUptime; 175 String mRuntime; 176 boolean mRunning; 177 178 boolean mHasSwappedOutPss; 179 180 public final SparseMappingTable mTableData = new SparseMappingTable(); 181 182 public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT]; 183 public final SysMemUsageTable mSysMemUsage = new SysMemUsageTable(mTableData); 184 185 // For writing parcels. 186 ArrayMap<String, Integer> mCommonStringToIndex; 187 188 // For reading parcels. 189 ArrayList<String> mIndexToCommonString; 190 191 public ProcessStats(boolean running) { 192 mRunning = running; 193 reset(); 194 if (running) { 195 // If we are actively running, we need to determine whether the system is 196 // collecting swap pss data. 197 Debug.MemoryInfo info = new Debug.MemoryInfo(); 198 Debug.getMemoryInfo(android.os.Process.myPid(), info); 199 mHasSwappedOutPss = info.hasSwappedOutPss(); 200 } 201 } 202 203 public ProcessStats(Parcel in) { 204 reset(); 205 readFromParcel(in); 206 } 207 208 public void add(ProcessStats other) { 209 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = other.mPackages.getMap(); 210 for (int ip=0; ip<pkgMap.size(); ip++) { 211 final String pkgName = pkgMap.keyAt(ip); 212 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 213 for (int iu=0; iu<uids.size(); iu++) { 214 final int uid = uids.keyAt(iu); 215 final SparseArray<PackageState> versions = uids.valueAt(iu); 216 for (int iv=0; iv<versions.size(); iv++) { 217 final int vers = versions.keyAt(iv); 218 final PackageState otherState = versions.valueAt(iv); 219 final int NPROCS = otherState.mProcesses.size(); 220 final int NSRVS = otherState.mServices.size(); 221 for (int iproc=0; iproc<NPROCS; iproc++) { 222 ProcessState otherProc = otherState.mProcesses.valueAt(iproc); 223 if (otherProc.getCommonProcess() != otherProc) { 224 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid 225 + " vers " + vers + " proc " + otherProc.getName()); 226 ProcessState thisProc = getProcessStateLocked(pkgName, uid, vers, 227 otherProc.getName()); 228 if (thisProc.getCommonProcess() == thisProc) { 229 if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting"); 230 thisProc.setMultiPackage(true); 231 long now = SystemClock.uptimeMillis(); 232 final PackageState pkgState = getPackageStateLocked(pkgName, uid, 233 vers); 234 thisProc = thisProc.clone(now); 235 pkgState.mProcesses.put(thisProc.getName(), thisProc); 236 } 237 thisProc.add(otherProc); 238 } 239 } 240 for (int isvc=0; isvc<NSRVS; isvc++) { 241 ServiceState otherSvc = otherState.mServices.valueAt(isvc); 242 if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid 243 + " service " + otherSvc.getName()); 244 ServiceState thisSvc = getServiceStateLocked(pkgName, uid, vers, 245 otherSvc.getProcessName(), otherSvc.getName()); 246 thisSvc.add(otherSvc); 247 } 248 } 249 } 250 } 251 252 ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap(); 253 for (int ip=0; ip<procMap.size(); ip++) { 254 SparseArray<ProcessState> uids = procMap.valueAt(ip); 255 for (int iu=0; iu<uids.size(); iu++) { 256 int uid = uids.keyAt(iu); 257 ProcessState otherProc = uids.valueAt(iu); 258 final String name = otherProc.getName(); 259 final String pkg = otherProc.getPackage(); 260 final int vers = otherProc.getVersion(); 261 ProcessState thisProc = mProcesses.get(name, uid); 262 if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + name); 263 if (thisProc == null) { 264 if (DEBUG) Slog.d(TAG, "Creating new process!"); 265 thisProc = new ProcessState(this, pkg, uid, vers, name); 266 mProcesses.put(name, uid, thisProc); 267 PackageState thisState = getPackageStateLocked(pkg, uid, vers); 268 if (!thisState.mProcesses.containsKey(name)) { 269 thisState.mProcesses.put(name, thisProc); 270 } 271 } 272 thisProc.add(otherProc); 273 } 274 } 275 276 for (int i=0; i<ADJ_COUNT; i++) { 277 if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by " 278 + other.mMemFactorDurations[i] + " from " 279 + mMemFactorDurations[i]); 280 mMemFactorDurations[i] += other.mMemFactorDurations[i]; 281 } 282 283 mSysMemUsage.mergeStats(other.mSysMemUsage); 284 285 if (other.mTimePeriodStartClock < mTimePeriodStartClock) { 286 mTimePeriodStartClock = other.mTimePeriodStartClock; 287 mTimePeriodStartClockStr = other.mTimePeriodStartClockStr; 288 } 289 mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime; 290 mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime; 291 292 mHasSwappedOutPss |= other.mHasSwappedOutPss; 293 } 294 295 public void addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem, 296 long nativeMem) { 297 if (mMemFactor != STATE_NOTHING) { 298 int state = mMemFactor * STATE_COUNT; 299 mSysMemUsageArgs[SYS_MEM_USAGE_SAMPLE_COUNT] = 1; 300 for (int i=0; i<3; i++) { 301 mSysMemUsageArgs[SYS_MEM_USAGE_CACHED_MINIMUM + i] = cachedMem; 302 mSysMemUsageArgs[SYS_MEM_USAGE_FREE_MINIMUM + i] = freeMem; 303 mSysMemUsageArgs[SYS_MEM_USAGE_ZRAM_MINIMUM + i] = zramMem; 304 mSysMemUsageArgs[SYS_MEM_USAGE_KERNEL_MINIMUM + i] = kernelMem; 305 mSysMemUsageArgs[SYS_MEM_USAGE_NATIVE_MINIMUM + i] = nativeMem; 306 } 307 mSysMemUsage.mergeStats(state, mSysMemUsageArgs, 0); 308 } 309 } 310 311 public static final Parcelable.Creator<ProcessStats> CREATOR 312 = new Parcelable.Creator<ProcessStats>() { 313 public ProcessStats createFromParcel(Parcel in) { 314 return new ProcessStats(in); 315 } 316 317 public ProcessStats[] newArray(int size) { 318 return new ProcessStats[size]; 319 } 320 }; 321 322 public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) { 323 data.totalTime = 0; 324 for (int i=0; i<STATE_COUNT; i++) { 325 data.processStateWeight[i] = 0; 326 data.processStatePss[i] = 0; 327 data.processStateTime[i] = 0; 328 data.processStateSamples[i] = 0; 329 } 330 for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) { 331 data.sysMemUsage[i] = 0; 332 } 333 data.sysMemCachedWeight = 0; 334 data.sysMemFreeWeight = 0; 335 data.sysMemZRamWeight = 0; 336 data.sysMemKernelWeight = 0; 337 data.sysMemNativeWeight = 0; 338 data.sysMemSamples = 0; 339 final long[] totalMemUsage = mSysMemUsage.getTotalMemUsage(); 340 for (int is=0; is<data.screenStates.length; is++) { 341 for (int im=0; im<data.memStates.length; im++) { 342 int memBucket = data.screenStates[is] + data.memStates[im]; 343 int stateBucket = memBucket * STATE_COUNT; 344 long memTime = mMemFactorDurations[memBucket]; 345 if (mMemFactor == memBucket) { 346 memTime += now - mStartTime; 347 } 348 data.totalTime += memTime; 349 final int sysKey = mSysMemUsage.getKey((byte)stateBucket); 350 long[] longs = totalMemUsage; 351 int idx = 0; 352 if (sysKey != SparseMappingTable.INVALID_KEY) { 353 final long[] tmpLongs = mSysMemUsage.getArrayForKey(sysKey); 354 final int tmpIndex = SparseMappingTable.getIndexFromKey(sysKey); 355 if (tmpLongs[tmpIndex+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) { 356 SysMemUsageTable.mergeSysMemUsage(data.sysMemUsage, 0, longs, idx); 357 longs = tmpLongs; 358 idx = tmpIndex; 359 } 360 } 361 data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE] 362 * (double)memTime; 363 data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE] 364 * (double)memTime; 365 data.sysMemZRamWeight += longs[idx + SYS_MEM_USAGE_ZRAM_AVERAGE] 366 * (double) memTime; 367 data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE] 368 * (double)memTime; 369 data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE] 370 * (double)memTime; 371 data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT]; 372 } 373 } 374 data.hasSwappedOutPss = mHasSwappedOutPss; 375 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 376 for (int iproc=0; iproc<procMap.size(); iproc++) { 377 SparseArray<ProcessState> uids = procMap.valueAt(iproc); 378 for (int iu=0; iu<uids.size(); iu++) { 379 final ProcessState proc = uids.valueAt(iu); 380 proc.aggregatePss(data, now); 381 } 382 } 383 } 384 385 public void reset() { 386 if (DEBUG) Slog.d(TAG, "Resetting state of " + mTimePeriodStartClockStr); 387 resetCommon(); 388 mPackages.getMap().clear(); 389 mProcesses.getMap().clear(); 390 mMemFactor = STATE_NOTHING; 391 mStartTime = 0; 392 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr); 393 } 394 395 public void resetSafely() { 396 if (DEBUG) Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr); 397 resetCommon(); 398 399 // First initialize use count of all common processes. 400 final long now = SystemClock.uptimeMillis(); 401 final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 402 for (int ip=procMap.size()-1; ip>=0; ip--) { 403 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 404 for (int iu=uids.size()-1; iu>=0; iu--) { 405 uids.valueAt(iu).tmpNumInUse = 0; 406 } 407 } 408 409 // Next reset or prune all per-package processes, and for the ones that are reset 410 // track this back to the common processes. 411 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 412 for (int ip=pkgMap.size()-1; ip>=0; ip--) { 413 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 414 for (int iu=uids.size()-1; iu>=0; iu--) { 415 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 416 for (int iv=vpkgs.size()-1; iv>=0; iv--) { 417 final PackageState pkgState = vpkgs.valueAt(iv); 418 for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) { 419 final ProcessState ps = pkgState.mProcesses.valueAt(iproc); 420 if (ps.isInUse()) { 421 ps.resetSafely(now); 422 ps.getCommonProcess().tmpNumInUse++; 423 ps.getCommonProcess().tmpFoundSubProc = ps; 424 } else { 425 pkgState.mProcesses.valueAt(iproc).makeDead(); 426 pkgState.mProcesses.removeAt(iproc); 427 } 428 } 429 for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) { 430 final ServiceState ss = pkgState.mServices.valueAt(isvc); 431 if (ss.isInUse()) { 432 ss.resetSafely(now); 433 } else { 434 pkgState.mServices.removeAt(isvc); 435 } 436 } 437 if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) { 438 vpkgs.removeAt(iv); 439 } 440 } 441 if (vpkgs.size() <= 0) { 442 uids.removeAt(iu); 443 } 444 } 445 if (uids.size() <= 0) { 446 pkgMap.removeAt(ip); 447 } 448 } 449 450 // Finally prune out any common processes that are no longer in use. 451 for (int ip=procMap.size()-1; ip>=0; ip--) { 452 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 453 for (int iu=uids.size()-1; iu>=0; iu--) { 454 ProcessState ps = uids.valueAt(iu); 455 if (ps.isInUse() || ps.tmpNumInUse > 0) { 456 // If this is a process for multiple packages, we could at this point 457 // be back down to one package. In that case, we want to revert back 458 // to a single shared ProcessState. We can do this by converting the 459 // current package-specific ProcessState up to the shared ProcessState, 460 // throwing away the current one we have here (because nobody else is 461 // using it). 462 if (!ps.isActive() && ps.isMultiPackage() && ps.tmpNumInUse == 1) { 463 // Here we go... 464 ps = ps.tmpFoundSubProc; 465 ps.makeStandalone(); 466 uids.setValueAt(iu, ps); 467 } else { 468 ps.resetSafely(now); 469 } 470 } else { 471 ps.makeDead(); 472 uids.removeAt(iu); 473 } 474 } 475 if (uids.size() <= 0) { 476 procMap.removeAt(ip); 477 } 478 } 479 480 mStartTime = now; 481 if (DEBUG) Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr); 482 } 483 484 private void resetCommon() { 485 mTimePeriodStartClock = System.currentTimeMillis(); 486 buildTimePeriodStartClockStr(); 487 mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); 488 mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis(); 489 mTableData.reset(); 490 Arrays.fill(mMemFactorDurations, 0); 491 mSysMemUsage.resetTable(); 492 mStartTime = 0; 493 mReadError = null; 494 mFlags = 0; 495 evaluateSystemProperties(true); 496 } 497 498 public boolean evaluateSystemProperties(boolean update) { 499 boolean changed = false; 500 String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.2", 501 VMRuntime.getRuntime().vmLibrary()); 502 if (!Objects.equals(runtime, mRuntime)) { 503 changed = true; 504 if (update) { 505 mRuntime = runtime; 506 } 507 } 508 return changed; 509 } 510 511 private void buildTimePeriodStartClockStr() { 512 mTimePeriodStartClockStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss", 513 mTimePeriodStartClock).toString(); 514 } 515 516 static final int[] BAD_TABLE = new int[0]; 517 518 private void writeCompactedLongArray(Parcel out, long[] array, int num) { 519 for (int i=0; i<num; i++) { 520 long val = array[i]; 521 if (val < 0) { 522 Slog.w(TAG, "Time val negative: " + val); 523 val = 0; 524 } 525 if (val <= Integer.MAX_VALUE) { 526 out.writeInt((int)val); 527 } else { 528 int top = ~((int)((val>>32)&0x7fffffff)); 529 int bottom = (int)(val&0x0ffffffffL); 530 out.writeInt(top); 531 out.writeInt(bottom); 532 } 533 } 534 } 535 536 private void readCompactedLongArray(Parcel in, int version, long[] array, int num) { 537 if (version <= 10) { 538 in.readLongArray(array); 539 return; 540 } 541 final int alen = array.length; 542 if (num > alen) { 543 throw new RuntimeException("bad array lengths: got " + num + " array is " + alen); 544 } 545 int i; 546 for (i=0; i<num; i++) { 547 int val = in.readInt(); 548 if (val >= 0) { 549 array[i] = val; 550 } else { 551 int bottom = in.readInt(); 552 array[i] = (((long)~val)<<32) | bottom; 553 } 554 } 555 while (i < alen) { 556 array[i] = 0; 557 i++; 558 } 559 } 560 561 private void writeCommonString(Parcel out, String name) { 562 Integer index = mCommonStringToIndex.get(name); 563 if (index != null) { 564 out.writeInt(index); 565 return; 566 } 567 index = mCommonStringToIndex.size(); 568 mCommonStringToIndex.put(name, index); 569 out.writeInt(~index); 570 out.writeString(name); 571 } 572 573 private String readCommonString(Parcel in, int version) { 574 if (version <= 9) { 575 return in.readString(); 576 } 577 int index = in.readInt(); 578 if (index >= 0) { 579 return mIndexToCommonString.get(index); 580 } 581 index = ~index; 582 String name = in.readString(); 583 while (mIndexToCommonString.size() <= index) { 584 mIndexToCommonString.add(null); 585 } 586 mIndexToCommonString.set(index, name); 587 return name; 588 } 589 590 @Override 591 public int describeContents() { 592 return 0; 593 } 594 595 @Override 596 public void writeToParcel(Parcel out, int flags) { 597 writeToParcel(out, SystemClock.uptimeMillis(), flags); 598 } 599 600 /** @hide */ 601 public void writeToParcel(Parcel out, long now, int flags) { 602 out.writeInt(MAGIC); 603 out.writeInt(PARCEL_VERSION); 604 out.writeInt(STATE_COUNT); 605 out.writeInt(ADJ_COUNT); 606 out.writeInt(PSS_COUNT); 607 out.writeInt(SYS_MEM_USAGE_COUNT); 608 out.writeInt(SparseMappingTable.ARRAY_SIZE); 609 610 mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.size()); 611 612 // First commit all running times. 613 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 614 final int NPROC = procMap.size(); 615 for (int ip=0; ip<NPROC; ip++) { 616 SparseArray<ProcessState> uids = procMap.valueAt(ip); 617 final int NUID = uids.size(); 618 for (int iu=0; iu<NUID; iu++) { 619 uids.valueAt(iu).commitStateTime(now); 620 } 621 } 622 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 623 final int NPKG = pkgMap.size(); 624 for (int ip=0; ip<NPKG; ip++) { 625 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 626 final int NUID = uids.size(); 627 for (int iu=0; iu<NUID; iu++) { 628 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 629 final int NVERS = vpkgs.size(); 630 for (int iv=0; iv<NVERS; iv++) { 631 PackageState pkgState = vpkgs.valueAt(iv); 632 final int NPROCS = pkgState.mProcesses.size(); 633 for (int iproc=0; iproc<NPROCS; iproc++) { 634 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 635 if (proc.getCommonProcess() != proc) { 636 proc.commitStateTime(now); 637 } 638 } 639 final int NSRVS = pkgState.mServices.size(); 640 for (int isvc=0; isvc<NSRVS; isvc++) { 641 pkgState.mServices.valueAt(isvc).commitStateTime(now); 642 } 643 } 644 } 645 } 646 647 out.writeLong(mTimePeriodStartClock); 648 out.writeLong(mTimePeriodStartRealtime); 649 out.writeLong(mTimePeriodEndRealtime); 650 out.writeLong(mTimePeriodStartUptime); 651 out.writeLong(mTimePeriodEndUptime); 652 out.writeString(mRuntime); 653 out.writeInt(mHasSwappedOutPss ? 1 : 0); 654 out.writeInt(mFlags); 655 656 mTableData.writeToParcel(out); 657 658 if (mMemFactor != STATE_NOTHING) { 659 mMemFactorDurations[mMemFactor] += now - mStartTime; 660 mStartTime = now; 661 } 662 writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length); 663 664 mSysMemUsage.writeToParcel(out); 665 666 out.writeInt(NPROC); 667 for (int ip=0; ip<NPROC; ip++) { 668 writeCommonString(out, procMap.keyAt(ip)); 669 final SparseArray<ProcessState> uids = procMap.valueAt(ip); 670 final int NUID = uids.size(); 671 out.writeInt(NUID); 672 for (int iu=0; iu<NUID; iu++) { 673 out.writeInt(uids.keyAt(iu)); 674 final ProcessState proc = uids.valueAt(iu); 675 writeCommonString(out, proc.getPackage()); 676 out.writeInt(proc.getVersion()); 677 proc.writeToParcel(out, now); 678 } 679 } 680 out.writeInt(NPKG); 681 for (int ip=0; ip<NPKG; ip++) { 682 writeCommonString(out, pkgMap.keyAt(ip)); 683 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 684 final int NUID = uids.size(); 685 out.writeInt(NUID); 686 for (int iu=0; iu<NUID; iu++) { 687 out.writeInt(uids.keyAt(iu)); 688 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 689 final int NVERS = vpkgs.size(); 690 out.writeInt(NVERS); 691 for (int iv=0; iv<NVERS; iv++) { 692 out.writeInt(vpkgs.keyAt(iv)); 693 final PackageState pkgState = vpkgs.valueAt(iv); 694 final int NPROCS = pkgState.mProcesses.size(); 695 out.writeInt(NPROCS); 696 for (int iproc=0; iproc<NPROCS; iproc++) { 697 writeCommonString(out, pkgState.mProcesses.keyAt(iproc)); 698 final ProcessState proc = pkgState.mProcesses.valueAt(iproc); 699 if (proc.getCommonProcess() == proc) { 700 // This is the same as the common process we wrote above. 701 out.writeInt(0); 702 } else { 703 // There is separate data for this package's process. 704 out.writeInt(1); 705 proc.writeToParcel(out, now); 706 } 707 } 708 final int NSRVS = pkgState.mServices.size(); 709 out.writeInt(NSRVS); 710 for (int isvc=0; isvc<NSRVS; isvc++) { 711 out.writeString(pkgState.mServices.keyAt(isvc)); 712 final ServiceState svc = pkgState.mServices.valueAt(isvc); 713 writeCommonString(out, svc.getProcessName()); 714 svc.writeToParcel(out, now); 715 } 716 } 717 } 718 } 719 720 mCommonStringToIndex = null; 721 } 722 723 private boolean readCheckedInt(Parcel in, int val, String what) { 724 int got; 725 if ((got=in.readInt()) != val) { 726 mReadError = "bad " + what + ": " + got; 727 return false; 728 } 729 return true; 730 } 731 732 static byte[] readFully(InputStream stream, int[] outLen) throws IOException { 733 int pos = 0; 734 final int initialAvail = stream.available(); 735 byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384]; 736 while (true) { 737 int amt = stream.read(data, pos, data.length-pos); 738 if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos 739 + " of avail " + data.length); 740 if (amt < 0) { 741 if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos 742 + " len=" + data.length); 743 outLen[0] = pos; 744 return data; 745 } 746 pos += amt; 747 if (pos >= data.length) { 748 byte[] newData = new byte[pos+16384]; 749 if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len " 750 + newData.length); 751 System.arraycopy(data, 0, newData, 0, pos); 752 data = newData; 753 } 754 } 755 } 756 757 public void read(InputStream stream) { 758 try { 759 int[] len = new int[1]; 760 byte[] raw = readFully(stream, len); 761 Parcel in = Parcel.obtain(); 762 in.unmarshall(raw, 0, len[0]); 763 in.setDataPosition(0); 764 stream.close(); 765 766 readFromParcel(in); 767 } catch (IOException e) { 768 mReadError = "caught exception: " + e; 769 } 770 } 771 772 public void readFromParcel(Parcel in) { 773 final boolean hadData = mPackages.getMap().size() > 0 774 || mProcesses.getMap().size() > 0; 775 if (hadData) { 776 resetSafely(); 777 } 778 779 if (!readCheckedInt(in, MAGIC, "magic number")) { 780 return; 781 } 782 int version = in.readInt(); 783 if (version != PARCEL_VERSION) { 784 mReadError = "bad version: " + version; 785 return; 786 } 787 if (!readCheckedInt(in, STATE_COUNT, "state count")) { 788 return; 789 } 790 if (!readCheckedInt(in, ADJ_COUNT, "adj count")) { 791 return; 792 } 793 if (!readCheckedInt(in, PSS_COUNT, "pss count")) { 794 return; 795 } 796 if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) { 797 return; 798 } 799 if (!readCheckedInt(in, SparseMappingTable.ARRAY_SIZE, "longs size")) { 800 return; 801 } 802 803 mIndexToCommonString = new ArrayList<String>(); 804 805 mTimePeriodStartClock = in.readLong(); 806 buildTimePeriodStartClockStr(); 807 mTimePeriodStartRealtime = in.readLong(); 808 mTimePeriodEndRealtime = in.readLong(); 809 mTimePeriodStartUptime = in.readLong(); 810 mTimePeriodEndUptime = in.readLong(); 811 mRuntime = in.readString(); 812 mHasSwappedOutPss = in.readInt() != 0; 813 mFlags = in.readInt(); 814 mTableData.readFromParcel(in); 815 readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length); 816 if (!mSysMemUsage.readFromParcel(in)) { 817 return; 818 } 819 820 int NPROC = in.readInt(); 821 if (NPROC < 0) { 822 mReadError = "bad process count: " + NPROC; 823 return; 824 } 825 while (NPROC > 0) { 826 NPROC--; 827 final String procName = readCommonString(in, version); 828 if (procName == null) { 829 mReadError = "bad process name"; 830 return; 831 } 832 int NUID = in.readInt(); 833 if (NUID < 0) { 834 mReadError = "bad uid count: " + NUID; 835 return; 836 } 837 while (NUID > 0) { 838 NUID--; 839 final int uid = in.readInt(); 840 if (uid < 0) { 841 mReadError = "bad uid: " + uid; 842 return; 843 } 844 final String pkgName = readCommonString(in, version); 845 if (pkgName == null) { 846 mReadError = "bad process package name"; 847 return; 848 } 849 final int vers = in.readInt(); 850 ProcessState proc = hadData ? mProcesses.get(procName, uid) : null; 851 if (proc != null) { 852 if (!proc.readFromParcel(in, false)) { 853 return; 854 } 855 } else { 856 proc = new ProcessState(this, pkgName, uid, vers, procName); 857 if (!proc.readFromParcel(in, true)) { 858 return; 859 } 860 } 861 if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid 862 + " " + proc); 863 mProcesses.put(procName, uid, proc); 864 } 865 } 866 867 if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes"); 868 869 int NPKG = in.readInt(); 870 if (NPKG < 0) { 871 mReadError = "bad package count: " + NPKG; 872 return; 873 } 874 while (NPKG > 0) { 875 NPKG--; 876 final String pkgName = readCommonString(in, version); 877 if (pkgName == null) { 878 mReadError = "bad package name"; 879 return; 880 } 881 int NUID = in.readInt(); 882 if (NUID < 0) { 883 mReadError = "bad uid count: " + NUID; 884 return; 885 } 886 while (NUID > 0) { 887 NUID--; 888 final int uid = in.readInt(); 889 if (uid < 0) { 890 mReadError = "bad uid: " + uid; 891 return; 892 } 893 int NVERS = in.readInt(); 894 if (NVERS < 0) { 895 mReadError = "bad versions count: " + NVERS; 896 return; 897 } 898 while (NVERS > 0) { 899 NVERS--; 900 final int vers = in.readInt(); 901 PackageState pkgState = new PackageState(pkgName, uid); 902 SparseArray<PackageState> vpkg = mPackages.get(pkgName, uid); 903 if (vpkg == null) { 904 vpkg = new SparseArray<PackageState>(); 905 mPackages.put(pkgName, uid, vpkg); 906 } 907 vpkg.put(vers, pkgState); 908 int NPROCS = in.readInt(); 909 if (NPROCS < 0) { 910 mReadError = "bad package process count: " + NPROCS; 911 return; 912 } 913 while (NPROCS > 0) { 914 NPROCS--; 915 String procName = readCommonString(in, version); 916 if (procName == null) { 917 mReadError = "bad package process name"; 918 return; 919 } 920 int hasProc = in.readInt(); 921 if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid 922 + " process " + procName + " hasProc=" + hasProc); 923 ProcessState commonProc = mProcesses.get(procName, uid); 924 if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid 925 + ": " + commonProc); 926 if (commonProc == null) { 927 mReadError = "no common proc: " + procName; 928 return; 929 } 930 if (hasProc != 0) { 931 // The process for this package is unique to the package; we 932 // need to load it. We don't need to do anything about it if 933 // it is not unique because if someone later looks for it 934 // they will find and use it from the global procs. 935 ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null; 936 if (proc != null) { 937 if (!proc.readFromParcel(in, false)) { 938 return; 939 } 940 } else { 941 proc = new ProcessState(commonProc, pkgName, uid, vers, procName, 942 0); 943 if (!proc.readFromParcel(in, true)) { 944 return; 945 } 946 } 947 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: " 948 + procName + " " + uid + " " + proc); 949 pkgState.mProcesses.put(procName, proc); 950 } else { 951 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: " 952 + procName + " " + uid + " " + commonProc); 953 pkgState.mProcesses.put(procName, commonProc); 954 } 955 } 956 int NSRVS = in.readInt(); 957 if (NSRVS < 0) { 958 mReadError = "bad package service count: " + NSRVS; 959 return; 960 } 961 while (NSRVS > 0) { 962 NSRVS--; 963 String serviceName = in.readString(); 964 if (serviceName == null) { 965 mReadError = "bad package service name"; 966 return; 967 } 968 String processName = version > 9 ? readCommonString(in, version) : null; 969 ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null; 970 if (serv == null) { 971 serv = new ServiceState(this, pkgName, serviceName, processName, null); 972 } 973 if (!serv.readFromParcel(in)) { 974 return; 975 } 976 if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: " 977 + serviceName + " " + uid + " " + serv); 978 pkgState.mServices.put(serviceName, serv); 979 } 980 } 981 } 982 } 983 984 mIndexToCommonString = null; 985 986 if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!"); 987 } 988 989 public PackageState getPackageStateLocked(String packageName, int uid, int vers) { 990 SparseArray<PackageState> vpkg = mPackages.get(packageName, uid); 991 if (vpkg == null) { 992 vpkg = new SparseArray<PackageState>(); 993 mPackages.put(packageName, uid, vpkg); 994 } 995 PackageState as = vpkg.get(vers); 996 if (as != null) { 997 return as; 998 } 999 as = new PackageState(packageName, uid); 1000 vpkg.put(vers, as); 1001 return as; 1002 } 1003 1004 public ProcessState getProcessStateLocked(String packageName, int uid, int vers, 1005 String processName) { 1006 final PackageState pkgState = getPackageStateLocked(packageName, uid, vers); 1007 ProcessState ps = pkgState.mProcesses.get(processName); 1008 if (ps != null) { 1009 return ps; 1010 } 1011 ProcessState commonProc = mProcesses.get(processName, uid); 1012 if (commonProc == null) { 1013 commonProc = new ProcessState(this, packageName, uid, vers, processName); 1014 mProcesses.put(processName, uid, commonProc); 1015 if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc); 1016 } 1017 if (!commonProc.isMultiPackage()) { 1018 if (packageName.equals(commonProc.getPackage()) && vers == commonProc.getVersion()) { 1019 // This common process is not in use by multiple packages, and 1020 // is for the calling package, so we can just use it directly. 1021 ps = commonProc; 1022 if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc); 1023 } else { 1024 if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!"); 1025 // This common process has not been in use by multiple packages, 1026 // but it was created for a different package than the caller. 1027 // We need to convert it to a multi-package process. 1028 commonProc.setMultiPackage(true); 1029 // To do this, we need to make two new process states, one a copy 1030 // of the current state for the process under the original package 1031 // name, and the second a free new process state for it as the 1032 // new package name. 1033 long now = SystemClock.uptimeMillis(); 1034 // First let's make a copy of the current process state and put 1035 // that under the now unique state for its original package name. 1036 final PackageState commonPkgState = getPackageStateLocked(commonProc.getPackage(), 1037 uid, commonProc.getVersion()); 1038 if (commonPkgState != null) { 1039 ProcessState cloned = commonProc.clone(now); 1040 if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.getPackage() 1041 + ": " + cloned); 1042 commonPkgState.mProcesses.put(commonProc.getName(), cloned); 1043 // If this has active services, we need to update their process pointer 1044 // to point to the new package-specific process state. 1045 for (int i=commonPkgState.mServices.size()-1; i>=0; i--) { 1046 ServiceState ss = commonPkgState.mServices.valueAt(i); 1047 if (ss.getProcess() == commonProc) { 1048 if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: " + ss); 1049 ss.setProcess(cloned); 1050 } else if (DEBUG) { 1051 Slog.d(TAG, "GETPROC leaving proc of " + ss); 1052 } 1053 } 1054 } else { 1055 Slog.w(TAG, "Cloning proc state: no package state " + commonProc.getPackage() 1056 + "/" + uid + " for proc " + commonProc.getName()); 1057 } 1058 // And now make a fresh new process state for the new package name. 1059 ps = new ProcessState(commonProc, packageName, uid, vers, processName, now); 1060 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps); 1061 } 1062 } else { 1063 // The common process is for multiple packages, we need to create a 1064 // separate object for the per-package data. 1065 ps = new ProcessState(commonProc, packageName, uid, vers, processName, 1066 SystemClock.uptimeMillis()); 1067 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps); 1068 } 1069 pkgState.mProcesses.put(processName, ps); 1070 if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps); 1071 return ps; 1072 } 1073 1074 public ServiceState getServiceStateLocked(String packageName, int uid, int vers, 1075 String processName, String className) { 1076 final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid, vers); 1077 ServiceState ss = as.mServices.get(className); 1078 if (ss != null) { 1079 if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss); 1080 return ss; 1081 } 1082 final ProcessState ps = processName != null 1083 ? getProcessStateLocked(packageName, uid, vers, processName) : null; 1084 ss = new ServiceState(this, packageName, className, processName, ps); 1085 as.mServices.put(className, ss); 1086 if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps); 1087 return ss; 1088 } 1089 1090 public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, 1091 boolean dumpAll, boolean activeOnly) { 1092 long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, 1093 mStartTime, now); 1094 boolean sepNeeded = false; 1095 if (mSysMemUsage.getKeyCount() > 0) { 1096 pw.println("System memory usage:"); 1097 mSysMemUsage.dump(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ); 1098 sepNeeded = true; 1099 } 1100 ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1101 boolean printedHeader = false; 1102 for (int ip=0; ip<pkgMap.size(); ip++) { 1103 final String pkgName = pkgMap.keyAt(ip); 1104 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1105 for (int iu=0; iu<uids.size(); iu++) { 1106 final int uid = uids.keyAt(iu); 1107 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1108 for (int iv=0; iv<vpkgs.size(); iv++) { 1109 final int vers = vpkgs.keyAt(iv); 1110 final PackageState pkgState = vpkgs.valueAt(iv); 1111 final int NPROCS = pkgState.mProcesses.size(); 1112 final int NSRVS = pkgState.mServices.size(); 1113 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); 1114 if (!pkgMatch) { 1115 boolean procMatch = false; 1116 for (int iproc=0; iproc<NPROCS; iproc++) { 1117 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1118 if (reqPackage.equals(proc.getName())) { 1119 procMatch = true; 1120 break; 1121 } 1122 } 1123 if (!procMatch) { 1124 continue; 1125 } 1126 } 1127 if (NPROCS > 0 || NSRVS > 0) { 1128 if (!printedHeader) { 1129 if (sepNeeded) pw.println(); 1130 pw.println("Per-Package Stats:"); 1131 printedHeader = true; 1132 sepNeeded = true; 1133 } 1134 pw.print(" * "); pw.print(pkgName); pw.print(" / "); 1135 UserHandle.formatUid(pw, uid); pw.print(" / v"); 1136 pw.print(vers); pw.println(":"); 1137 } 1138 if (!dumpSummary || dumpAll) { 1139 for (int iproc=0; iproc<NPROCS; iproc++) { 1140 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1141 if (!pkgMatch && !reqPackage.equals(proc.getName())) { 1142 continue; 1143 } 1144 if (activeOnly && !proc.isInUse()) { 1145 pw.print(" (Not active: "); 1146 pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")"); 1147 continue; 1148 } 1149 pw.print(" Process "); 1150 pw.print(pkgState.mProcesses.keyAt(iproc)); 1151 if (proc.getCommonProcess().isMultiPackage()) { 1152 pw.print(" (multi, "); 1153 } else { 1154 pw.print(" (unique, "); 1155 } 1156 pw.print(proc.getDurationsBucketCount()); 1157 pw.print(" entries)"); 1158 pw.println(":"); 1159 proc.dumpProcessState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, 1160 ALL_PROC_STATES, now); 1161 proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, 1162 ALL_PROC_STATES); 1163 proc.dumpInternalLocked(pw, " ", dumpAll); 1164 } 1165 } else { 1166 ArrayList<ProcessState> procs = new ArrayList<ProcessState>(); 1167 for (int iproc=0; iproc<NPROCS; iproc++) { 1168 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1169 if (!pkgMatch && !reqPackage.equals(proc.getName())) { 1170 continue; 1171 } 1172 if (activeOnly && !proc.isInUse()) { 1173 continue; 1174 } 1175 procs.add(proc); 1176 } 1177 DumpUtils.dumpProcessSummaryLocked(pw, " ", procs, 1178 ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES, 1179 now, totalTime); 1180 } 1181 for (int isvc=0; isvc<NSRVS; isvc++) { 1182 ServiceState svc = pkgState.mServices.valueAt(isvc); 1183 if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) { 1184 continue; 1185 } 1186 if (activeOnly && !svc.isInUse()) { 1187 pw.print(" (Not active: "); 1188 pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")"); 1189 continue; 1190 } 1191 if (dumpAll) { 1192 pw.print(" Service "); 1193 } else { 1194 pw.print(" * "); 1195 } 1196 pw.print(pkgState.mServices.keyAt(isvc)); 1197 pw.println(":"); 1198 pw.print(" Process: "); pw.println(svc.getProcessName()); 1199 svc.dumpStats(pw, " ", " ", " ", 1200 now, totalTime, dumpSummary, dumpAll); 1201 } 1202 } 1203 } 1204 } 1205 1206 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 1207 printedHeader = false; 1208 int numShownProcs = 0, numTotalProcs = 0; 1209 for (int ip=0; ip<procMap.size(); ip++) { 1210 String procName = procMap.keyAt(ip); 1211 SparseArray<ProcessState> uids = procMap.valueAt(ip); 1212 for (int iu=0; iu<uids.size(); iu++) { 1213 int uid = uids.keyAt(iu); 1214 numTotalProcs++; 1215 final ProcessState proc = uids.valueAt(iu); 1216 if (proc.hasAnyData()) { 1217 continue; 1218 } 1219 if (!proc.isMultiPackage()) { 1220 continue; 1221 } 1222 if (reqPackage != null && !reqPackage.equals(procName) 1223 && !reqPackage.equals(proc.getPackage())) { 1224 continue; 1225 } 1226 numShownProcs++; 1227 if (sepNeeded) { 1228 pw.println(); 1229 } 1230 sepNeeded = true; 1231 if (!printedHeader) { 1232 pw.println("Multi-Package Common Processes:"); 1233 printedHeader = true; 1234 } 1235 if (activeOnly && !proc.isInUse()) { 1236 pw.print(" (Not active: "); pw.print(procName); pw.println(")"); 1237 continue; 1238 } 1239 pw.print(" * "); pw.print(procName); pw.print(" / "); 1240 UserHandle.formatUid(pw, uid); 1241 pw.print(" ("); pw.print(proc.getDurationsBucketCount()); 1242 pw.print(" entries)"); pw.println(":"); 1243 proc.dumpProcessState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, 1244 ALL_PROC_STATES, now); 1245 proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES); 1246 proc.dumpInternalLocked(pw, " ", dumpAll); 1247 } 1248 } 1249 if (dumpAll) { 1250 pw.println(); 1251 pw.print(" Total procs: "); pw.print(numShownProcs); 1252 pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); 1253 } 1254 1255 if (sepNeeded) { 1256 pw.println(); 1257 } 1258 if (dumpSummary) { 1259 pw.println("Summary:"); 1260 dumpSummaryLocked(pw, reqPackage, now, activeOnly); 1261 } else { 1262 dumpTotalsLocked(pw, now); 1263 } 1264 1265 if (dumpAll) { 1266 pw.println(); 1267 pw.println("Internal state:"); 1268 /* 1269 pw.print(" Num long arrays: "); pw.println(mLongs.size()); 1270 pw.print(" Next long entry: "); pw.println(mNextLong); 1271 */ 1272 pw.print(" mRunning="); pw.println(mRunning); 1273 } 1274 } 1275 1276 public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) { 1277 long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, 1278 mStartTime, now); 1279 dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, 1280 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly); 1281 pw.println(); 1282 dumpTotalsLocked(pw, now); 1283 } 1284 1285 long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, 1286 long totalTime, long curTotalMem, int samples) { 1287 if (memWeight != 0) { 1288 long mem = (long)(memWeight * 1024 / totalTime); 1289 pw.print(prefix); 1290 pw.print(label); 1291 pw.print(": "); 1292 DebugUtils.printSizeValue(pw, mem); 1293 pw.print(" ("); 1294 pw.print(samples); 1295 pw.print(" samples)"); 1296 pw.println(); 1297 return curTotalMem + mem; 1298 } 1299 return curTotalMem; 1300 } 1301 1302 void dumpTotalsLocked(PrintWriter pw, long now) { 1303 pw.println("Run time Stats:"); 1304 DumpUtils.dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now); 1305 pw.println(); 1306 pw.println("Memory usage:"); 1307 TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, 1308 ALL_MEM_ADJ); 1309 computeTotalMemoryUse(totalMem, now); 1310 long totalPss = 0; 1311 totalPss = printMemoryCategory(pw, " ", "Kernel ", totalMem.sysMemKernelWeight, 1312 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 1313 totalPss = printMemoryCategory(pw, " ", "Native ", totalMem.sysMemNativeWeight, 1314 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 1315 for (int i=0; i<STATE_COUNT; i++) { 1316 // Skip restarting service state -- that is not actually a running process. 1317 if (i != STATE_SERVICE_RESTARTING) { 1318 totalPss = printMemoryCategory(pw, " ", DumpUtils.STATE_NAMES[i], 1319 totalMem.processStateWeight[i], totalMem.totalTime, totalPss, 1320 totalMem.processStateSamples[i]); 1321 } 1322 } 1323 totalPss = printMemoryCategory(pw, " ", "Cached ", totalMem.sysMemCachedWeight, 1324 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 1325 totalPss = printMemoryCategory(pw, " ", "Free ", totalMem.sysMemFreeWeight, 1326 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 1327 totalPss = printMemoryCategory(pw, " ", "Z-Ram ", totalMem.sysMemZRamWeight, 1328 totalMem.totalTime, totalPss, totalMem.sysMemSamples); 1329 pw.print(" TOTAL : "); 1330 DebugUtils.printSizeValue(pw, totalPss); 1331 pw.println(); 1332 printMemoryCategory(pw, " ", DumpUtils.STATE_NAMES[STATE_SERVICE_RESTARTING], 1333 totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss, 1334 totalMem.processStateSamples[STATE_SERVICE_RESTARTING]); 1335 pw.println(); 1336 pw.print(" Start time: "); 1337 pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock)); 1338 pw.println(); 1339 pw.print(" Total elapsed time: "); 1340 TimeUtils.formatDuration( 1341 (mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime) 1342 - mTimePeriodStartRealtime, pw); 1343 boolean partial = true; 1344 if ((mFlags&FLAG_SHUTDOWN) != 0) { 1345 pw.print(" (shutdown)"); 1346 partial = false; 1347 } 1348 if ((mFlags&FLAG_SYSPROPS) != 0) { 1349 pw.print(" (sysprops)"); 1350 partial = false; 1351 } 1352 if ((mFlags&FLAG_COMPLETE) != 0) { 1353 pw.print(" (complete)"); 1354 partial = false; 1355 } 1356 if (partial) { 1357 pw.print(" (partial)"); 1358 } 1359 if (mHasSwappedOutPss) { 1360 pw.print(" (swapped-out-pss)"); 1361 } 1362 pw.print(' '); 1363 pw.print(mRuntime); 1364 pw.println(); 1365 } 1366 1367 void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, 1368 int[] screenStates, int[] memStates, int[] procStates, 1369 int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) { 1370 ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates, 1371 procStates, sortProcStates, now, reqPackage, activeOnly); 1372 if (procs.size() > 0) { 1373 if (header != null) { 1374 pw.println(); 1375 pw.println(header); 1376 } 1377 DumpUtils.dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates, 1378 sortProcStates, now, totalTime); 1379 } 1380 } 1381 1382 public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates, 1383 int[] procStates, int sortProcStates[], long now, String reqPackage, 1384 boolean activeOnly) { 1385 final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>(); 1386 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1387 for (int ip=0; ip<pkgMap.size(); ip++) { 1388 final String pkgName = pkgMap.keyAt(ip); 1389 final SparseArray<SparseArray<PackageState>> procs = pkgMap.valueAt(ip); 1390 for (int iu=0; iu<procs.size(); iu++) { 1391 final SparseArray<PackageState> vpkgs = procs.valueAt(iu); 1392 final int NVERS = vpkgs.size(); 1393 for (int iv=0; iv<NVERS; iv++) { 1394 final PackageState state = vpkgs.valueAt(iv); 1395 final int NPROCS = state.mProcesses.size(); 1396 final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); 1397 for (int iproc=0; iproc<NPROCS; iproc++) { 1398 final ProcessState proc = state.mProcesses.valueAt(iproc); 1399 if (!pkgMatch && !reqPackage.equals(proc.getName())) { 1400 continue; 1401 } 1402 if (activeOnly && !proc.isInUse()) { 1403 continue; 1404 } 1405 foundProcs.add(proc.getCommonProcess()); 1406 } 1407 } 1408 } 1409 } 1410 ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size()); 1411 for (int i=0; i<foundProcs.size(); i++) { 1412 ProcessState proc = foundProcs.valueAt(i); 1413 if (proc.computeProcessTimeLocked(screenStates, memStates, procStates, now) > 0) { 1414 outProcs.add(proc); 1415 if (procStates != sortProcStates) { 1416 proc.computeProcessTimeLocked(screenStates, memStates, sortProcStates, now); 1417 } 1418 } 1419 } 1420 Collections.sort(outProcs, ProcessState.COMPARATOR); 1421 return outProcs; 1422 } 1423 1424 public void dumpCheckinLocked(PrintWriter pw, String reqPackage) { 1425 final long now = SystemClock.uptimeMillis(); 1426 final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); 1427 pw.println("vers,5"); 1428 pw.print("period,"); pw.print(mTimePeriodStartClockStr); 1429 pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(","); 1430 pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime); 1431 boolean partial = true; 1432 if ((mFlags&FLAG_SHUTDOWN) != 0) { 1433 pw.print(",shutdown"); 1434 partial = false; 1435 } 1436 if ((mFlags&FLAG_SYSPROPS) != 0) { 1437 pw.print(",sysprops"); 1438 partial = false; 1439 } 1440 if ((mFlags&FLAG_COMPLETE) != 0) { 1441 pw.print(",complete"); 1442 partial = false; 1443 } 1444 if (partial) { 1445 pw.print(",partial"); 1446 } 1447 if (mHasSwappedOutPss) { 1448 pw.print(",swapped-out-pss"); 1449 } 1450 pw.println(); 1451 pw.print("config,"); pw.println(mRuntime); 1452 for (int ip=0; ip<pkgMap.size(); ip++) { 1453 final String pkgName = pkgMap.keyAt(ip); 1454 if (reqPackage != null && !reqPackage.equals(pkgName)) { 1455 continue; 1456 } 1457 final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip); 1458 for (int iu=0; iu<uids.size(); iu++) { 1459 final int uid = uids.keyAt(iu); 1460 final SparseArray<PackageState> vpkgs = uids.valueAt(iu); 1461 for (int iv=0; iv<vpkgs.size(); iv++) { 1462 final int vers = vpkgs.keyAt(iv); 1463 final PackageState pkgState = vpkgs.valueAt(iv); 1464 final int NPROCS = pkgState.mProcesses.size(); 1465 final int NSRVS = pkgState.mServices.size(); 1466 for (int iproc=0; iproc<NPROCS; iproc++) { 1467 ProcessState proc = pkgState.mProcesses.valueAt(iproc); 1468 proc.dumpPackageProcCheckin(pw, pkgName, uid, vers, 1469 pkgState.mProcesses.keyAt(iproc), now); 1470 } 1471 for (int isvc=0; isvc<NSRVS; isvc++) { 1472 final String serviceName = DumpUtils.collapseString(pkgName, 1473 pkgState.mServices.keyAt(isvc)); 1474 final ServiceState svc = pkgState.mServices.valueAt(isvc); 1475 svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now); 1476 } 1477 } 1478 } 1479 } 1480 1481 ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); 1482 for (int ip=0; ip<procMap.size(); ip++) { 1483 String procName = procMap.keyAt(ip); 1484 SparseArray<ProcessState> uids = procMap.valueAt(ip); 1485 for (int iu=0; iu<uids.size(); iu++) { 1486 final int uid = uids.keyAt(iu); 1487 final ProcessState procState = uids.valueAt(iu); 1488 procState.dumpProcCheckin(pw, procName, uid, now); 1489 } 1490 } 1491 pw.print("total"); 1492 DumpUtils.dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor, mStartTime, now); 1493 pw.println(); 1494 final int sysMemUsageCount = mSysMemUsage.getKeyCount(); 1495 if (sysMemUsageCount > 0) { 1496 pw.print("sysmemusage"); 1497 for (int i=0; i<sysMemUsageCount; i++) { 1498 final int key = mSysMemUsage.getKeyAt(i); 1499 final int type = SparseMappingTable.getIdFromKey(key); 1500 pw.print(","); 1501 DumpUtils.printProcStateTag(pw, type); 1502 for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) { 1503 if (j > SYS_MEM_USAGE_CACHED_MINIMUM) { 1504 pw.print(":"); 1505 } 1506 pw.print(mSysMemUsage.getValue(key, j)); 1507 } 1508 } 1509 } 1510 pw.println(); 1511 TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, 1512 ALL_MEM_ADJ); 1513 computeTotalMemoryUse(totalMem, now); 1514 pw.print("weights,"); 1515 pw.print(totalMem.totalTime); 1516 pw.print(","); 1517 pw.print(totalMem.sysMemCachedWeight); 1518 pw.print(":"); 1519 pw.print(totalMem.sysMemSamples); 1520 pw.print(","); 1521 pw.print(totalMem.sysMemFreeWeight); 1522 pw.print(":"); 1523 pw.print(totalMem.sysMemSamples); 1524 pw.print(","); 1525 pw.print(totalMem.sysMemZRamWeight); 1526 pw.print(":"); 1527 pw.print(totalMem.sysMemSamples); 1528 pw.print(","); 1529 pw.print(totalMem.sysMemKernelWeight); 1530 pw.print(":"); 1531 pw.print(totalMem.sysMemSamples); 1532 pw.print(","); 1533 pw.print(totalMem.sysMemNativeWeight); 1534 pw.print(":"); 1535 pw.print(totalMem.sysMemSamples); 1536 for (int i=0; i<STATE_COUNT; i++) { 1537 pw.print(","); 1538 pw.print(totalMem.processStateWeight[i]); 1539 pw.print(":"); 1540 pw.print(totalMem.processStateSamples[i]); 1541 } 1542 pw.println(); 1543 } 1544 1545 1546 final public static class ProcessStateHolder { 1547 public final int appVersion; 1548 public ProcessState state; 1549 1550 public ProcessStateHolder(int _appVersion) { 1551 appVersion = _appVersion; 1552 } 1553 } 1554 1555 public static final class PackageState { 1556 public final ArrayMap<String, ProcessState> mProcesses 1557 = new ArrayMap<String, ProcessState>(); 1558 public final ArrayMap<String, ServiceState> mServices 1559 = new ArrayMap<String, ServiceState>(); 1560 public final String mPackageName; 1561 public final int mUid; 1562 1563 public PackageState(String packageName, int uid) { 1564 mUid = uid; 1565 mPackageName = packageName; 1566 } 1567 } 1568 1569 public static final class ProcessDataCollection { 1570 final int[] screenStates; 1571 final int[] memStates; 1572 final int[] procStates; 1573 1574 public long totalTime; 1575 public long numPss; 1576 public long minPss; 1577 public long avgPss; 1578 public long maxPss; 1579 public long minUss; 1580 public long avgUss; 1581 public long maxUss; 1582 1583 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) { 1584 screenStates = _screenStates; 1585 memStates = _memStates; 1586 procStates = _procStates; 1587 } 1588 1589 void print(PrintWriter pw, long overallTime, boolean full) { 1590 if (totalTime > overallTime) { 1591 pw.print("*"); 1592 } 1593 DumpUtils.printPercent(pw, (double) totalTime / (double) overallTime); 1594 if (numPss > 0) { 1595 pw.print(" ("); 1596 DebugUtils.printSizeValue(pw, minPss * 1024); 1597 pw.print("-"); 1598 DebugUtils.printSizeValue(pw, avgPss * 1024); 1599 pw.print("-"); 1600 DebugUtils.printSizeValue(pw, maxPss * 1024); 1601 pw.print("/"); 1602 DebugUtils.printSizeValue(pw, minUss * 1024); 1603 pw.print("-"); 1604 DebugUtils.printSizeValue(pw, avgUss * 1024); 1605 pw.print("-"); 1606 DebugUtils.printSizeValue(pw, maxUss * 1024); 1607 if (full) { 1608 pw.print(" over "); 1609 pw.print(numPss); 1610 } 1611 pw.print(")"); 1612 } 1613 } 1614 } 1615 1616 public static class TotalMemoryUseCollection { 1617 final int[] screenStates; 1618 final int[] memStates; 1619 1620 public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) { 1621 screenStates = _screenStates; 1622 memStates = _memStates; 1623 } 1624 1625 public long totalTime; 1626 public long[] processStatePss = new long[STATE_COUNT]; 1627 public double[] processStateWeight = new double[STATE_COUNT]; 1628 public long[] processStateTime = new long[STATE_COUNT]; 1629 public int[] processStateSamples = new int[STATE_COUNT]; 1630 public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT]; 1631 public double sysMemCachedWeight; 1632 public double sysMemFreeWeight; 1633 public double sysMemZRamWeight; 1634 public double sysMemKernelWeight; 1635 public double sysMemNativeWeight; 1636 public int sysMemSamples; 1637 public boolean hasSwappedOutPss; 1638 } 1639 1640} 1641