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