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