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