1 /* 2 * Copyright (C) 2020 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.server.am; 18 19 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 20 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; 21 import static android.os.Process.FIRST_APPLICATION_UID; 22 import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS; 23 import static android.view.Display.INVALID_DISPLAY; 24 25 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL; 26 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; 27 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; 28 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; 29 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ; 30 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS; 31 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RSS; 32 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS; 33 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RSS; 34 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 35 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 36 import static com.android.server.am.ActivityManagerService.DUMP_MEM_OOM_ADJ; 37 import static com.android.server.am.ActivityManagerService.DUMP_MEM_OOM_LABEL; 38 import static com.android.server.am.ActivityManagerService.GC_BACKGROUND_PROCESSES_MSG; 39 import static com.android.server.am.ActivityManagerService.KSM_SHARED; 40 import static com.android.server.am.ActivityManagerService.KSM_SHARING; 41 import static com.android.server.am.ActivityManagerService.KSM_UNSHARED; 42 import static com.android.server.am.ActivityManagerService.KSM_VOLATILE; 43 import static com.android.server.am.ActivityManagerService.REPORT_MEM_USAGE_MSG; 44 import static com.android.server.am.ActivityManagerService.appendBasicMemEntry; 45 import static com.android.server.am.ActivityManagerService.appendMemBucket; 46 import static com.android.server.am.ActivityManagerService.appendMemInfo; 47 import static com.android.server.am.ActivityManagerService.getKsmInfo; 48 import static com.android.server.am.ActivityManagerService.stringifyKBSize; 49 import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING; 50 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 51 import static com.android.server.wm.ActivityTaskManagerService.DUMP_ACTIVITIES_CMD; 52 53 import android.annotation.BroadcastBehavior; 54 import android.annotation.NonNull; 55 import android.annotation.Nullable; 56 import android.app.ActivityManager; 57 import android.app.ActivityThread; 58 import android.app.IApplicationThread; 59 import android.app.ProfilerInfo; 60 import android.content.ComponentCallbacks2; 61 import android.content.ContentResolver; 62 import android.content.Context; 63 import android.content.Intent; 64 import android.content.pm.PackageManager.NameNotFoundException; 65 import android.net.Uri; 66 import android.os.Binder; 67 import android.os.Build; 68 import android.os.Debug; 69 import android.os.Flags; 70 import android.os.Handler; 71 import android.os.Looper; 72 import android.os.Message; 73 import android.os.ParcelFileDescriptor; 74 import android.os.RemoteException; 75 import android.os.ServiceManager; 76 import android.os.SystemClock; 77 import android.os.SystemProperties; 78 import android.os.UserHandle; 79 import android.provider.DeviceConfig; 80 import android.provider.DeviceConfig.Properties; 81 import android.text.TextUtils; 82 import android.util.ArrayMap; 83 import android.util.DebugUtils; 84 import android.util.FeatureFlagUtils; 85 import android.util.Pair; 86 import android.util.Slog; 87 import android.util.SparseArray; 88 import android.util.SparseIntArray; 89 import android.util.StatsEvent; 90 import android.util.proto.ProtoOutputStream; 91 92 import com.android.internal.annotations.GuardedBy; 93 import com.android.internal.app.ProcessMap; 94 import com.android.internal.app.procstats.ProcessStats; 95 import com.android.internal.os.BackgroundThread; 96 import com.android.internal.os.BinderInternal; 97 import com.android.internal.os.ProcessCpuTracker; 98 import com.android.internal.util.DumpUtils; 99 import com.android.internal.util.FastPrintWriter; 100 import com.android.internal.util.FrameworkStatsLog; 101 import com.android.internal.util.MemInfoReader; 102 import com.android.internal.util.QuickSelect; 103 import com.android.server.am.LowMemDetector.MemFactor; 104 import com.android.server.power.stats.BatteryStatsImpl; 105 import com.android.server.utils.PriorityDump; 106 107 import java.io.FileDescriptor; 108 import java.io.IOException; 109 import java.io.PrintWriter; 110 import java.io.StringWriter; 111 import java.util.ArrayList; 112 import java.util.Collections; 113 import java.util.Comparator; 114 import java.util.HashMap; 115 import java.util.List; 116 import java.util.Map; 117 import java.util.concurrent.CountDownLatch; 118 import java.util.concurrent.atomic.AtomicBoolean; 119 import java.util.concurrent.atomic.AtomicInteger; 120 import java.util.concurrent.atomic.AtomicLong; 121 import java.util.function.Consumer; 122 import java.util.function.Predicate; 123 124 /** 125 * A helper class taking care of the profiling, memory and cpu sampling of apps 126 */ 127 public class AppProfiler { 128 private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM; 129 130 static final String TAG_PSS = TAG + POSTFIX_PSS; 131 static final String TAG_RSS = TAG + POSTFIX_RSS; 132 133 static final String TAG_OOM_ADJ = ActivityManagerService.TAG_OOM_ADJ; 134 135 /** Control over CPU and battery monitoring */ 136 // write battery stats every 30 minutes. 137 static final long BATTERY_STATS_TIME = 30 * 60 * 1000; 138 139 static final boolean MONITOR_CPU_USAGE = true; 140 141 // don't sample cpu less than every 5 seconds. 142 static final long MONITOR_CPU_MIN_TIME = 5 * 1000; 143 144 // wait possibly forever for next cpu sample. 145 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; 146 147 static final boolean MONITOR_THREAD_CPU_USAGE = false; 148 149 static final String ACTIVITY_START_PSS_DEFER_CONFIG = "activity_start_pss_defer"; 150 151 /** 152 * Broadcast sent when heap dump collection has been completed. 153 */ 154 @BroadcastBehavior(includeBackground = true, protectedBroadcast = true) 155 private static final String ACTION_HEAP_DUMP_FINISHED = 156 "com.android.internal.intent.action.HEAP_DUMP_FINISHED"; 157 158 /** 159 * The process we are reporting 160 */ 161 private static final String EXTRA_HEAP_DUMP_PROCESS_NAME = 162 "com.android.internal.extra.heap_dump.PROCESS_NAME"; 163 164 /** 165 * The size limit the process reached. 166 */ 167 private static final String EXTRA_HEAP_DUMP_SIZE_BYTES = 168 "com.android.internal.extra.heap_dump.SIZE_BYTES"; 169 170 /** 171 * Whether the user initiated the dump or not. 172 */ 173 private static final String EXTRA_HEAP_DUMP_IS_USER_INITIATED = 174 "com.android.internal.extra.heap_dump.IS_USER_INITIATED"; 175 176 /** 177 * Optional name of package to directly launch. 178 */ 179 private static final String EXTRA_HEAP_DUMP_REPORT_PACKAGE = 180 "com.android.internal.extra.heap_dump.REPORT_PACKAGE"; 181 182 /** 183 * How long we defer PSS gathering while activities are starting, in milliseconds. 184 * This is adjustable via DeviceConfig. If it is zero or negative, no PSS deferral 185 * is done. 186 */ 187 private volatile long mPssDeferralTime = 0; 188 189 /** 190 * Processes we want to collect PSS or RSS data from. 191 */ 192 @GuardedBy("mProfilerLock") 193 private final ArrayList<ProcessProfileRecord> mPendingPssOrRssProfiles = new ArrayList<>(); 194 195 /** 196 * Depth of overlapping activity-start PSS deferral notes 197 */ 198 private final AtomicInteger mActivityStartingNesting = new AtomicInteger(0); 199 200 /** 201 * Last time we requested PSS data of all processes. 202 */ 203 @GuardedBy("mProfilerLock") 204 private long mLastFullPssTime = SystemClock.uptimeMillis(); 205 206 /** 207 * If set, the next time we collect PSS or RSS data we should do a full collection with data 208 * from native processes and the kernel. 209 */ 210 @GuardedBy("mProfilerLock") 211 private boolean mFullPssOrRssPending = false; 212 213 /** 214 * If true, we are running under a test environment so will sample PSS or RSS from processes 215 * much more rapidly to try to collect better data when the tests are rapidly running through 216 * apps. 217 */ 218 private volatile boolean mTestPssOrRssMode = false; 219 220 private final LowMemDetector mLowMemDetector; 221 222 /** 223 * Allow the current computed overall memory level of the system to go down? 224 * This is set to false when we are killing processes for reasons other than 225 * memory management, so that the now smaller process list will not be taken as 226 * an indication that memory is tighter. 227 */ 228 @GuardedBy("mService") 229 private boolean mAllowLowerMemLevel = false; 230 231 /** 232 * The last computed memory level, for holding when we are in a state that 233 * processes are going away for other reasons. 234 */ 235 @GuardedBy("mService") 236 private @MemFactor int mLastMemoryLevel = ADJ_MEM_FACTOR_NORMAL; 237 238 @GuardedBy("mService") 239 private @MemFactor int mMemFactorOverride = ADJ_MEM_FACTOR_NOTHING; 240 241 /** 242 * The last total number of process we have, to determine if changes actually look 243 * like a shrinking number of process due to lower RAM. 244 */ 245 @GuardedBy("mService") 246 private int mLastNumProcesses; 247 248 /** 249 * Total time spent with RAM that has been added in the past since the last idle time. 250 */ 251 @GuardedBy("mProcLock") 252 private long mLowRamTimeSinceLastIdle = 0; 253 254 /** 255 * If RAM is currently low, when that horrible situation started. 256 */ 257 @GuardedBy("mProcLock") 258 private long mLowRamStartTime = 0; 259 260 /** 261 * Last time we report a memory usage. 262 */ 263 @GuardedBy("mService") 264 private long mLastMemUsageReportTime = 0; 265 266 /** 267 * List of processes that should gc as soon as things are idle. 268 */ 269 @GuardedBy("mProfilerLock") 270 private final ArrayList<ProcessRecord> mProcessesToGc = new ArrayList<>(); 271 272 /** 273 * Stores a map of process name -> agent string. When a process is started and mAgentAppMap 274 * is not null, this map is checked and the mapped agent installed during bind-time. Note: 275 * A non-null agent in mProfileInfo overrides this. 276 */ 277 @GuardedBy("mProfilerLock") 278 private @Nullable Map<String, String> mAppAgentMap = null; 279 280 @GuardedBy("mProfilerLock") 281 private int mProfileType = 0; 282 283 @GuardedBy("mProfilerLock") 284 private final ProfileData mProfileData = new ProfileData(); 285 286 @GuardedBy("mProfilerLock") 287 private final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>(); 288 289 @GuardedBy("mProfilerLock") 290 private String mMemWatchDumpProcName; 291 292 @GuardedBy("mProfilerLock") 293 private Uri mMemWatchDumpUri; 294 295 @GuardedBy("mProfilerLock") 296 private int mMemWatchDumpPid; 297 298 @GuardedBy("mProfilerLock") 299 private int mMemWatchDumpUid; 300 301 @GuardedBy("mProfilerLock") 302 private boolean mMemWatchIsUserInitiated; 303 304 @GuardedBy("mService") 305 boolean mHasHomeProcess; 306 307 @GuardedBy("mService") 308 boolean mHasPreviousProcess; 309 310 /** 311 * Used to collect per-process CPU use for ANRs, battery stats, etc. 312 * Must acquire this object's lock when accessing it. 313 * NOTE: this lock will be held while doing long operations (trawling 314 * through all processes in /proc), so it should never be acquired by 315 * any critical paths such as when holding the main activity manager lock. 316 */ 317 private final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker( 318 MONITOR_THREAD_CPU_USAGE); 319 private final AtomicLong mLastCpuTime = new AtomicLong(0); 320 private final AtomicBoolean mProcessCpuMutexFree = new AtomicBoolean(true); 321 private final CountDownLatch mProcessCpuInitLatch = new CountDownLatch(1); 322 323 private volatile long mLastWriteTime = 0; 324 325 /** 326 * Runtime CPU use collection thread. This object's lock is used to 327 * perform synchronization with the thread (notifying it to run). 328 */ 329 private final Thread mProcessCpuThread; 330 331 private final ActivityManagerService mService; 332 private final Handler mBgHandler; 333 334 final CachedAppsWatermarkData mCachedAppsWatermarkData = new CachedAppsWatermarkData(); 335 336 /** 337 * The lock to guard some of the profiling data here and {@link ProcessProfileRecord}. 338 * 339 * <p> 340 * The function suffix with this lock would be "-LPf" (Locked with Profiler lock). 341 * </p> 342 */ 343 final Object mProfilerLock = new Object(); 344 345 final ActivityManagerGlobalLock mProcLock; 346 347 /** 348 * Observe DeviceConfig changes to the PSS calculation interval 349 */ 350 private final DeviceConfig.OnPropertiesChangedListener mPssDelayConfigListener = 351 new DeviceConfig.OnPropertiesChangedListener() { 352 @Override 353 public void onPropertiesChanged(Properties properties) { 354 if (properties.getKeyset().contains(ACTIVITY_START_PSS_DEFER_CONFIG)) { 355 mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0); 356 if (DEBUG_PSS) { 357 Slog.d(TAG_PSS, "Activity-start PSS delay now " 358 + mPssDeferralTime + " ms"); 359 } 360 } 361 } 362 }; 363 364 private class ProfileData { 365 private String mProfileApp = null; 366 private ProcessRecord mProfileProc = null; 367 private ProfilerInfo mProfilerInfo = null; 368 setProfileApp(String profileApp)369 void setProfileApp(String profileApp) { 370 mProfileApp = profileApp; 371 if (mService.mAtmInternal != null) { 372 mService.mAtmInternal.setProfileApp(profileApp); 373 } 374 } 375 getProfileApp()376 String getProfileApp() { 377 return mProfileApp; 378 } 379 setProfileProc(ProcessRecord profileProc)380 void setProfileProc(ProcessRecord profileProc) { 381 mProfileProc = profileProc; 382 if (mService.mAtmInternal != null) { 383 mService.mAtmInternal.setProfileProc(profileProc == null ? null 384 : profileProc.getWindowProcessController()); 385 } 386 } 387 getProfileProc()388 ProcessRecord getProfileProc() { 389 return mProfileProc; 390 } 391 setProfilerInfo(ProfilerInfo profilerInfo)392 void setProfilerInfo(ProfilerInfo profilerInfo) { 393 mProfilerInfo = profilerInfo; 394 if (mService.mAtmInternal != null) { 395 mService.mAtmInternal.setProfilerInfo(profilerInfo); 396 } 397 } 398 getProfilerInfo()399 ProfilerInfo getProfilerInfo() { 400 return mProfilerInfo; 401 } 402 } 403 404 /** 405 * A simple data class holding the information about the cached apps high watermark. 406 * 407 * Keep it sync with the frameworks/proto_logging/stats/atoms.proto 408 */ 409 class CachedAppsWatermarkData { 410 /** The high water mark of the number of cached apps. */ 411 @GuardedBy("mProcLock") 412 int mCachedAppHighWatermark; 413 414 /** 415 * The uptime (in seconds) at the high watermark. 416 * Note this is going to be pull metrics, so we'll need the timestamp here. 417 */ 418 @GuardedBy("mProcLock") 419 int mUptimeInSeconds; 420 421 /** The number of binder proxy at that high water mark. */ 422 @GuardedBy("mProcLock") 423 int mBinderProxySnapshot; 424 425 /** Free physical memory (in kb) on device. */ 426 @GuardedBy("mProcLock") 427 int mFreeInKb; 428 429 /** Cched physical memory (in kb) on device. */ 430 @GuardedBy("mProcLock") 431 int mCachedInKb; 432 433 /** zram (in kb) on device. */ 434 @GuardedBy("mProcLock") 435 int mZramInKb; 436 437 /** Kernel memory (in kb) on device. */ 438 @GuardedBy("mProcLock") 439 int mKernelInKb; 440 441 /** The number of apps in frozen state. */ 442 @GuardedBy("mProcLock") 443 int mNumOfFrozenApps; 444 445 /** The longest frozen time (now - last_frozen) in current frozen apps. */ 446 @GuardedBy("mProcLock") 447 int mLongestFrozenTimeInSeconds; 448 449 /** The shortest frozen time (now - last_frozen) in current frozen apps. */ 450 @GuardedBy("mProcLock") 451 int mShortestFrozenTimeInSeconds; 452 453 /** The mean frozen time (now - last_frozen) in current frozen apps. */ 454 @GuardedBy("mProcLock") 455 int mMeanFrozenTimeInSeconds; 456 457 /** The average frozen time (now - last_frozen) in current frozen apps. */ 458 @GuardedBy("mProcLock") 459 int mAverageFrozenTimeInSeconds; 460 461 /** 462 * This is an array holding the frozen app durations temporarily 463 * while updating the cached app high watermark. 464 */ 465 @GuardedBy("mProcLock") 466 private long[] mCachedAppFrozenDurations; 467 468 /** 469 * The earliest frozen timestamp within the frozen apps. 470 */ 471 @GuardedBy("mProcLock") 472 private long mEarliestFrozenTimestamp; 473 474 /** 475 * The most recent frozen timestamp within the frozen apps. 476 */ 477 @GuardedBy("mProcLock") 478 private long mLatestFrozenTimestamp; 479 480 /** 481 * The sum of total frozen durations of all frozen apps. 482 */ 483 @GuardedBy("mProcLock") 484 private long mTotalFrozenDurations; 485 486 @GuardedBy("mProcLock") updateCachedAppsHighWatermarkIfNecessaryLocked(int numOfCachedApps, long now)487 void updateCachedAppsHighWatermarkIfNecessaryLocked(int numOfCachedApps, long now) { 488 if (numOfCachedApps > mCachedAppHighWatermark) { 489 mCachedAppHighWatermark = numOfCachedApps; 490 mUptimeInSeconds = (int) (now / 1000); 491 492 // The rest of the updates are pretty costly, do it in a separated handler. 493 mService.mHandler.removeMessages( 494 ActivityManagerService.UPDATE_CACHED_APP_HIGH_WATERMARK); 495 mService.mHandler.obtainMessage( 496 ActivityManagerService.UPDATE_CACHED_APP_HIGH_WATERMARK, Long.valueOf(now)) 497 .sendToTarget(); 498 } 499 } 500 updateCachedAppsSnapshot(long now)501 void updateCachedAppsSnapshot(long now) { 502 synchronized (mProcLock) { 503 mEarliestFrozenTimestamp = now; 504 mLatestFrozenTimestamp = 0L; 505 mTotalFrozenDurations = 0L; 506 mNumOfFrozenApps = 0; 507 final int lruSize = mService.mProcessList.getLruSizeLOSP(); 508 if (mCachedAppFrozenDurations == null 509 || mCachedAppFrozenDurations.length < lruSize) { 510 mCachedAppFrozenDurations = new long[Math.max( 511 lruSize, mService.mConstants.CUR_MAX_CACHED_PROCESSES)]; 512 } 513 mService.mProcessList.forEachLruProcessesLOSP(true, app -> { 514 if (app.mOptRecord.isFrozen()) { 515 final long freezeTime = app.mOptRecord.getFreezeUnfreezeTime(); 516 if (freezeTime < mEarliestFrozenTimestamp) { 517 mEarliestFrozenTimestamp = freezeTime; 518 } 519 if (freezeTime > mLatestFrozenTimestamp) { 520 mLatestFrozenTimestamp = freezeTime; 521 } 522 final long duration = now - freezeTime; 523 mTotalFrozenDurations += duration; 524 mCachedAppFrozenDurations[mNumOfFrozenApps++] = duration; 525 } 526 }); 527 if (mNumOfFrozenApps > 0) { 528 mLongestFrozenTimeInSeconds = (int) ((now - mEarliestFrozenTimestamp) / 1000); 529 mShortestFrozenTimeInSeconds = (int) ((now - mLatestFrozenTimestamp) / 1000); 530 mAverageFrozenTimeInSeconds = 531 (int) ((mTotalFrozenDurations / mNumOfFrozenApps) / 1000); 532 mMeanFrozenTimeInSeconds = (int) (QuickSelect.select(mCachedAppFrozenDurations, 533 0, mNumOfFrozenApps, mNumOfFrozenApps / 2) / 1000); 534 } 535 536 mBinderProxySnapshot = 0; 537 final SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts(); 538 if (counts != null) { 539 for (int i = 0, size = counts.size(); i < size; i++) { 540 final int uid = counts.keyAt(i); 541 final UidRecord uidRec = mService.mProcessList.getUidRecordLOSP(uid); 542 if (uidRec != null) { 543 mBinderProxySnapshot += counts.valueAt(i); 544 } 545 } 546 } 547 548 final MemInfoReader memInfo = new MemInfoReader(); 549 memInfo.readMemInfo(); 550 mFreeInKb = (int) memInfo.getFreeSizeKb(); 551 mCachedInKb = (int) memInfo.getCachedSizeKb(); 552 mZramInKb = (int) memInfo.getZramTotalSizeKb(); 553 mKernelInKb = (int) memInfo.getKernelUsedSizeKb(); 554 } 555 } 556 557 @NonNull getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull)558 StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull) { 559 synchronized (mProcLock) { 560 final StatsEvent event = FrameworkStatsLog.buildStatsEvent(atomTag, 561 mCachedAppHighWatermark, 562 mUptimeInSeconds, 563 mBinderProxySnapshot, 564 mFreeInKb, 565 mCachedInKb, 566 mZramInKb, 567 mKernelInKb, 568 mNumOfFrozenApps, 569 mLongestFrozenTimeInSeconds, 570 mShortestFrozenTimeInSeconds, 571 mMeanFrozenTimeInSeconds, 572 mAverageFrozenTimeInSeconds); 573 if (resetAfterPull) { 574 mCachedAppHighWatermark = 0; 575 mUptimeInSeconds = 0; 576 mBinderProxySnapshot = 0; 577 mFreeInKb = 0; 578 mCachedInKb = 0; 579 mZramInKb = 0; 580 mKernelInKb = 0; 581 mNumOfFrozenApps = 0; 582 mLongestFrozenTimeInSeconds = 0; 583 mShortestFrozenTimeInSeconds = 0; 584 mMeanFrozenTimeInSeconds = 0; 585 mAverageFrozenTimeInSeconds = 0; 586 } 587 return event; 588 } 589 } 590 } 591 592 private class BgHandler extends Handler { 593 static final int COLLECT_PSS_BG_MSG = 1; 594 static final int DEFER_PSS_MSG = 2; 595 static final int STOP_DEFERRING_PSS_MSG = 3; 596 static final int MEMORY_PRESSURE_CHANGED = 4; BgHandler(Looper looper)597 BgHandler(Looper looper) { 598 super(looper); 599 } 600 601 @Override handleMessage(Message msg)602 public void handleMessage(Message msg) { 603 switch (msg.what) { 604 case COLLECT_PSS_BG_MSG: 605 if (isProfilingPss()) { 606 collectPssInBackground(); 607 } else { 608 collectRssInBackground(); 609 } 610 break; 611 case DEFER_PSS_MSG: 612 deferPssForActivityStart(); 613 break; 614 case STOP_DEFERRING_PSS_MSG: 615 stopDeferPss(); 616 break; 617 case MEMORY_PRESSURE_CHANGED: 618 synchronized (mService) { 619 handleMemoryPressureChangedLocked(msg.arg1, msg.arg2); 620 } 621 break; 622 } 623 } 624 } 625 collectPssInBackground()626 private void collectPssInBackground() { 627 long start = SystemClock.uptimeMillis(); 628 MemInfoReader memInfo = null; 629 synchronized (mProfilerLock) { 630 if (mFullPssOrRssPending) { 631 mFullPssOrRssPending = false; 632 memInfo = new MemInfoReader(); 633 } 634 } 635 if (memInfo != null) { 636 updateCpuStatsNow(); 637 long nativeTotalPss = 0; 638 final List<ProcessCpuTracker.Stats> stats; 639 synchronized (mProcessCpuTracker) { 640 stats = mProcessCpuTracker.getStats(st -> { 641 return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID; 642 }); 643 } 644 645 if (!mService.mConstants.APP_PROFILER_PSS_PROFILING_DISABLED) { 646 final int numOfStats = stats.size(); 647 for (int j = 0; j < numOfStats; j++) { 648 synchronized (mService.mPidsSelfLocked) { 649 if (mService.mPidsSelfLocked.indexOfKey(stats.get(j).pid) >= 0) { 650 // This is one of our own processes; skip it. 651 continue; 652 } 653 } 654 nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null); 655 } 656 } 657 658 memInfo.readMemInfo(); 659 synchronized (mService.mProcessStats.mLock) { 660 if (DEBUG_PSS) { 661 Slog.d(TAG_PSS, "Collected native and kernel memory in " 662 + (SystemClock.uptimeMillis() - start) + "ms"); 663 } 664 final long cachedKb = memInfo.getCachedSizeKb(); 665 final long freeKb = memInfo.getFreeSizeKb(); 666 final long zramKb = memInfo.getZramTotalSizeKb(); 667 final long kernelKb = memInfo.getKernelUsedSizeKb(); 668 EventLogTags.writeAmMeminfo(cachedKb * 1024, freeKb * 1024, zramKb * 1024, 669 kernelKb * 1024, nativeTotalPss * 1024); 670 mService.mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb, 671 nativeTotalPss); 672 } 673 } 674 675 int num = 0; 676 long[] tmp = new long[3]; 677 do { 678 ProcessProfileRecord profile; 679 int procState; 680 int statType; 681 int pid = -1; 682 long lastPssTime; 683 synchronized (mProfilerLock) { 684 if (mPendingPssOrRssProfiles.size() <= 0) { 685 if (mTestPssOrRssMode || DEBUG_PSS) { 686 Slog.d(TAG_PSS, 687 "Collected pss of " + num + " processes in " 688 + (SystemClock.uptimeMillis() - start) + "ms"); 689 } 690 mPendingPssOrRssProfiles.clear(); 691 return; 692 } 693 profile = mPendingPssOrRssProfiles.remove(0); 694 procState = profile.getPssProcState(); 695 statType = profile.getPssStatType(); 696 lastPssTime = profile.getLastPssTime(); 697 long now = SystemClock.uptimeMillis(); 698 if (profile.getThread() != null && procState == profile.getSetProcState() 699 && (lastPssTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) < now) { 700 pid = profile.getPid(); 701 } else { 702 profile.abortNextPssTime(); 703 if (DEBUG_PSS) { 704 Slog.d(TAG_PSS, "Skipped pss collection of " + pid 705 + ": still need " 706 + (lastPssTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE - now) 707 + "ms until safe"); 708 } 709 profile = null; 710 pid = 0; 711 } 712 } 713 if (profile != null) { 714 long startTime = SystemClock.uptimeMillis(); 715 // skip background PSS calculation under the following situations: 716 // - app is capturing camera imagery 717 // - app is frozen and we have already collected PSS once. 718 final boolean skipPSSCollection = 719 (profile.mApp.mOptRecord != null 720 && profile.mApp.mOptRecord.skipPSSCollectionBecauseFrozen()) 721 || mService.isCameraActiveForUid(profile.mApp.uid) 722 || mService.mConstants.APP_PROFILER_PSS_PROFILING_DISABLED; 723 long pss = skipPSSCollection ? 0 : Debug.getPss(pid, tmp, null); 724 long endTime = SystemClock.uptimeMillis(); 725 synchronized (mProfilerLock) { 726 if (pss != 0 && profile.getThread() != null 727 && profile.getSetProcState() == procState 728 && profile.getPid() == pid && profile.getLastPssTime() == lastPssTime) { 729 num++; 730 profile.commitNextPssTime(); 731 recordPssSampleLPf(profile, procState, pss, tmp[0], tmp[1], tmp[2], 732 statType, endTime - startTime, SystemClock.uptimeMillis()); 733 } else { 734 profile.abortNextPssTime(); 735 if (DEBUG_PSS) { 736 Slog.d(TAG_PSS, "Skipped pss collection of " + pid 737 + ": " + (profile.getThread() == null ? "NO_THREAD " : "") 738 + (skipPSSCollection ? "SKIP_PSS_COLLECTION " : "") 739 + (profile.getPid() != pid ? "PID_CHANGED " : "") 740 + " initState=" + procState + " curState=" 741 + profile.getSetProcState() + " " 742 + (profile.getLastPssTime() != lastPssTime 743 ? "TIME_CHANGED" : "")); 744 } 745 } 746 } 747 } 748 } while (true); 749 } 750 isProfilingPss()751 boolean isProfilingPss() { 752 return !Flags.removeAppProfilerPssCollection() 753 || mService.mConstants.mForceEnablePssProfiling; 754 } 755 756 // This method is analogous to collectPssInBackground() and is intended to be used as a 757 // replacement if Flags.removeAppProfilerPssCollection() is enabled. References to PSS in 758 // methods outside of AppProfiler have generally been kept where a new RSS equivalent is not 759 // technically necessary. These can be updated once the flag is completely rolled out. collectRssInBackground()760 private void collectRssInBackground() { 761 long start = SystemClock.uptimeMillis(); 762 MemInfoReader memInfo = null; 763 synchronized (mProfilerLock) { 764 if (mFullPssOrRssPending) { 765 mFullPssOrRssPending = false; 766 memInfo = new MemInfoReader(); 767 } 768 } 769 if (memInfo != null) { 770 updateCpuStatsNow(); 771 long nativeTotalRss = 0; 772 final List<ProcessCpuTracker.Stats> stats; 773 synchronized (mProcessCpuTracker) { 774 stats = mProcessCpuTracker.getStats(st -> { 775 return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID; 776 }); 777 } 778 779 // We assume that if PSS collection isn't needed or desired, RSS collection can be 780 // disabled as well. 781 if (!mService.mConstants.APP_PROFILER_PSS_PROFILING_DISABLED) { 782 final int numOfStats = stats.size(); 783 for (int j = 0; j < numOfStats; j++) { 784 synchronized (mService.mPidsSelfLocked) { 785 if (mService.mPidsSelfLocked.indexOfKey(stats.get(j).pid) >= 0) { 786 // This is one of our own processes; skip it. 787 continue; 788 } 789 } 790 nativeTotalRss += Debug.getRss(stats.get(j).pid, null); 791 } 792 } 793 794 memInfo.readMemInfo(); 795 synchronized (mService.mProcessStats.mLock) { 796 // We assume that an enabled DEBUG_PSS can apply to RSS as well, since only one of 797 // either collectPssInBackground() or collectRssInBackground() will be used. 798 if (DEBUG_RSS) { 799 Slog.d(TAG_RSS, "Collected native and kernel memory in " 800 + (SystemClock.uptimeMillis() - start) + "ms"); 801 } 802 final long cachedKb = memInfo.getCachedSizeKb(); 803 final long freeKb = memInfo.getFreeSizeKb(); 804 final long zramKb = memInfo.getZramTotalSizeKb(); 805 final long kernelKb = memInfo.getKernelUsedSizeKb(); 806 // The last value needs to be updated in log tags to refer to RSS; this will be 807 // updated once the flag is fully rolled out. 808 EventLogTags.writeAmMeminfo(cachedKb * 1024, freeKb * 1024, zramKb * 1024, 809 kernelKb * 1024, nativeTotalRss * 1024); 810 mService.mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb, 811 nativeTotalRss); 812 } 813 } 814 815 // This loop differs from its original form in collectPssInBackground(), as it does not 816 // collect USS or SwapPss (since those are reported in smaps, not status). 817 int num = 0; 818 do { 819 ProcessProfileRecord profile; 820 int procState; 821 int statType; 822 int pid = -1; 823 long lastRssTime; 824 synchronized (mProfilerLock) { 825 if (mPendingPssOrRssProfiles.size() <= 0) { 826 if (mTestPssOrRssMode || DEBUG_RSS) { 827 Slog.d(TAG_RSS, 828 "Collected rss of " + num + " processes in " 829 + (SystemClock.uptimeMillis() - start) + "ms"); 830 } 831 mPendingPssOrRssProfiles.clear(); 832 return; 833 } 834 profile = mPendingPssOrRssProfiles.remove(0); 835 procState = profile.getPssProcState(); 836 statType = profile.getPssStatType(); 837 lastRssTime = profile.getLastPssTime(); 838 long now = SystemClock.uptimeMillis(); 839 if (profile.getThread() != null && procState == profile.getSetProcState() 840 && (lastRssTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) < now) { 841 pid = profile.getPid(); 842 } else { 843 profile.abortNextPssTime(); 844 if (DEBUG_RSS) { 845 Slog.d(TAG_RSS, "Skipped rss collection of " + pid 846 + ": still need " 847 + (lastRssTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE - now) 848 + "ms until safe"); 849 } 850 profile = null; 851 pid = 0; 852 } 853 } 854 if (profile != null) { 855 long startTime = SystemClock.uptimeMillis(); 856 // skip background RSS calculation under the following situations: 857 // - app is capturing camera imagery 858 // - app is frozen and we have already collected RSS once. 859 final boolean skipRSSCollection = 860 (profile.mApp.mOptRecord != null 861 && profile.mApp.mOptRecord.skipPSSCollectionBecauseFrozen()) 862 || mService.isCameraActiveForUid(profile.mApp.uid) 863 || mService.mConstants.APP_PROFILER_PSS_PROFILING_DISABLED; 864 long rss = skipRSSCollection ? 0 : Debug.getRss(pid, null); 865 long endTime = SystemClock.uptimeMillis(); 866 synchronized (mProfilerLock) { 867 if (rss != 0 && profile.getThread() != null 868 && profile.getSetProcState() == procState 869 && profile.getPid() == pid && profile.getLastPssTime() == lastRssTime) { 870 num++; 871 profile.commitNextPssTime(); 872 recordRssSampleLPf(profile, procState, rss, statType, endTime - startTime, 873 SystemClock.uptimeMillis()); 874 } else { 875 profile.abortNextPssTime(); 876 if (DEBUG_RSS) { 877 Slog.d(TAG_RSS, "Skipped rss collection of " + pid 878 + ": " + (profile.getThread() == null ? "NO_THREAD " : "") 879 + (skipRSSCollection ? "SKIP_RSS_COLLECTION " : "") 880 + (profile.getPid() != pid ? "PID_CHANGED " : "") 881 + " initState=" + procState + " curState=" 882 + profile.getSetProcState() + " " 883 + (profile.getLastPssTime() != lastRssTime 884 ? "TIME_CHANGED" : "")); 885 } 886 } 887 } 888 } 889 } while (true); 890 } 891 892 @GuardedBy("mProfilerLock") updateNextPssTimeLPf(int procState, ProcessProfileRecord profile, long now, boolean forceUpdate)893 void updateNextPssTimeLPf(int procState, ProcessProfileRecord profile, long now, 894 boolean forceUpdate) { 895 if (!forceUpdate) { 896 if (now <= profile.getNextPssTime() && now <= Math.max(profile.getLastPssTime() 897 + ProcessList.PSS_MAX_INTERVAL, profile.getLastStateTime() 898 + ProcessList.minTimeFromStateChange(mTestPssOrRssMode))) { 899 // update is not due, ignore it. 900 return; 901 } 902 if (!requestPssLPf(profile, procState)) { 903 return; 904 } 905 } 906 profile.setNextPssTime(profile.computeNextPssTime(procState, 907 mTestPssOrRssMode, mService.mAtmInternal.isSleeping(), now)); 908 } 909 910 /** 911 * Record new PSS sample for a process. 912 */ 913 @GuardedBy("mProfilerLock") recordPssSampleLPf(ProcessProfileRecord profile, int procState, long pss, long uss, long swapPss, long rss, int statType, long pssDuration, long now)914 private void recordPssSampleLPf(ProcessProfileRecord profile, int procState, long pss, long uss, 915 long swapPss, long rss, int statType, long pssDuration, long now) { 916 final ProcessRecord proc = profile.mApp; 917 EventLogTags.writeAmPss( 918 profile.getPid(), proc.uid, proc.processName, pss * 1024, uss * 1024, 919 swapPss * 1024, rss * 1024, statType, procState, pssDuration); 920 profile.setLastPssTime(now); 921 profile.addPss(pss, uss, rss, true, statType, pssDuration); 922 if (DEBUG_PSS) { 923 Slog.d(TAG_PSS, 924 "pss of " + proc.toShortString() + ": " + pss 925 + " lastPss=" + profile.getLastPss() 926 + " state=" + ProcessList.makeProcStateString(procState)); 927 } 928 if (profile.getInitialIdlePssOrRss() == 0) { 929 profile.setInitialIdlePssOrRss(pss); 930 } 931 profile.setLastPss(pss); 932 profile.setLastSwapPss(swapPss); 933 if (procState >= ActivityManager.PROCESS_STATE_HOME) { 934 profile.setLastCachedPss(pss); 935 profile.setLastCachedSwapPss(swapPss); 936 } 937 profile.setLastRss(rss); 938 939 final SparseArray<Pair<Long, String>> watchUids = 940 mMemWatchProcesses.getMap().get(proc.processName); 941 Long check = null; 942 if (watchUids != null) { 943 Pair<Long, String> val = watchUids.get(proc.uid); 944 if (val == null) { 945 val = watchUids.get(0); 946 } 947 if (val != null) { 948 check = val.first; 949 } 950 } 951 if (check != null) { 952 if ((pss * 1024) >= check && profile.getThread() != null 953 && mMemWatchDumpProcName == null) { 954 if (Build.IS_DEBUGGABLE || proc.isDebuggable()) { 955 Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting"); 956 startHeapDumpLPf(profile, false); 957 } else { 958 Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check 959 + ", but debugging not enabled"); 960 } 961 } 962 } 963 } 964 965 /** 966 * Record new RSS sample for a process. 967 * 968 * This method is analogous to recordPssSampleLPf() and is intended to be used as a replacement 969 * if Flags.removeAppProfilerPssCollection() is enabled. Functionally, this differs in that PSS, 970 * SwapPss, and USS are no longer collected and reported. 971 * 972 * This method will also poll PSS if the app has requested that a heap dump be taken if its PSS 973 * reaches some threshold set with ActivityManager.setWatchHeapLimit(). 974 */ 975 @GuardedBy("mProfilerLock") recordRssSampleLPf(ProcessProfileRecord profile, int procState, long rss, int statType, long rssDuration, long now)976 private void recordRssSampleLPf(ProcessProfileRecord profile, int procState, long rss, 977 int statType, long rssDuration, long now) { 978 final ProcessRecord proc = profile.mApp; 979 // TODO(b/296454553): writeAmPss needs to be renamed to writeAmRss, and the zeroed out 980 // fields need to be removed. This will be updated once the flag is fully rolled out to 981 // avoid churn in the .logtags file, which has a mapping of IDs to tags (and is also 982 // technically deprecated). 983 EventLogTags.writeAmPss( 984 profile.getPid(), proc.uid, proc.processName, /* pss = */ 0, /* uss = */ 0, 985 /* swapPss = */ 0, rss * 1024, statType, procState, rssDuration); 986 profile.setLastPssTime(now); 987 // The PSS here is emitted in logs, so we can zero it out instead of subbing in RSS. 988 profile.addPss(/* pss = */ 0, /* uss = */ 0, rss, true, statType, rssDuration); 989 if (DEBUG_RSS) { 990 Slog.d(TAG_RSS, 991 "rss of " + proc.toShortString() + ": " + rss 992 + " lastRss=" + profile.getLastRss() 993 + " state=" + ProcessList.makeProcStateString(procState)); 994 } 995 if (profile.getInitialIdlePssOrRss() == 0) { 996 profile.setInitialIdlePssOrRss(rss); 997 } 998 profile.setLastRss(rss); 999 if (procState >= ActivityManager.PROCESS_STATE_HOME) { 1000 profile.setLastCachedRss(rss); 1001 } 1002 1003 final SparseArray<Pair<Long, String>> watchUids = 1004 mMemWatchProcesses.getMap().get(proc.processName); 1005 Long check = null; 1006 if (watchUids != null) { 1007 Pair<Long, String> val = watchUids.get(proc.uid); 1008 if (val == null) { 1009 val = watchUids.get(0); 1010 } 1011 if (val != null) { 1012 check = val.first; 1013 } 1014 } 1015 1016 if (check != null) { 1017 long pss = Debug.getPss(profile.getPid(), null, null); 1018 if ((pss * 1024) >= check && profile.getThread() != null 1019 && mMemWatchDumpProcName == null) { 1020 if (Build.IS_DEBUGGABLE || proc.isDebuggable()) { 1021 Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting"); 1022 startHeapDumpLPf(profile, false); 1023 } else { 1024 Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check 1025 + ", but debugging not enabled"); 1026 } 1027 } 1028 } 1029 } 1030 1031 private final class RecordPssRunnable implements Runnable { 1032 private final ProcessProfileRecord mProfile; 1033 private final Uri mDumpUri; 1034 private final ContentResolver mContentResolver; 1035 RecordPssRunnable(ProcessProfileRecord profile, Uri dumpUri, ContentResolver contentResolver)1036 RecordPssRunnable(ProcessProfileRecord profile, Uri dumpUri, 1037 ContentResolver contentResolver) { 1038 mProfile = profile; 1039 mDumpUri = dumpUri; 1040 mContentResolver = contentResolver; 1041 } 1042 1043 @Override run()1044 public void run() { 1045 try (ParcelFileDescriptor fd = mContentResolver.openFileDescriptor(mDumpUri, "rw")) { 1046 IApplicationThread thread = mProfile.getThread(); 1047 if (thread != null) { 1048 try { 1049 if (DEBUG_PSS) { 1050 Slog.d(TAG_PSS, "Requesting dump heap from " 1051 + mProfile.mApp + " to " + mDumpUri.getPath()); 1052 } 1053 thread.dumpHeap(/* managed= */ true, 1054 /* mallocInfo= */ false, 1055 /* runGc= */ false, 1056 /* dumpbitmaps= */ null, 1057 mDumpUri.getPath(), fd, 1058 /* finishCallback= */ null); 1059 } catch (RemoteException e) { 1060 } 1061 } 1062 } catch (IOException e) { 1063 Slog.e(TAG, "Failed to dump heap", e); 1064 // Need to clear the heap dump variables, otherwise no further heap dumps will be 1065 // attempted. 1066 abortHeapDump(mProfile.mApp.processName); 1067 } 1068 } 1069 } 1070 1071 @GuardedBy("mProfilerLock") startHeapDumpLPf(ProcessProfileRecord profile, boolean isUserInitiated)1072 void startHeapDumpLPf(ProcessProfileRecord profile, boolean isUserInitiated) { 1073 final ProcessRecord proc = profile.mApp; 1074 mMemWatchDumpProcName = proc.processName; 1075 mMemWatchDumpUri = makeHeapDumpUri(proc.processName); 1076 mMemWatchDumpPid = profile.getPid(); 1077 mMemWatchDumpUid = proc.uid; 1078 mMemWatchIsUserInitiated = isUserInitiated; 1079 Context ctx; 1080 try { 1081 ctx = mService.mContext.createPackageContextAsUser("android", 0, 1082 UserHandle.getUserHandleForUid(mMemWatchDumpUid)); 1083 } catch (NameNotFoundException e) { 1084 throw new RuntimeException("android package not found."); 1085 } 1086 BackgroundThread.getHandler().post( 1087 new RecordPssRunnable(profile, mMemWatchDumpUri, ctx.getContentResolver())); 1088 } 1089 dumpHeapFinished(String path, int callerPid)1090 void dumpHeapFinished(String path, int callerPid) { 1091 synchronized (mProfilerLock) { 1092 if (callerPid != mMemWatchDumpPid) { 1093 Slog.w(TAG, "dumpHeapFinished: Calling pid " + Binder.getCallingPid() 1094 + " does not match last pid " + mMemWatchDumpPid); 1095 return; 1096 } 1097 if (mMemWatchDumpUri == null || !mMemWatchDumpUri.getPath().equals(path)) { 1098 Slog.w(TAG, "dumpHeapFinished: Calling path " + path 1099 + " does not match last path " + mMemWatchDumpUri); 1100 return; 1101 } 1102 if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path); 1103 mService.mHandler.sendEmptyMessage( 1104 ActivityManagerService.POST_DUMP_HEAP_NOTIFICATION_MSG); 1105 1106 // Forced gc to clean up the remnant hprof fd. 1107 Runtime.getRuntime().gc(); 1108 } 1109 } 1110 handlePostDumpHeapNotification()1111 void handlePostDumpHeapNotification() { 1112 final String procName; 1113 final int uid; 1114 final long memLimit; 1115 final String reportPackage; 1116 final boolean isUserInitiated; 1117 synchronized (mProfilerLock) { 1118 uid = mMemWatchDumpUid; 1119 procName = mMemWatchDumpProcName; 1120 Pair<Long, String> val = mMemWatchProcesses.get(procName, uid); 1121 if (val == null) { 1122 val = mMemWatchProcesses.get(procName, 0); 1123 } 1124 if (val != null) { 1125 memLimit = val.first; 1126 reportPackage = val.second; 1127 } else { 1128 memLimit = 0; 1129 reportPackage = null; 1130 } 1131 isUserInitiated = mMemWatchIsUserInitiated; 1132 1133 mMemWatchDumpUri = null; 1134 mMemWatchDumpProcName = null; 1135 mMemWatchDumpPid = -1; 1136 mMemWatchDumpUid = -1; 1137 } 1138 if (procName == null) { 1139 return; 1140 } 1141 1142 if (DEBUG_PSS) { 1143 Slog.d(TAG_PSS, "Showing dump heap notification from " + procName + "/" + uid); 1144 } 1145 1146 Intent dumpFinishedIntent = new Intent(ACTION_HEAP_DUMP_FINISHED); 1147 // Send this only to the Shell package. 1148 dumpFinishedIntent.setPackage("com.android.shell"); 1149 dumpFinishedIntent.putExtra(Intent.EXTRA_UID, uid); 1150 dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_IS_USER_INITIATED, isUserInitiated); 1151 dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_SIZE_BYTES, memLimit); 1152 dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_REPORT_PACKAGE, reportPackage); 1153 dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_PROCESS_NAME, procName); 1154 1155 mService.mContext.sendBroadcastAsUser(dumpFinishedIntent, 1156 UserHandle.getUserHandleForUid(uid)); 1157 } 1158 setDumpHeapDebugLimit(String processName, int uid, long maxMemSize, String reportPackage)1159 void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize, 1160 String reportPackage) { 1161 synchronized (mProfilerLock) { 1162 if (maxMemSize > 0) { 1163 mMemWatchProcesses.put(processName, uid, new Pair(maxMemSize, reportPackage)); 1164 } else { 1165 if (uid != 0) { 1166 mMemWatchProcesses.remove(processName, uid); 1167 } else { 1168 mMemWatchProcesses.getMap().remove(processName); 1169 } 1170 } 1171 } 1172 } 1173 1174 /** Clear the currently executing heap dump variables so a new heap dump can be started. */ abortHeapDump(String procName)1175 private void abortHeapDump(String procName) { 1176 Message msg = mService.mHandler.obtainMessage(ActivityManagerService.ABORT_DUMPHEAP_MSG); 1177 msg.obj = procName; 1178 mService.mHandler.sendMessage(msg); 1179 } 1180 handleAbortDumpHeap(String procName)1181 void handleAbortDumpHeap(String procName) { 1182 if (procName != null) { 1183 synchronized (mProfilerLock) { 1184 if (procName.equals(mMemWatchDumpProcName)) { 1185 mMemWatchDumpProcName = null; 1186 mMemWatchDumpUri = null; 1187 mMemWatchDumpPid = -1; 1188 mMemWatchDumpUid = -1; 1189 } 1190 } 1191 } 1192 } 1193 1194 /** @hide */ makeHeapDumpUri(String procName)1195 private static Uri makeHeapDumpUri(String procName) { 1196 return Uri.parse("content://com.android.shell.heapdump/" + procName + "_javaheap.bin"); 1197 } 1198 1199 /** 1200 * Schedule PSS collection of a process. 1201 */ 1202 @GuardedBy("mProfilerLock") requestPssLPf(ProcessProfileRecord profile, int procState)1203 private boolean requestPssLPf(ProcessProfileRecord profile, int procState) { 1204 if (mPendingPssOrRssProfiles.contains(profile)) { 1205 return false; 1206 } 1207 if (mPendingPssOrRssProfiles.size() == 0) { 1208 final long deferral = (mPssDeferralTime > 0 && mActivityStartingNesting.get() > 0) 1209 ? mPssDeferralTime : 0; 1210 if (DEBUG_PSS && deferral > 0) { 1211 Slog.d(TAG_PSS, "requestPssLPf() deferring PSS request by " 1212 + deferral + " ms"); 1213 } 1214 mBgHandler.sendEmptyMessageDelayed(BgHandler.COLLECT_PSS_BG_MSG, deferral); 1215 } 1216 if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + profile.mApp); 1217 profile.setPssProcState(procState); 1218 profile.setPssStatType(ProcessStats.ADD_PSS_INTERNAL_SINGLE); 1219 mPendingPssOrRssProfiles.add(profile); 1220 return true; 1221 } 1222 1223 /** 1224 * Re-defer a posted PSS collection pass, if one exists. Assumes deferral is 1225 * currently active policy when called. 1226 */ 1227 @GuardedBy("mProfilerLock") deferPssIfNeededLPf()1228 private void deferPssIfNeededLPf() { 1229 if (mPendingPssOrRssProfiles.size() > 0) { 1230 mBgHandler.removeMessages(BgHandler.COLLECT_PSS_BG_MSG); 1231 mBgHandler.sendEmptyMessageDelayed(BgHandler.COLLECT_PSS_BG_MSG, mPssDeferralTime); 1232 } 1233 } 1234 deferPssForActivityStart()1235 private void deferPssForActivityStart() { 1236 if (mPssDeferralTime > 0) { 1237 if (DEBUG_PSS) { 1238 Slog.d(TAG_PSS, "Deferring PSS collection for activity start"); 1239 } 1240 synchronized (mProfilerLock) { 1241 deferPssIfNeededLPf(); 1242 } 1243 mActivityStartingNesting.getAndIncrement(); 1244 mBgHandler.sendEmptyMessageDelayed(BgHandler.STOP_DEFERRING_PSS_MSG, mPssDeferralTime); 1245 } 1246 } 1247 stopDeferPss()1248 private void stopDeferPss() { 1249 final int nesting = mActivityStartingNesting.decrementAndGet(); 1250 if (nesting <= 0) { 1251 if (DEBUG_PSS) { 1252 Slog.d(TAG_PSS, "PSS activity start deferral interval ended; now " 1253 + nesting); 1254 } 1255 if (nesting < 0) { 1256 Slog.wtf(TAG, "Activity start nesting undercount!"); 1257 mActivityStartingNesting.incrementAndGet(); 1258 } 1259 } else { 1260 if (DEBUG_PSS) { 1261 Slog.d(TAG_PSS, "Still deferring PSS, nesting=" + nesting); 1262 } 1263 } 1264 } 1265 1266 /** 1267 * Schedule PSS collection of all processes. 1268 */ 1269 @GuardedBy("mProcLock") requestPssAllProcsLPr(long now, boolean always, boolean memLowered)1270 void requestPssAllProcsLPr(long now, boolean always, boolean memLowered) { 1271 synchronized (mProfilerLock) { 1272 if (!always) { 1273 if (now < (mLastFullPssTime 1274 + (memLowered ? mService.mConstants.FULL_PSS_LOWERED_INTERVAL 1275 : mService.mConstants.FULL_PSS_MIN_INTERVAL))) { 1276 return; 1277 } 1278 } 1279 if (DEBUG_PSS) { 1280 Slog.d(TAG_PSS, "Requesting pss of all procs! memLowered=" + memLowered); 1281 } 1282 mLastFullPssTime = now; 1283 mFullPssOrRssPending = true; 1284 for (int i = mPendingPssOrRssProfiles.size() - 1; i >= 0; i--) { 1285 mPendingPssOrRssProfiles.get(i).abortNextPssTime(); 1286 } 1287 mPendingPssOrRssProfiles.ensureCapacity(mService.mProcessList.getLruSizeLOSP()); 1288 mPendingPssOrRssProfiles.clear(); 1289 mService.mProcessList.forEachLruProcessesLOSP(false, app -> { 1290 final ProcessProfileRecord profile = app.mProfile; 1291 if (profile.getThread() == null 1292 || profile.getSetProcState() == PROCESS_STATE_NONEXISTENT) { 1293 return; 1294 } 1295 final long lastStateTime = profile.getLastStateTime(); 1296 if (memLowered || (always 1297 && now > lastStateTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) 1298 || now > (lastStateTime + ProcessList.PSS_ALL_INTERVAL)) { 1299 profile.setPssProcState(profile.getSetProcState()); 1300 profile.setPssStatType(always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL 1301 : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM); 1302 updateNextPssTimeLPf(profile.getSetProcState(), profile, now, true); 1303 mPendingPssOrRssProfiles.add(profile); 1304 } 1305 }); 1306 if (!mBgHandler.hasMessages(BgHandler.COLLECT_PSS_BG_MSG)) { 1307 mBgHandler.sendEmptyMessage(BgHandler.COLLECT_PSS_BG_MSG); 1308 } 1309 } 1310 } 1311 setTestPssMode(boolean enabled)1312 void setTestPssMode(boolean enabled) { 1313 synchronized (mProcLock) { 1314 mTestPssOrRssMode = enabled; 1315 if (enabled) { 1316 // Whenever we enable the mode, we want to take a snapshot all of current 1317 // process mem use. 1318 requestPssAllProcsLPr(SystemClock.uptimeMillis(), true, true); 1319 } 1320 } 1321 } 1322 getTestPssMode()1323 boolean getTestPssMode() { 1324 return mTestPssOrRssMode; 1325 } 1326 1327 @GuardedBy("mService") getLastMemoryLevelLocked()1328 @MemFactor int getLastMemoryLevelLocked() { 1329 if (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING) { 1330 return mMemFactorOverride; 1331 } 1332 return mLastMemoryLevel; 1333 } 1334 1335 @GuardedBy("mService") isLastMemoryLevelNormal()1336 boolean isLastMemoryLevelNormal() { 1337 if (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING) { 1338 return mMemFactorOverride <= ADJ_MEM_FACTOR_NORMAL; 1339 } 1340 return mLastMemoryLevel <= ADJ_MEM_FACTOR_NORMAL; 1341 } 1342 1343 @GuardedBy("mProcLock") updateLowRamTimestampLPr(long now)1344 void updateLowRamTimestampLPr(long now) { 1345 mLowRamTimeSinceLastIdle = 0; 1346 if (mLowRamStartTime != 0) { 1347 mLowRamStartTime = now; 1348 } 1349 } 1350 1351 @GuardedBy("mService") setAllowLowerMemLevelLocked(boolean allowLowerMemLevel)1352 void setAllowLowerMemLevelLocked(boolean allowLowerMemLevel) { 1353 mAllowLowerMemLevel = allowLowerMemLevel; 1354 } 1355 1356 @GuardedBy("mService") setMemFactorOverrideLocked(@emFactor int factor)1357 void setMemFactorOverrideLocked(@MemFactor int factor) { 1358 mMemFactorOverride = factor; 1359 } 1360 1361 @GuardedBy({"mService", "mProcLock"}) updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming, long now)1362 void updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming, long now) { 1363 int memFactor; 1364 if (mLowMemDetector != null && mLowMemDetector.isAvailable()) { 1365 memFactor = mLowMemDetector.getMemFactor(); 1366 } else { 1367 // Now determine the memory trimming level of background processes. 1368 // Unfortunately we need to start at the back of the list to do this 1369 // properly. We only do this if the number of background apps we 1370 // are managing to keep around is less than half the maximum we desire; 1371 // if we are keeping a good number around, we'll let them use whatever 1372 // memory they want. 1373 if (numCached <= mService.mConstants.CUR_TRIM_CACHED_PROCESSES 1374 && numEmpty <= mService.mConstants.CUR_TRIM_EMPTY_PROCESSES) { 1375 final int numCachedAndEmpty = numCached + numEmpty; 1376 if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) { 1377 memFactor = ADJ_MEM_FACTOR_CRITICAL; 1378 } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) { 1379 memFactor = ADJ_MEM_FACTOR_LOW; 1380 } else { 1381 memFactor = ADJ_MEM_FACTOR_MODERATE; 1382 } 1383 } else { 1384 memFactor = ADJ_MEM_FACTOR_NORMAL; 1385 } 1386 } 1387 // We always allow the memory level to go up (better). We only allow it to go 1388 // down if we are in a state where that is allowed, *and* the total number of processes 1389 // has gone down since last time. 1390 if (DEBUG_OOM_ADJ) { 1391 Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor + " override=" + mMemFactorOverride 1392 + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel 1393 + " numProcs=" + mService.mProcessList.getLruSizeLOSP() 1394 + " last=" + mLastNumProcesses); 1395 } 1396 boolean override; 1397 if (override = (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING)) { 1398 memFactor = mMemFactorOverride; 1399 } 1400 if (memFactor > mLastMemoryLevel) { 1401 if (!override && (!mAllowLowerMemLevel 1402 || mService.mProcessList.getLruSizeLOSP() >= mLastNumProcesses)) { 1403 memFactor = mLastMemoryLevel; 1404 if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!"); 1405 } 1406 } 1407 if (memFactor != mLastMemoryLevel) { 1408 EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel); 1409 FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor); 1410 mBgHandler.obtainMessage(BgHandler.MEMORY_PRESSURE_CHANGED, mLastMemoryLevel, memFactor) 1411 .sendToTarget(); 1412 } 1413 1414 mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked( 1415 numCached + numEmpty, now); 1416 boolean allChanged; 1417 int trackerMemFactor; 1418 synchronized (mService.mProcessStats.mLock) { 1419 allChanged = mService.mProcessStats.setMemFactorLocked(memFactor, 1420 mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(), 1421 SystemClock.uptimeMillis() /* re-acquire the time within the lock */); 1422 trackerMemFactor = mService.mProcessStats.getMemFactorLocked(); 1423 } 1424 1425 mLastMemoryLevel = memFactor; 1426 mLastNumProcesses = mService.mProcessList.getLruSizeLOSP(); 1427 1428 // Dispatch UI_HIDDEN to processes that need it 1429 mService.mProcessList.forEachLruProcessesLOSP( 1430 true, 1431 app -> { 1432 final ProcessProfileRecord profile = app.mProfile; 1433 final IApplicationThread thread; 1434 final ProcessStateRecord state = app.mState; 1435 if (state.hasProcStateChanged()) { 1436 state.setProcStateChanged(false); 1437 } 1438 int procState = app.mState.getCurProcState(); 1439 if (((procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 1440 && procState 1441 < ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) 1442 || app.mState.isSystemNoUi()) 1443 && app.mProfile.hasPendingUiClean()) { 1444 // If this application is now in the background and it 1445 // had done UI, then give it the special trim level to 1446 // have it free UI resources. 1447 if ((thread = app.getThread()) != null) { 1448 try { 1449 thread.scheduleTrimMemory( 1450 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); 1451 app.mProfile.setPendingUiClean(false); 1452 } catch (RemoteException e) { 1453 1454 } 1455 } 1456 } 1457 }); 1458 } 1459 1460 @GuardedBy({"mService", "mProcLock"}) trimMemoryUiHiddenIfNecessaryLSP(ProcessRecord app)1461 private void trimMemoryUiHiddenIfNecessaryLSP(ProcessRecord app) { 1462 if ((app.mState.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 1463 || app.mState.isSystemNoUi()) && app.mProfile.hasPendingUiClean()) { 1464 // If this application is now in the background and it 1465 // had done UI, then give it the special trim level to 1466 // have it free UI resources. 1467 scheduleTrimMemoryLSP(app, ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN, 1468 "Trimming memory of bg-ui "); 1469 app.mProfile.setPendingUiClean(false); 1470 } 1471 } 1472 1473 @GuardedBy({"mService", "mProcLock"}) scheduleTrimMemoryLSP(ProcessRecord app, int level, String msg)1474 private void scheduleTrimMemoryLSP(ProcessRecord app, int level, String msg) { 1475 IApplicationThread thread; 1476 if (app.mProfile.getTrimMemoryLevel() < level && (thread = app.getThread()) != null) { 1477 try { 1478 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) { 1479 Slog.v(TAG_OOM_ADJ, msg + app.processName + " to " + level); 1480 } 1481 mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app, 1482 CachedAppOptimizer.UNFREEZE_REASON_TRIM_MEMORY); 1483 thread.scheduleTrimMemory(level); 1484 } catch (RemoteException e) { 1485 } 1486 } 1487 } 1488 1489 @GuardedBy("mProcLock") getLowRamTimeSinceIdleLPr(long now)1490 long getLowRamTimeSinceIdleLPr(long now) { 1491 return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now - mLowRamStartTime) : 0); 1492 } 1493 1494 /** 1495 * Ask a given process to GC right now. 1496 */ 1497 @GuardedBy("mProfilerLock") performAppGcLPf(ProcessRecord app)1498 private void performAppGcLPf(ProcessRecord app) { 1499 try { 1500 final ProcessProfileRecord profile = app.mProfile; 1501 profile.setLastRequestedGc(SystemClock.uptimeMillis()); 1502 IApplicationThread thread = profile.getThread(); 1503 if (thread != null) { 1504 if (profile.getReportLowMemory()) { 1505 profile.setReportLowMemory(false); 1506 thread.scheduleLowMemory(); 1507 } else { 1508 thread.processInBackground(); 1509 } 1510 } 1511 } catch (Exception e) { 1512 // whatever. 1513 } 1514 } 1515 1516 /** 1517 * Perform GCs on all processes that are waiting for it, but only 1518 * if things are idle. 1519 */ 1520 @GuardedBy("mProfilerLock") performAppGcsLPf()1521 private void performAppGcsLPf() { 1522 if (mProcessesToGc.size() <= 0) { 1523 return; 1524 } 1525 while (mProcessesToGc.size() > 0) { 1526 final ProcessRecord proc = mProcessesToGc.remove(0); 1527 final ProcessProfileRecord profile = proc.mProfile; 1528 if (profile.getCurRawAdj() > ProcessList.PERCEPTIBLE_APP_ADJ 1529 || profile.getReportLowMemory()) { 1530 if ((profile.getLastRequestedGc() + mService.mConstants.GC_MIN_INTERVAL) 1531 <= SystemClock.uptimeMillis()) { 1532 // To avoid spamming the system, we will GC processes one 1533 // at a time, waiting a few seconds between each. 1534 performAppGcLPf(proc); 1535 scheduleAppGcsLPf(); 1536 return; 1537 } else { 1538 // It hasn't been long enough since we last GCed this 1539 // process... put it in the list to wait for its time. 1540 addProcessToGcListLPf(proc); 1541 break; 1542 } 1543 } 1544 } 1545 1546 scheduleAppGcsLPf(); 1547 } 1548 1549 /** 1550 * If all looks good, perform GCs on all processes waiting for them. 1551 */ 1552 @GuardedBy("mService") performAppGcsIfAppropriateLocked()1553 final void performAppGcsIfAppropriateLocked() { 1554 synchronized (mProfilerLock) { 1555 if (mService.canGcNowLocked()) { 1556 performAppGcsLPf(); 1557 return; 1558 } 1559 // Still not idle, wait some more. 1560 scheduleAppGcsLPf(); 1561 } 1562 } 1563 1564 /** 1565 * Schedule the execution of all pending app GCs. 1566 */ 1567 @GuardedBy("mProfilerLock") scheduleAppGcsLPf()1568 final void scheduleAppGcsLPf() { 1569 mService.mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG); 1570 1571 if (mProcessesToGc.size() > 0) { 1572 // Schedule a GC for the time to the next process. 1573 ProcessRecord proc = mProcessesToGc.get(0); 1574 Message msg = mService.mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG); 1575 1576 long when = proc.mProfile.getLastRequestedGc() + mService.mConstants.GC_MIN_INTERVAL; 1577 long now = SystemClock.uptimeMillis(); 1578 if (when < (now + mService.mConstants.GC_TIMEOUT)) { 1579 when = now + mService.mConstants.GC_TIMEOUT; 1580 } 1581 mService.mHandler.sendMessageAtTime(msg, when); 1582 } 1583 } 1584 1585 /** 1586 * Add a process to the array of processes waiting to be GCed. Keeps the 1587 * list in sorted order by the last GC time. The process can't already be 1588 * on the list. 1589 */ 1590 @GuardedBy("mProfilerLock") addProcessToGcListLPf(ProcessRecord proc)1591 private void addProcessToGcListLPf(ProcessRecord proc) { 1592 boolean added = false; 1593 for (int i = mProcessesToGc.size() - 1; i >= 0; i--) { 1594 if (mProcessesToGc.get(i).mProfile.getLastRequestedGc() 1595 < proc.mProfile.getLastRequestedGc()) { 1596 added = true; 1597 mProcessesToGc.add(i + 1, proc); 1598 break; 1599 } 1600 } 1601 if (!added) { 1602 mProcessesToGc.add(0, proc); 1603 } 1604 } 1605 1606 @GuardedBy("mService") doLowMemReportIfNeededLocked(ProcessRecord dyingProc)1607 final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) { 1608 // If there are no longer any background processes running, 1609 // and the app that died was not running instrumentation, 1610 // then tell everyone we are now low on memory. 1611 if (!mService.mProcessList.haveBackgroundProcessLOSP()) { 1612 boolean doReport = Build.IS_DEBUGGABLE; 1613 final long now = SystemClock.uptimeMillis(); 1614 if (doReport) { 1615 if (now < (mLastMemUsageReportTime + 5 * 60 * 1000)) { 1616 doReport = false; 1617 } else { 1618 mLastMemUsageReportTime = now; 1619 } 1620 } 1621 final int lruSize = mService.mProcessList.getLruSizeLOSP(); 1622 final ArrayList<ProcessMemInfo> memInfos = doReport 1623 ? new ArrayList<ProcessMemInfo>(lruSize) : null; 1624 EventLogTags.writeAmLowMemory(lruSize); 1625 mService.mProcessList.forEachLruProcessesLOSP(false, rec -> { 1626 if (rec == dyingProc || rec.getThread() == null) { 1627 return; 1628 } 1629 final ProcessStateRecord state = rec.mState; 1630 if (memInfos != null) { 1631 memInfos.add(new ProcessMemInfo(rec.processName, rec.getPid(), 1632 state.getSetAdj(), state.getSetProcState(), 1633 state.getAdjType(), state.makeAdjReason())); 1634 } 1635 final ProcessProfileRecord profile = rec.mProfile; 1636 if ((profile.getLastLowMemory() + mService.mConstants.GC_MIN_INTERVAL) <= now) { 1637 // The low memory report is overriding any current 1638 // state for a GC request. Make sure to do 1639 // heavy/important/visible/foreground processes first. 1640 synchronized (mProfilerLock) { 1641 if (state.getSetAdj() <= ProcessList.HEAVY_WEIGHT_APP_ADJ) { 1642 profile.setLastRequestedGc(0); 1643 } else { 1644 profile.setLastRequestedGc(profile.getLastLowMemory()); 1645 } 1646 profile.setReportLowMemory(true); 1647 profile.setLastLowMemory(now); 1648 mProcessesToGc.remove(rec); 1649 addProcessToGcListLPf(rec); 1650 } 1651 } 1652 }); 1653 if (doReport) { 1654 Message msg = mService.mHandler.obtainMessage(REPORT_MEM_USAGE_MSG, memInfos); 1655 mService.mHandler.sendMessage(msg); 1656 } 1657 } 1658 synchronized (mProfilerLock) { 1659 scheduleAppGcsLPf(); 1660 } 1661 } 1662 reportMemUsage(ArrayList<ProcessMemInfo> memInfos)1663 void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) { 1664 final SparseArray<ProcessMemInfo> infoMap = new SparseArray<>(memInfos.size()); 1665 for (int i = 0, size = memInfos.size(); i < size; i++) { 1666 ProcessMemInfo mi = memInfos.get(i); 1667 infoMap.put(mi.pid, mi); 1668 } 1669 updateCpuStatsNow(); 1670 long[] memtrackTmp = new long[4]; 1671 long[] swaptrackTmp = new long[2]; 1672 // Get a list of Stats that have vsize > 0 1673 final List<ProcessCpuTracker.Stats> stats = getCpuStats(st -> st.vsize > 0); 1674 final int statsCount = stats.size(); 1675 long totalMemtrackGraphics = 0; 1676 long totalMemtrackGl = 0; 1677 for (int i = 0; i < statsCount; i++) { 1678 ProcessCpuTracker.Stats st = stats.get(i); 1679 long pss = Debug.getPss(st.pid, swaptrackTmp, memtrackTmp); 1680 if (pss > 0) { 1681 if (infoMap.indexOfKey(st.pid) < 0) { 1682 ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid, 1683 ProcessList.NATIVE_ADJ, -1, "native", null); 1684 mi.pss = pss; 1685 mi.swapPss = swaptrackTmp[1]; 1686 mi.memtrack = memtrackTmp[0]; 1687 totalMemtrackGraphics += memtrackTmp[1]; 1688 totalMemtrackGl += memtrackTmp[2]; 1689 memInfos.add(mi); 1690 } 1691 } 1692 } 1693 1694 long totalPss = 0; 1695 long totalSwapPss = 0; 1696 long totalMemtrack = 0; 1697 for (int i = 0, size = memInfos.size(); i < size; i++) { 1698 ProcessMemInfo mi = memInfos.get(i); 1699 if (mi.pss == 0) { 1700 mi.pss = Debug.getPss(mi.pid, swaptrackTmp, memtrackTmp); 1701 mi.swapPss = swaptrackTmp[1]; 1702 mi.memtrack = memtrackTmp[0]; 1703 totalMemtrackGraphics += memtrackTmp[1]; 1704 totalMemtrackGl += memtrackTmp[2]; 1705 } 1706 totalPss += mi.pss; 1707 totalSwapPss += mi.swapPss; 1708 totalMemtrack += mi.memtrack; 1709 } 1710 Collections.sort(memInfos, new Comparator<ProcessMemInfo>() { 1711 @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) { 1712 if (lhs.oomAdj != rhs.oomAdj) { 1713 return lhs.oomAdj < rhs.oomAdj ? -1 : 1; 1714 } 1715 if (lhs.pss != rhs.pss) { 1716 return lhs.pss < rhs.pss ? 1 : -1; 1717 } 1718 return 0; 1719 } 1720 }); 1721 1722 StringBuilder tag = new StringBuilder(128); 1723 StringBuilder stack = new StringBuilder(128); 1724 tag.append("Low on memory -- "); 1725 appendMemBucket(tag, totalPss, "total", false); 1726 appendMemBucket(stack, totalPss, "total", true); 1727 1728 StringBuilder fullNativeBuilder = new StringBuilder(1024); 1729 StringBuilder shortNativeBuilder = new StringBuilder(1024); 1730 StringBuilder fullJavaBuilder = new StringBuilder(1024); 1731 1732 boolean firstLine = true; 1733 int lastOomAdj = Integer.MIN_VALUE; 1734 long extraNativeRam = 0; 1735 long extraNativeMemtrack = 0; 1736 long cachedPss = 0; 1737 for (int i = 0, size = memInfos.size(); i < size; i++) { 1738 ProcessMemInfo mi = memInfos.get(i); 1739 1740 if (mi.oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) { 1741 cachedPss += mi.pss; 1742 } 1743 1744 if (mi.oomAdj != ProcessList.NATIVE_ADJ 1745 && (mi.oomAdj < ProcessList.SERVICE_ADJ 1746 || mi.oomAdj == ProcessList.HOME_APP_ADJ 1747 || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) { 1748 if (lastOomAdj != mi.oomAdj) { 1749 lastOomAdj = mi.oomAdj; 1750 if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) { 1751 tag.append(" / "); 1752 } 1753 if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) { 1754 if (firstLine) { 1755 stack.append(":"); 1756 firstLine = false; 1757 } 1758 stack.append("\n\t at "); 1759 } else { 1760 stack.append("$"); 1761 } 1762 } else { 1763 tag.append(" "); 1764 stack.append("$"); 1765 } 1766 if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) { 1767 appendMemBucket(tag, mi.pss, mi.name, false); 1768 } 1769 appendMemBucket(stack, mi.pss, mi.name, true); 1770 if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ 1771 && ((i + 1) >= size || memInfos.get(i + 1).oomAdj != lastOomAdj)) { 1772 stack.append("("); 1773 for (int k = 0; k < DUMP_MEM_OOM_ADJ.length; k++) { 1774 if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) { 1775 stack.append(DUMP_MEM_OOM_LABEL[k]); 1776 stack.append(":"); 1777 stack.append(DUMP_MEM_OOM_ADJ[k]); 1778 } 1779 } 1780 stack.append(")"); 1781 } 1782 } 1783 1784 appendMemInfo(fullNativeBuilder, mi); 1785 if (mi.oomAdj == ProcessList.NATIVE_ADJ) { 1786 // The short form only has native processes that are >= 512K. 1787 if (mi.pss >= 512) { 1788 appendMemInfo(shortNativeBuilder, mi); 1789 } else { 1790 extraNativeRam += mi.pss; 1791 extraNativeMemtrack += mi.memtrack; 1792 } 1793 } else { 1794 // Short form has all other details, but if we have collected RAM 1795 // from smaller native processes let's dump a summary of that. 1796 if (extraNativeRam > 0) { 1797 appendBasicMemEntry(shortNativeBuilder, ProcessList.NATIVE_ADJ, 1798 -1, extraNativeRam, extraNativeMemtrack, "(Other native)"); 1799 shortNativeBuilder.append('\n'); 1800 extraNativeRam = 0; 1801 } 1802 appendMemInfo(fullJavaBuilder, mi); 1803 } 1804 } 1805 1806 fullJavaBuilder.append(" "); 1807 ProcessList.appendRamKb(fullJavaBuilder, totalPss); 1808 fullJavaBuilder.append(": TOTAL"); 1809 if (totalMemtrack > 0) { 1810 fullJavaBuilder.append(" ("); 1811 fullJavaBuilder.append(stringifyKBSize(totalMemtrack)); 1812 fullJavaBuilder.append(" memtrack)"); 1813 } 1814 fullJavaBuilder.append("\n"); 1815 1816 MemInfoReader memInfo = new MemInfoReader(); 1817 memInfo.readMemInfo(); 1818 final long[] infos = memInfo.getRawInfo(); 1819 1820 StringBuilder memInfoBuilder = new StringBuilder(1024); 1821 Debug.getMemInfo(infos); 1822 memInfoBuilder.append(" MemInfo: "); 1823 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SLAB])).append(" slab, "); 1824 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SHMEM])).append(" shmem, "); 1825 memInfoBuilder.append(stringifyKBSize( 1826 infos[Debug.MEMINFO_VM_ALLOC_USED])).append(" vm alloc, "); 1827 memInfoBuilder.append(stringifyKBSize( 1828 infos[Debug.MEMINFO_PAGE_TABLES])).append(" page tables "); 1829 memInfoBuilder.append(stringifyKBSize( 1830 infos[Debug.MEMINFO_KERNEL_STACK])).append(" kernel stack\n"); 1831 memInfoBuilder.append(" "); 1832 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_BUFFERS])).append(" buffers, "); 1833 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_CACHED])).append(" cached, "); 1834 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_MAPPED])).append(" mapped, "); 1835 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_FREE])).append(" free\n"); 1836 if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) { 1837 memInfoBuilder.append(" ZRAM: "); 1838 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_ZRAM_TOTAL])); 1839 memInfoBuilder.append(" RAM, "); 1840 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SWAP_TOTAL])); 1841 memInfoBuilder.append(" swap total, "); 1842 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SWAP_FREE])); 1843 memInfoBuilder.append(" swap free\n"); 1844 } 1845 final long[] ksm = getKsmInfo(); 1846 if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0 1847 || ksm[KSM_VOLATILE] != 0) { 1848 memInfoBuilder.append(" KSM: "); 1849 memInfoBuilder.append(stringifyKBSize(ksm[KSM_SHARING])); 1850 memInfoBuilder.append(" saved from shared "); 1851 memInfoBuilder.append(stringifyKBSize(ksm[KSM_SHARED])); 1852 memInfoBuilder.append("\n "); 1853 memInfoBuilder.append(stringifyKBSize(ksm[KSM_UNSHARED])); 1854 memInfoBuilder.append(" unshared; "); 1855 memInfoBuilder.append(stringifyKBSize(ksm[KSM_VOLATILE])); 1856 memInfoBuilder.append(" volatile\n"); 1857 } 1858 memInfoBuilder.append(" Free RAM: "); 1859 memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb() 1860 + memInfo.getFreeSizeKb())); 1861 memInfoBuilder.append("\n"); 1862 long kernelUsed = memInfo.getKernelUsedSizeKb(); 1863 final long ionHeap = Debug.getIonHeapsSizeKb(); 1864 final long ionPool = Debug.getIonPoolsSizeKb(); 1865 final long dmabufMapped = Debug.getDmabufMappedSizeKb(); 1866 if (ionHeap >= 0 && ionPool >= 0) { 1867 final long ionUnmapped = ionHeap - dmabufMapped; 1868 memInfoBuilder.append(" ION: "); 1869 memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool)); 1870 memInfoBuilder.append("\n"); 1871 kernelUsed += ionUnmapped; 1872 // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being 1873 // set on ION VMAs, however it might be included by the memtrack HAL. 1874 // Replace memtrack HAL reported Graphics category with mapped dmabufs 1875 totalPss -= totalMemtrackGraphics; 1876 totalPss += dmabufMapped; 1877 } else { 1878 final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb(); 1879 if (totalExportedDmabuf >= 0) { 1880 final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped; 1881 memInfoBuilder.append("DMA-BUF: "); 1882 memInfoBuilder.append(stringifyKBSize(totalExportedDmabuf)); 1883 memInfoBuilder.append("\n"); 1884 // Account unmapped dmabufs as part of kernel memory allocations 1885 kernelUsed += dmabufUnmapped; 1886 // Replace memtrack HAL reported Graphics category with mapped dmabufs 1887 totalPss -= totalMemtrackGraphics; 1888 totalPss += dmabufMapped; 1889 } 1890 // These are included in the totalExportedDmabuf above and hence do not need to be added 1891 // to kernelUsed. 1892 final long totalExportedDmabufHeap = Debug.getDmabufHeapTotalExportedKb(); 1893 if (totalExportedDmabufHeap >= 0) { 1894 memInfoBuilder.append("DMA-BUF Heap: "); 1895 memInfoBuilder.append(stringifyKBSize(totalExportedDmabufHeap)); 1896 memInfoBuilder.append("\n"); 1897 } 1898 1899 final long totalDmabufHeapPool = Debug.getDmabufHeapPoolsSizeKb(); 1900 if (totalDmabufHeapPool >= 0) { 1901 memInfoBuilder.append("DMA-BUF Heaps pool: "); 1902 memInfoBuilder.append(stringifyKBSize(totalDmabufHeapPool)); 1903 memInfoBuilder.append("\n"); 1904 } 1905 } 1906 1907 final long gpuUsage = Debug.getGpuTotalUsageKb(); 1908 if (gpuUsage >= 0) { 1909 final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb(); 1910 if (gpuPrivateUsage >= 0) { 1911 final long gpuDmaBufUsage = gpuUsage - gpuPrivateUsage; 1912 memInfoBuilder.append(" GPU: "); 1913 memInfoBuilder.append(stringifyKBSize(gpuUsage)); 1914 memInfoBuilder.append(" ("); 1915 memInfoBuilder.append(stringifyKBSize(gpuDmaBufUsage)); 1916 memInfoBuilder.append(" dmabuf + "); 1917 memInfoBuilder.append(stringifyKBSize(gpuPrivateUsage)); 1918 memInfoBuilder.append(" private)\n"); 1919 // Replace memtrack HAL reported GL category with private GPU allocations and 1920 // account it as part of kernel memory allocations 1921 totalPss -= totalMemtrackGl; 1922 kernelUsed += gpuPrivateUsage; 1923 } else { 1924 memInfoBuilder.append(" GPU: "); 1925 memInfoBuilder.append(stringifyKBSize(gpuUsage)); 1926 memInfoBuilder.append("\n"); 1927 } 1928 1929 } 1930 memInfoBuilder.append(" Used RAM: "); 1931 memInfoBuilder.append(stringifyKBSize( 1932 totalPss - cachedPss + kernelUsed)); 1933 memInfoBuilder.append("\n"); 1934 1935 // Note: ION/DMA-BUF heap pools are reclaimable and hence, they are included as part of 1936 // memInfo.getCachedSizeKb(). 1937 memInfoBuilder.append(" Lost RAM: "); 1938 memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb() 1939 - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() 1940 - kernelUsed - memInfo.getZramTotalSizeKb())); 1941 memInfoBuilder.append("\n"); 1942 Slog.i(TAG, "Low on memory:"); 1943 Slog.i(TAG, shortNativeBuilder.toString()); 1944 Slog.i(TAG, fullJavaBuilder.toString()); 1945 Slog.i(TAG, memInfoBuilder.toString()); 1946 1947 StringBuilder dropBuilder = new StringBuilder(1024); 1948 dropBuilder.append("Low on memory:"); 1949 dropBuilder.append(stack); 1950 dropBuilder.append('\n'); 1951 dropBuilder.append(fullNativeBuilder); 1952 dropBuilder.append(fullJavaBuilder); 1953 dropBuilder.append('\n'); 1954 dropBuilder.append(memInfoBuilder); 1955 dropBuilder.append('\n'); 1956 StringWriter catSw = new StringWriter(); 1957 synchronized (mService) { 1958 PrintWriter catPw = new FastPrintWriter(catSw, false, 256); 1959 String[] emptyArgs = new String[] { }; 1960 catPw.println(); 1961 synchronized (mProcLock) { 1962 mService.mProcessList.dumpProcessesLSP(null, catPw, emptyArgs, 0, false, null, -1); 1963 } 1964 catPw.println(); 1965 mService.mServices.newServiceDumperLocked(null, catPw, emptyArgs, 0, 1966 false, null).dumpLocked(); 1967 catPw.println(); 1968 mService.mAtmInternal.dump(DUMP_ACTIVITIES_CMD, null, catPw, emptyArgs, 0, false, false, 1969 null, INVALID_DISPLAY); 1970 catPw.flush(); 1971 } 1972 dropBuilder.append(catSw.toString()); 1973 FrameworkStatsLog.write(FrameworkStatsLog.LOW_MEM_REPORTED); 1974 mService.addErrorToDropBox("lowmem", null, "system_server", null, 1975 null, null, tag.toString(), dropBuilder.toString(), null, null, null, null, null, 1976 null); 1977 synchronized (mService) { 1978 long now = SystemClock.uptimeMillis(); 1979 if (mLastMemUsageReportTime < now) { 1980 mLastMemUsageReportTime = now; 1981 } 1982 } 1983 } 1984 1985 @GuardedBy("mService") handleMemoryPressureChangedLocked(@emFactor int oldMemFactor, @MemFactor int newMemFactor)1986 private void handleMemoryPressureChangedLocked(@MemFactor int oldMemFactor, 1987 @MemFactor int newMemFactor) { 1988 mService.mServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked( 1989 oldMemFactor, newMemFactor, "mem-pressure-event", SystemClock.uptimeMillis()); 1990 } 1991 1992 @GuardedBy("mProfilerLock") stopProfilerLPf(ProcessRecord proc, int profileType)1993 private void stopProfilerLPf(ProcessRecord proc, int profileType) { 1994 if (proc == null || proc == mProfileData.getProfileProc()) { 1995 proc = mProfileData.getProfileProc(); 1996 profileType = mProfileType; 1997 clearProfilerLPf(); 1998 } 1999 if (proc == null) { 2000 return; 2001 } 2002 final IApplicationThread thread = proc.mProfile.getThread(); 2003 if (thread == null) { 2004 return; 2005 } 2006 try { 2007 thread.profilerControl(false, null, profileType); 2008 } catch (RemoteException e) { 2009 throw new IllegalStateException("Process disappeared"); 2010 } 2011 } 2012 2013 @GuardedBy("mProfilerLock") clearProfilerLPf()2014 void clearProfilerLPf() { 2015 if (mProfileData.getProfilerInfo() != null 2016 && mProfileData.getProfilerInfo().profileFd != null) { 2017 try { 2018 mProfileData.getProfilerInfo().profileFd.close(); 2019 } catch (IOException e) { 2020 } 2021 } 2022 mProfileData.setProfileApp(null); 2023 mProfileData.setProfileProc(null); 2024 mProfileData.setProfilerInfo(null); 2025 } 2026 2027 @GuardedBy("mProfilerLock") clearProfilerLPf(ProcessRecord app)2028 void clearProfilerLPf(ProcessRecord app) { 2029 if (mProfileData.getProfileProc() == null 2030 || mProfileData.getProfilerInfo() == null 2031 || mProfileData.getProfileProc() != app) { 2032 return; 2033 } 2034 clearProfilerLPf(); 2035 } 2036 2037 @GuardedBy("mProfilerLock") profileControlLPf(ProcessRecord proc, boolean start, ProfilerInfo profilerInfo, int profileType)2038 boolean profileControlLPf(ProcessRecord proc, boolean start, 2039 ProfilerInfo profilerInfo, int profileType) { 2040 try { 2041 if (start) { 2042 stopProfilerLPf(null, 0); 2043 mService.setProfileApp(proc.info, proc.processName, profilerInfo, 2044 proc.isSdkSandbox ? proc.getClientInfoForSdkSandbox() : null); 2045 mProfileData.setProfileProc(proc); 2046 mProfileType = profileType; 2047 ParcelFileDescriptor fd = profilerInfo.profileFd; 2048 try { 2049 fd = fd.dup(); 2050 } catch (IOException e) { 2051 fd = null; 2052 } 2053 profilerInfo.profileFd = fd; 2054 proc.mProfile.getThread().profilerControl(start, profilerInfo, profileType); 2055 fd = null; 2056 try { 2057 mProfileData.getProfilerInfo().profileFd.close(); 2058 } catch (IOException e) { 2059 } 2060 mProfileData.getProfilerInfo().profileFd = null; 2061 2062 if (proc.getPid() == mService.MY_PID) { 2063 // When profiling the system server itself, avoid closing the file 2064 // descriptor, as profilerControl will not create a copy. 2065 // Note: it is also not correct to just set profileFd to null, as the 2066 // whole ProfilerInfo instance is passed down! 2067 profilerInfo = null; 2068 } 2069 } else { 2070 stopProfilerLPf(proc, profileType); 2071 if (profilerInfo != null && profilerInfo.profileFd != null) { 2072 try { 2073 profilerInfo.profileFd.close(); 2074 } catch (IOException e) { 2075 } 2076 } 2077 } 2078 2079 return true; 2080 } catch (RemoteException e) { 2081 throw new IllegalStateException("Process disappeared"); 2082 } finally { 2083 if (profilerInfo != null && profilerInfo.profileFd != null) { 2084 try { 2085 profilerInfo.profileFd.close(); 2086 } catch (IOException e) { 2087 } 2088 } 2089 } 2090 } 2091 2092 @GuardedBy("mProfilerLock") setProfileAppLPf(String processName, ProfilerInfo profilerInfo)2093 void setProfileAppLPf(String processName, ProfilerInfo profilerInfo) { 2094 mProfileData.setProfileApp(processName); 2095 2096 if (mProfileData.getProfilerInfo() != null) { 2097 if (mProfileData.getProfilerInfo().profileFd != null) { 2098 try { 2099 mProfileData.getProfilerInfo().profileFd.close(); 2100 } catch (IOException e) { 2101 } 2102 } 2103 } 2104 mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo)); 2105 mProfileType = 0; 2106 } 2107 2108 @GuardedBy("mProfilerLock") setProfileProcLPf(ProcessRecord proc)2109 void setProfileProcLPf(ProcessRecord proc) { 2110 mProfileData.setProfileProc(proc); 2111 } 2112 2113 @GuardedBy("mProfilerLock") setAgentAppLPf(@onNull String packageName, @Nullable String agent)2114 void setAgentAppLPf(@NonNull String packageName, @Nullable String agent) { 2115 if (agent == null) { 2116 if (mAppAgentMap != null) { 2117 mAppAgentMap.remove(packageName); 2118 if (mAppAgentMap.isEmpty()) { 2119 mAppAgentMap = null; 2120 } 2121 } 2122 } else { 2123 if (mAppAgentMap == null) { 2124 mAppAgentMap = new HashMap<>(); 2125 } 2126 if (mAppAgentMap.size() >= 100) { 2127 // Limit the size of the map, to avoid OOMEs. 2128 Slog.e(TAG, "App agent map has too many entries, cannot add " + packageName 2129 + "/" + agent); 2130 return; 2131 } 2132 mAppAgentMap.put(packageName, agent); 2133 } 2134 } 2135 updateCpuStats()2136 void updateCpuStats() { 2137 final long now = SystemClock.uptimeMillis(); 2138 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) { 2139 return; 2140 } 2141 if (mProcessCpuMutexFree.compareAndSet(true, false)) { 2142 synchronized (mProcessCpuThread) { 2143 mProcessCpuThread.notify(); 2144 } 2145 } 2146 } 2147 updateCpuStatsNow()2148 void updateCpuStatsNow() { 2149 final boolean monitorPhantomProcs = mService.mSystemReady && FeatureFlagUtils.isEnabled( 2150 mService.mContext, SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS); 2151 synchronized (mProcessCpuTracker) { 2152 mProcessCpuMutexFree.set(false); 2153 final long now = SystemClock.uptimeMillis(); 2154 boolean haveNewCpuStats = false; 2155 2156 if (MONITOR_CPU_USAGE 2157 && mLastCpuTime.get() < (now - MONITOR_CPU_MIN_TIME)) { 2158 mLastCpuTime.set(now); 2159 mProcessCpuTracker.update(); 2160 if (mProcessCpuTracker.hasGoodLastStats()) { 2161 haveNewCpuStats = true; 2162 //Slog.i(TAG, mProcessCpu.printCurrentState()); 2163 //Slog.i(TAG, "Total CPU usage: " 2164 // + mProcessCpu.getTotalCpuPercent() + "%"); 2165 2166 // Slog the cpu usage if the property is set. 2167 if ("true".equals(SystemProperties.get("events.cpu"))) { 2168 int user = mProcessCpuTracker.getLastUserTime(); 2169 int system = mProcessCpuTracker.getLastSystemTime(); 2170 int iowait = mProcessCpuTracker.getLastIoWaitTime(); 2171 int irq = mProcessCpuTracker.getLastIrqTime(); 2172 int softIrq = mProcessCpuTracker.getLastSoftIrqTime(); 2173 int idle = mProcessCpuTracker.getLastIdleTime(); 2174 2175 int total = user + system + iowait + irq + softIrq + idle; 2176 if (total == 0) total = 1; 2177 2178 EventLogTags.writeCpu( 2179 ((user + system + iowait + irq + softIrq) * 100) / total, 2180 (user * 100) / total, 2181 (system * 100) / total, 2182 (iowait * 100) / total, 2183 (irq * 100) / total, 2184 (softIrq * 100) / total); 2185 } 2186 } 2187 } 2188 2189 if (monitorPhantomProcs && haveNewCpuStats) { 2190 mService.mPhantomProcessList.updateProcessCpuStatesLocked(mProcessCpuTracker); 2191 } 2192 2193 final BatteryStatsImpl bstats = mService.mBatteryStatsService.getActiveStatistics(); 2194 synchronized (bstats) { 2195 if (haveNewCpuStats) { 2196 if (bstats.startAddingCpuStatsLocked()) { 2197 int totalUTime = 0; 2198 int totalSTime = 0; 2199 final int statsCount = mProcessCpuTracker.countStats(); 2200 final long elapsedRealtime = SystemClock.elapsedRealtime(); 2201 final long uptime = SystemClock.uptimeMillis(); 2202 synchronized (mService.mPidsSelfLocked) { 2203 for (int i = 0; i < statsCount; i++) { 2204 ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); 2205 if (!st.working) { 2206 continue; 2207 } 2208 ProcessRecord pr = mService.mPidsSelfLocked.get(st.pid); 2209 totalUTime += st.rel_utime; 2210 totalSTime += st.rel_stime; 2211 if (pr != null) { 2212 final ProcessProfileRecord profile = pr.mProfile; 2213 BatteryStatsImpl.Uid.Proc ps = profile.getCurProcBatteryStats(); 2214 if (ps == null || !ps.isActive()) { 2215 profile.setCurProcBatteryStats( 2216 ps = bstats.getProcessStatsLocked( 2217 pr.info.uid, pr.processName, 2218 elapsedRealtime, uptime)); 2219 } 2220 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); 2221 final long curCpuTime = profile.mCurCpuTime.addAndGet( 2222 st.rel_utime + st.rel_stime); 2223 profile.mLastCpuTime.compareAndSet(0, curCpuTime); 2224 } else { 2225 BatteryStatsImpl.Uid.Proc ps = 2226 (BatteryStatsImpl.Uid.Proc) st.batteryStats; 2227 if (ps == null || !ps.isActive()) { 2228 st.batteryStats = ps = bstats.getProcessStatsLocked( 2229 st.uid, st.name, elapsedRealtime, uptime); 2230 } 2231 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); 2232 } 2233 EventLogTags.writeAmCpu(st.pid, st.uid, st.baseName, 2234 st.rel_uptime, st.rel_utime, st.rel_stime); 2235 } 2236 } 2237 2238 final int userTime = mProcessCpuTracker.getLastUserTime(); 2239 final int systemTime = mProcessCpuTracker.getLastSystemTime(); 2240 final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime(); 2241 final int irqTime = mProcessCpuTracker.getLastIrqTime(); 2242 final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); 2243 final int idleTime = mProcessCpuTracker.getLastIdleTime(); 2244 bstats.addCpuStatsLocked(totalUTime, totalSTime, userTime, 2245 systemTime, iowaitTime, irqTime, softIrqTime, idleTime); 2246 } 2247 bstats.finishAddingCpuStatsLocked(); 2248 } 2249 2250 if (mLastWriteTime < (now - BATTERY_STATS_TIME)) { 2251 mLastWriteTime = now; 2252 mService.mBatteryStatsService.scheduleWriteToDisk(); 2253 } 2254 } 2255 } 2256 } 2257 getCpuTimeForPid(int pid)2258 long getCpuTimeForPid(int pid) { 2259 return mProcessCpuTracker.getCpuTimeForPid(pid); 2260 } 2261 getCpuDelayTimeForPid(int pid)2262 long getCpuDelayTimeForPid(int pid) { 2263 return mProcessCpuTracker.getCpuDelayTimeForPid(pid); 2264 } 2265 getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate)2266 List<ProcessCpuTracker.Stats> getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate) { 2267 synchronized (mProcessCpuTracker) { 2268 return mProcessCpuTracker.getStats(st -> predicate.test(st)); 2269 } 2270 } 2271 forAllCpuStats(Consumer<ProcessCpuTracker.Stats> consumer)2272 void forAllCpuStats(Consumer<ProcessCpuTracker.Stats> consumer) { 2273 synchronized (mProcessCpuTracker) { 2274 final int numOfStats = mProcessCpuTracker.countStats(); 2275 for (int i = 0; i < numOfStats; i++) { 2276 consumer.accept(mProcessCpuTracker.getStats(i)); 2277 } 2278 } 2279 } 2280 2281 private class ProcessCpuThread extends Thread { ProcessCpuThread(String name)2282 ProcessCpuThread(String name) { 2283 super(name); 2284 } 2285 2286 @Override run()2287 public void run() { 2288 synchronized (mProcessCpuTracker) { 2289 mProcessCpuInitLatch.countDown(); 2290 mProcessCpuTracker.init(); 2291 } 2292 while (true) { 2293 try { 2294 try { 2295 synchronized (this) { 2296 final long now = SystemClock.uptimeMillis(); 2297 long nextCpuDelay = (mLastCpuTime.get() + MONITOR_CPU_MAX_TIME) - now; 2298 long nextWriteDelay = (mLastWriteTime + BATTERY_STATS_TIME) - now; 2299 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay 2300 // + ", write delay=" + nextWriteDelay); 2301 if (nextWriteDelay < nextCpuDelay) { 2302 nextCpuDelay = nextWriteDelay; 2303 } 2304 if (nextCpuDelay > 0) { 2305 mProcessCpuMutexFree.set(true); 2306 this.wait(nextCpuDelay); 2307 } 2308 } 2309 } catch (InterruptedException e) { 2310 } 2311 updateCpuStatsNow(); 2312 } catch (Exception e) { 2313 Slog.e(TAG, "Unexpected exception collecting process stats", e); 2314 } 2315 } 2316 } 2317 } 2318 2319 class CpuBinder extends Binder { 2320 private final PriorityDump.PriorityDumper mPriorityDumper = 2321 new PriorityDump.PriorityDumper() { 2322 @Override 2323 public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, 2324 boolean asProto) { 2325 if (!DumpUtils.checkDumpAndUsageStatsPermission(mService.mContext, "cpuinfo", pw)) { 2326 return; 2327 } 2328 synchronized (mProcessCpuTracker) { 2329 if (asProto) { 2330 mProcessCpuTracker.dumpProto(fd); 2331 return; 2332 } 2333 pw.print(mProcessCpuTracker.printCurrentLoad()); 2334 pw.print(mProcessCpuTracker.printCurrentState( 2335 SystemClock.uptimeMillis())); 2336 } 2337 } 2338 }; 2339 2340 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2341 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2342 PriorityDump.dump(mPriorityDumper, fd, pw, args); 2343 } 2344 } 2345 setCpuInfoService()2346 void setCpuInfoService() { 2347 if (MONITOR_CPU_USAGE) { 2348 ServiceManager.addService("cpuinfo", new CpuBinder(), 2349 /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); 2350 } 2351 } 2352 AppProfiler(ActivityManagerService service, Looper bgLooper, LowMemDetector detector)2353 AppProfiler(ActivityManagerService service, Looper bgLooper, LowMemDetector detector) { 2354 mService = service; 2355 mProcLock = service.mProcLock; 2356 mBgHandler = new BgHandler(bgLooper); 2357 mLowMemDetector = detector; 2358 mProcessCpuThread = new ProcessCpuThread("CpuTracker"); 2359 } 2360 retrieveSettings()2361 void retrieveSettings() { 2362 final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 2363 ACTIVITY_START_PSS_DEFER_CONFIG, 0L); 2364 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 2365 ActivityThread.currentApplication().getMainExecutor(), 2366 mPssDelayConfigListener); 2367 mPssDeferralTime = pssDeferralMs; 2368 } 2369 onActivityManagerInternalAdded()2370 void onActivityManagerInternalAdded() { 2371 mProcessCpuThread.start(); 2372 // Wait for the synchronized block started in mProcessCpuThread, 2373 // so that any other access to mProcessCpuTracker from main thread 2374 // will be blocked during mProcessCpuTracker initialization. 2375 try { 2376 mProcessCpuInitLatch.await(); 2377 } catch (InterruptedException e) { 2378 Slog.wtf(TAG, "Interrupted wait during start", e); 2379 Thread.currentThread().interrupt(); 2380 throw new IllegalStateException("Interrupted wait during start"); 2381 } 2382 } 2383 onActivityLaunched()2384 void onActivityLaunched() { 2385 // This is safe to force to the head of the queue because it relies only 2386 // on refcounting to track begin/end of deferrals, not on actual 2387 // message ordering. We don't care *what* activity is being 2388 // launched; only that we're doing so. 2389 if (mPssDeferralTime > 0) { 2390 final Message msg = mBgHandler.obtainMessage(BgHandler.DEFER_PSS_MSG); 2391 mBgHandler.sendMessageAtFrontOfQueue(msg); 2392 } 2393 } 2394 2395 @GuardedBy("mService") setupProfilerInfoLocked(@onNull IApplicationThread thread, ProcessRecord app, ActiveInstrumentation instr)2396 ProfilerInfo setupProfilerInfoLocked(@NonNull IApplicationThread thread, ProcessRecord app, 2397 ActiveInstrumentation instr) throws IOException, RemoteException { 2398 ProfilerInfo profilerInfo = null; 2399 String preBindAgent = null; 2400 final String processName = app.processName; 2401 synchronized (mProfilerLock) { 2402 if (mProfileData.getProfileApp() != null 2403 && mProfileData.getProfileApp().equals(processName)) { 2404 mProfileData.setProfileProc(app); 2405 if (mProfileData.getProfilerInfo() != null) { 2406 // Send a profiler info object to the app if either a file is given, or 2407 // an agent should be loaded at bind-time. 2408 boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null 2409 || mProfileData.getProfilerInfo().attachAgentDuringBind; 2410 profilerInfo = needsInfo 2411 ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null; 2412 if (mProfileData.getProfilerInfo().agent != null) { 2413 preBindAgent = mProfileData.getProfilerInfo().agent; 2414 } 2415 } 2416 } else if (instr != null && instr.mProfileFile != null) { 2417 profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false, null, 2418 false, 0, ProfilerInfo.OUTPUT_VERSION_DEFAULT); 2419 } 2420 if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) { 2421 // We need to do a debuggable check here. See setAgentApp for why the check is 2422 // postponed to here. 2423 if (app.isDebuggable()) { 2424 String agent = mAppAgentMap.get(processName); 2425 // Do not overwrite already requested agent. 2426 if (profilerInfo == null) { 2427 profilerInfo = new ProfilerInfo(null, null, 0, false, false, 2428 mAppAgentMap.get(processName), true, 0, 2429 ProfilerInfo.OUTPUT_VERSION_DEFAULT); 2430 } else if (profilerInfo.agent == null) { 2431 profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true); 2432 } 2433 } 2434 } 2435 2436 if (profilerInfo != null && profilerInfo.profileFd != null) { 2437 profilerInfo.profileFd = profilerInfo.profileFd.dup(); 2438 if (TextUtils.equals(mProfileData.getProfileApp(), processName) 2439 && mProfileData.getProfilerInfo() != null) { 2440 clearProfilerLPf(); 2441 } 2442 } 2443 } 2444 2445 // Check if this is a secondary process that should be incorporated into some 2446 // currently active instrumentation. (Note we do this AFTER all of the profiling 2447 // stuff above because profiling can currently happen only in the primary 2448 // instrumentation process.) 2449 if (mService.mActiveInstrumentation.size() > 0 && instr == null) { 2450 for (int i = mService.mActiveInstrumentation.size() - 1; 2451 i >= 0 && app.getActiveInstrumentation() == null; i--) { 2452 ActiveInstrumentation aInstr = mService.mActiveInstrumentation.get(i); 2453 if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) { 2454 synchronized (mProcLock) { 2455 if (aInstr.mTargetProcesses.length == 0) { 2456 // This is the wildcard mode, where every process brought up for 2457 // the target instrumentation should be included. 2458 if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) { 2459 app.setActiveInstrumentation(aInstr); 2460 aInstr.mRunningProcesses.add(app); 2461 } 2462 } else { 2463 for (String proc : aInstr.mTargetProcesses) { 2464 if (proc.equals(app.processName)) { 2465 app.setActiveInstrumentation(aInstr); 2466 aInstr.mRunningProcesses.add(app); 2467 break; 2468 } 2469 } 2470 } 2471 } 2472 } 2473 } 2474 } 2475 2476 // If we were asked to attach an agent on startup, do so now, before we're binding 2477 // application code. 2478 if (preBindAgent != null) { 2479 thread.attachAgent(preBindAgent); 2480 } 2481 if (app.isDebuggable()) { 2482 thread.attachStartupAgents(app.info.dataDir); 2483 } 2484 return profilerInfo; 2485 } 2486 2487 @GuardedBy("mService") onCleanupApplicationRecordLocked(ProcessRecord app)2488 void onCleanupApplicationRecordLocked(ProcessRecord app) { 2489 synchronized (mProfilerLock) { 2490 final ProcessProfileRecord profile = app.mProfile; 2491 mProcessesToGc.remove(app); 2492 mPendingPssOrRssProfiles.remove(profile); 2493 profile.abortNextPssTime(); 2494 } 2495 } 2496 2497 @GuardedBy("mService") onAppDiedLocked(ProcessRecord app)2498 void onAppDiedLocked(ProcessRecord app) { 2499 synchronized (mProfilerLock) { 2500 if (mProfileData.getProfileProc() == app) { 2501 clearProfilerLPf(); 2502 } 2503 } 2504 } 2505 2506 @GuardedBy("mProfilerLock") dumpMemWatchProcessesLPf(PrintWriter pw, boolean needSep)2507 boolean dumpMemWatchProcessesLPf(PrintWriter pw, boolean needSep) { 2508 if (mMemWatchProcesses.getMap().size() > 0) { 2509 pw.println(" Mem watch processes:"); 2510 final ArrayMap<String, SparseArray<Pair<Long, String>>> procs = 2511 mMemWatchProcesses.getMap(); 2512 for (int i = procs.size() - 1; i >= 0; i--) { 2513 final String proc = procs.keyAt(i); 2514 final SparseArray<Pair<Long, String>> uids = procs.valueAt(i); 2515 for (int j = uids.size() - 1; j >= 0; j--) { 2516 if (needSep) { 2517 pw.println(); 2518 needSep = false; 2519 } 2520 StringBuilder sb = new StringBuilder(); 2521 sb.append(" ").append(proc).append('/'); 2522 UserHandle.formatUid(sb, uids.keyAt(j)); 2523 Pair<Long, String> val = uids.valueAt(j); 2524 sb.append(": "); DebugUtils.sizeValueToString(val.first, sb); 2525 if (val.second != null) { 2526 sb.append(", report to ").append(val.second); 2527 } 2528 pw.println(sb.toString()); 2529 } 2530 } 2531 pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName); 2532 pw.print(" mMemWatchDumpUri="); pw.println(mMemWatchDumpUri); 2533 pw.print(" mMemWatchDumpPid="); pw.println(mMemWatchDumpPid); 2534 pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid); 2535 pw.print(" mMemWatchIsUserInitiated="); pw.println(mMemWatchIsUserInitiated); 2536 } 2537 return needSep; 2538 } 2539 2540 @GuardedBy("mService") dumpProfileDataLocked(PrintWriter pw, String dumpPackage, boolean needSep)2541 boolean dumpProfileDataLocked(PrintWriter pw, String dumpPackage, boolean needSep) { 2542 if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null 2543 || (mProfileData.getProfilerInfo() != null 2544 && (mProfileData.getProfilerInfo().profileFile != null 2545 || mProfileData.getProfilerInfo().profileFd != null))) { 2546 if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) { 2547 if (needSep) { 2548 pw.println(); 2549 needSep = false; 2550 } 2551 pw.println(" mProfileApp=" + mProfileData.getProfileApp() 2552 + " mProfileProc=" + mProfileData.getProfileProc()); 2553 if (mProfileData.getProfilerInfo() != null) { 2554 pw.println(" mProfileFile=" + mProfileData.getProfilerInfo().profileFile 2555 + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd); 2556 pw.println( 2557 " mSamplingInterval=" + mProfileData.getProfilerInfo().samplingInterval 2558 + " mAutoStopProfiler=" 2559 + mProfileData.getProfilerInfo().autoStopProfiler 2560 + " mStreamingOutput=" 2561 + mProfileData.getProfilerInfo().streamingOutput 2562 + " mClockType=" 2563 + mProfileData.getProfilerInfo().clockType 2564 + " mProfilerOutputVersion=" 2565 + mProfileData.getProfilerInfo().profilerOutputVersion); 2566 pw.println(" mProfileType=" + mProfileType); 2567 } 2568 } 2569 } 2570 return needSep; 2571 } 2572 2573 @GuardedBy("mService") dumpLastMemoryLevelLocked(PrintWriter pw)2574 void dumpLastMemoryLevelLocked(PrintWriter pw) { 2575 switch (mLastMemoryLevel) { 2576 case ADJ_MEM_FACTOR_NORMAL: 2577 pw.println("normal)"); 2578 break; 2579 case ADJ_MEM_FACTOR_MODERATE: 2580 pw.println("moderate)"); 2581 break; 2582 case ADJ_MEM_FACTOR_LOW: 2583 pw.println("low)"); 2584 break; 2585 case ADJ_MEM_FACTOR_CRITICAL: 2586 pw.println("critical)"); 2587 break; 2588 default: 2589 pw.print(mLastMemoryLevel); 2590 pw.println(")"); 2591 break; 2592 } 2593 } 2594 2595 @GuardedBy("mService") dumpMemoryLevelsLocked(PrintWriter pw)2596 void dumpMemoryLevelsLocked(PrintWriter pw) { 2597 pw.println(" mAllowLowerMemLevel=" + mAllowLowerMemLevel 2598 + " mLastMemoryLevel=" + mLastMemoryLevel 2599 + " mLastNumProcesses=" + mLastNumProcesses); 2600 } 2601 2602 @GuardedBy("mProfilerLock") writeMemWatchProcessToProtoLPf(ProtoOutputStream proto)2603 void writeMemWatchProcessToProtoLPf(ProtoOutputStream proto) { 2604 if (mMemWatchProcesses.getMap().size() > 0) { 2605 final long token = proto.start( 2606 ActivityManagerServiceDumpProcessesProto.MEM_WATCH_PROCESSES); 2607 ArrayMap<String, SparseArray<Pair<Long, String>>> procs = mMemWatchProcesses.getMap(); 2608 for (int i = 0; i < procs.size(); i++) { 2609 final String proc = procs.keyAt(i); 2610 final SparseArray<Pair<Long, String>> uids = procs.valueAt(i); 2611 final long ptoken = proto.start( 2612 ActivityManagerServiceDumpProcessesProto.MemWatchProcess.PROCS); 2613 proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.NAME, 2614 proc); 2615 for (int j = uids.size() - 1; j >= 0; j--) { 2616 final long utoken = proto.start(ActivityManagerServiceDumpProcessesProto 2617 .MemWatchProcess.Process.MEM_STATS); 2618 Pair<Long, String> val = uids.valueAt(j); 2619 proto.write(ActivityManagerServiceDumpProcessesProto 2620 .MemWatchProcess.Process.MemStats.UID, uids.keyAt(j)); 2621 proto.write(ActivityManagerServiceDumpProcessesProto 2622 .MemWatchProcess.Process.MemStats.SIZE, 2623 DebugUtils.sizeValueToString(val.first, new StringBuilder())); 2624 proto.write(ActivityManagerServiceDumpProcessesProto 2625 .MemWatchProcess.Process.MemStats.REPORT_TO, val.second); 2626 proto.end(utoken); 2627 } 2628 proto.end(ptoken); 2629 } 2630 2631 final long dtoken = proto.start( 2632 ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP); 2633 proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME, 2634 mMemWatchDumpProcName); 2635 proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.URI, 2636 mMemWatchDumpUri.toString()); 2637 proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID, 2638 mMemWatchDumpPid); 2639 proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID, 2640 mMemWatchDumpUid); 2641 proto.write( 2642 ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.IS_USER_INITIATED, 2643 mMemWatchIsUserInitiated); 2644 proto.end(dtoken); 2645 2646 proto.end(token); 2647 } 2648 } 2649 2650 @GuardedBy("mService") writeProfileDataToProtoLocked(ProtoOutputStream proto, String dumpPackage)2651 void writeProfileDataToProtoLocked(ProtoOutputStream proto, String dumpPackage) { 2652 if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null 2653 || (mProfileData.getProfilerInfo() != null 2654 && (mProfileData.getProfilerInfo().profileFile != null 2655 || mProfileData.getProfilerInfo().profileFd != null))) { 2656 if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) { 2657 final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE); 2658 proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME, 2659 mProfileData.getProfileApp()); 2660 mProfileData.getProfileProc().dumpDebug(proto, 2661 ActivityManagerServiceDumpProcessesProto.Profile.PROC); 2662 if (mProfileData.getProfilerInfo() != null) { 2663 mProfileData.getProfilerInfo().dumpDebug(proto, 2664 ActivityManagerServiceDumpProcessesProto.Profile.INFO); 2665 proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE, 2666 mProfileType); 2667 } 2668 proto.end(token); 2669 } 2670 } 2671 } 2672 2673 @GuardedBy("mService") writeMemoryLevelsToProtoLocked(ProtoOutputStream proto)2674 void writeMemoryLevelsToProtoLocked(ProtoOutputStream proto) { 2675 proto.write(ActivityManagerServiceDumpProcessesProto.ALLOW_LOWER_MEM_LEVEL, 2676 mAllowLowerMemLevel); 2677 proto.write(ActivityManagerServiceDumpProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel); 2678 proto.write(ActivityManagerServiceDumpProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses); 2679 } 2680 printCurrentCpuState(StringBuilder report, long time)2681 void printCurrentCpuState(StringBuilder report, long time) { 2682 synchronized (mProcessCpuTracker) { 2683 // Only print the first 10 processes 2684 report.append(mProcessCpuTracker.printCurrentState(time, /* maxProcesses= */10)); 2685 } 2686 } 2687 getAppProfileStatsForDebugging(long time, int linesOfStats)2688 Pair<String, String> getAppProfileStatsForDebugging(long time, int linesOfStats) { 2689 String cpuLoad = null; 2690 String stats = null; 2691 synchronized (mProcessCpuTracker) { 2692 updateCpuStatsNow(); 2693 cpuLoad = mProcessCpuTracker.printCurrentLoad(); 2694 stats = mProcessCpuTracker.printCurrentState(time); 2695 } 2696 // Only return linesOfStats lines of Cpu stats. 2697 int toIndex = 0; 2698 for (int i = 0; i <= linesOfStats; i++) { 2699 int nextIndex = stats.indexOf('\n', toIndex); 2700 if (nextIndex == -1) { 2701 toIndex = stats.length(); 2702 break; 2703 } 2704 toIndex = nextIndex + 1; 2705 } 2706 return new Pair(cpuLoad, stats.substring(0, toIndex)); 2707 } 2708 2709 @GuardedBy("mProfilerLock") writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage)2710 void writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) { 2711 if (mProcessesToGc.size() > 0) { 2712 long now = SystemClock.uptimeMillis(); 2713 for (int i = 0, size = mProcessesToGc.size(); i < size; i++) { 2714 ProcessRecord r = mProcessesToGc.get(i); 2715 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) { 2716 continue; 2717 } 2718 final long token = proto.start(fieldId); 2719 final ProcessProfileRecord profile = r.mProfile; 2720 r.dumpDebug(proto, ProcessToGcProto.PROC); 2721 proto.write(ProcessToGcProto.REPORT_LOW_MEMORY, profile.getReportLowMemory()); 2722 proto.write(ProcessToGcProto.NOW_UPTIME_MS, now); 2723 proto.write(ProcessToGcProto.LAST_GCED_MS, profile.getLastRequestedGc()); 2724 proto.write(ProcessToGcProto.LAST_LOW_MEMORY_MS, profile.getLastLowMemory()); 2725 proto.end(token); 2726 } 2727 } 2728 } 2729 2730 @GuardedBy("mProfilerLock") dumpProcessesToGc(PrintWriter pw, boolean needSep, String dumpPackage)2731 boolean dumpProcessesToGc(PrintWriter pw, boolean needSep, String dumpPackage) { 2732 if (mProcessesToGc.size() > 0) { 2733 boolean printed = false; 2734 long now = SystemClock.uptimeMillis(); 2735 for (int i = 0, size = mProcessesToGc.size(); i < size; i++) { 2736 ProcessRecord proc = mProcessesToGc.get(i); 2737 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) { 2738 continue; 2739 } 2740 if (!printed) { 2741 if (needSep) pw.println(); 2742 needSep = true; 2743 pw.println(" Processes that are waiting to GC:"); 2744 printed = true; 2745 } 2746 pw.print(" Process "); pw.println(proc); 2747 final ProcessProfileRecord profile = proc.mProfile; 2748 pw.print(" lowMem="); pw.print(profile.getReportLowMemory()); 2749 pw.print(", last gced="); 2750 pw.print(now - profile.getLastRequestedGc()); 2751 pw.print(" ms ago, last lowMem="); 2752 pw.print(now - profile.getLastLowMemory()); 2753 pw.println(" ms ago"); 2754 2755 } 2756 } 2757 return needSep; 2758 } 2759 } 2760