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