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