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