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