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 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 234 public ProcessStats(Parcel in) { 235 reset(); 236 readFromParcel(in); 237 } 238 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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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 741 public int describeContents() { 742 return 0; 743 } 744 745 @Override 746 public void writeToParcel(Parcel out, int flags) { 747 writeToParcel(out, SystemClock.uptimeMillis(), flags); 748 } 749 750 /** @hide */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1890 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) { 1891 screenStates = _screenStates; 1892 memStates = _memStates; 1893 procStates = _procStates; 1894 } 1895 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 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