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 ProcessStats(boolean running)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 ProcessStats(Parcel in)213 public ProcessStats(Parcel in) { 214 reset(); 215 readFromParcel(in); 216 } 217 add(ProcessStats other)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 addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem, long nativeMem)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 computeTotalMemoryUse(TotalMemoryUseCollection data, long now)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 reset()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 resetSafely()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 resetCommon()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 evaluateSystemProperties(boolean update)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 buildTimePeriodStartClockStr()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 */ updateFragmentation()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 */ splitAndParseNumbers(String s)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 writeCompactedLongArray(Parcel out, long[] array, int num)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 readCompactedLongArray(Parcel in, int version, long[] array, int num)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 writeCommonString(Parcel out, String name)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 readCommonString(Parcel in, int version)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 describeContents()697 public int describeContents() { 698 return 0; 699 } 700 701 @Override writeToParcel(Parcel out, int flags)702 public void writeToParcel(Parcel out, int flags) { 703 writeToParcel(out, SystemClock.uptimeMillis(), flags); 704 } 705 706 /** @hide */ writeToParcel(Parcel out, long now, int flags)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 readCheckedInt(Parcel in, int val, String what)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 readFully(InputStream stream, int[] outLen)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 read(InputStream stream)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 readFromParcel(Parcel in)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 getPackageStateLocked(String packageName, int uid, int vers)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 getProcessStateLocked(String packageName, int uid, int vers, String processName)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 getServiceStateLocked(String packageName, int uid, int vers, String processName, String className)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 dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, boolean dumpAll, boolean activeOnly)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 dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly)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 dumpFragmentationLocked(PrintWriter pw)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 printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, long totalTime, long curTotalMem, int samples)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 dumpTotalsLocked(PrintWriter pw, long now)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 dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, int[] screenStates, int[] memStates, int[] procStates, int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly)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 collectProcessesLocked(int[] screenStates, int[] memStates, int[] procStates, int sortProcStates[], long now, String reqPackage, boolean activeOnly)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 dumpCheckinLocked(PrintWriter pw, String reqPackage)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 ProcessStateHolder(int _appVersion)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 PackageState(String packageName, int uid)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 ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates)1747 public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) { 1748 screenStates = _screenStates; 1749 memStates = _memStates; 1750 procStates = _procStates; 1751 } 1752 print(PrintWriter pw, long overallTime, boolean full)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 TotalMemoryUseCollection(int[] _screenStates, int[] _memStates)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