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