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