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