• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         mService.mProcessStateController.setIsLastMemoryLevelNormal(isLastMemoryLevelNormal());
1360     }
1361 
1362     @GuardedBy({"mService", "mProcLock"})
updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming, long now)1363     void updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming, long now) {
1364         int memFactor;
1365         if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
1366             memFactor = mLowMemDetector.getMemFactor();
1367         } else {
1368             // Now determine the memory trimming level of background processes.
1369             // Unfortunately we need to start at the back of the list to do this
1370             // properly.  We only do this if the number of background apps we
1371             // are managing to keep around is less than half the maximum we desire;
1372             // if we are keeping a good number around, we'll let them use whatever
1373             // memory they want.
1374             if (numCached <= mService.mConstants.CUR_TRIM_CACHED_PROCESSES
1375                     && numEmpty <= mService.mConstants.CUR_TRIM_EMPTY_PROCESSES) {
1376                 final int numCachedAndEmpty = numCached + numEmpty;
1377                 if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
1378                     memFactor = ADJ_MEM_FACTOR_CRITICAL;
1379                 } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
1380                     memFactor = ADJ_MEM_FACTOR_LOW;
1381                 } else {
1382                     memFactor = ADJ_MEM_FACTOR_MODERATE;
1383                 }
1384             } else {
1385                 memFactor = ADJ_MEM_FACTOR_NORMAL;
1386             }
1387         }
1388         // We always allow the memory level to go up (better).  We only allow it to go
1389         // down if we are in a state where that is allowed, *and* the total number of processes
1390         // has gone down since last time.
1391         if (DEBUG_OOM_ADJ) {
1392             Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor + " override=" + mMemFactorOverride
1393                     + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
1394                     + " numProcs=" + mService.mProcessList.getLruSizeLOSP()
1395                     + " last=" + mLastNumProcesses);
1396         }
1397         boolean override;
1398         if (override = (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING)) {
1399             memFactor = mMemFactorOverride;
1400         }
1401         if (memFactor > mLastMemoryLevel) {
1402             if (!override && (!mAllowLowerMemLevel
1403                     || mService.mProcessList.getLruSizeLOSP() >= mLastNumProcesses)) {
1404                 memFactor = mLastMemoryLevel;
1405                 if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
1406             }
1407         }
1408         if (memFactor != mLastMemoryLevel) {
1409             EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
1410             FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
1411             mBgHandler.obtainMessage(BgHandler.MEMORY_PRESSURE_CHANGED, mLastMemoryLevel, memFactor)
1412                     .sendToTarget();
1413         }
1414 
1415         mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked(
1416                 numCached + numEmpty, now);
1417         boolean allChanged;
1418         int trackerMemFactor;
1419         synchronized (mService.mProcessStats.mLock) {
1420             allChanged = mService.mProcessStats.setMemFactorLocked(memFactor,
1421                     mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(),
1422                     SystemClock.uptimeMillis() /* re-acquire the time within the lock */);
1423             trackerMemFactor = mService.mProcessStats.getMemFactorLocked();
1424         }
1425 
1426         mLastMemoryLevel = memFactor;
1427         mService.mProcessStateController.setIsLastMemoryLevelNormal(isLastMemoryLevelNormal());
1428         mLastNumProcesses = mService.mProcessList.getLruSizeLOSP();
1429 
1430         // Dispatch UI_HIDDEN to processes that need it
1431         mService.mProcessList.forEachLruProcessesLOSP(
1432                 true,
1433                 app -> {
1434                     final ProcessProfileRecord profile = app.mProfile;
1435                     final IApplicationThread thread;
1436                     final ProcessStateRecord state = app.mState;
1437                     if (state.hasProcStateChanged()) {
1438                         state.setProcStateChanged(false);
1439                     }
1440                     int procState = app.mState.getCurProcState();
1441                     if (((procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
1442                                             && procState
1443                                                     < ActivityManager.PROCESS_STATE_CACHED_ACTIVITY)
1444                                     || app.mState.isSystemNoUi())
1445                             && app.mProfile.hasPendingUiClean()) {
1446                         // If this application is now in the background and it
1447                         // had done UI, then give it the special trim level to
1448                         // have it free UI resources.
1449                         if ((thread = app.getThread()) != null) {
1450                             try {
1451                                 thread.scheduleTrimMemory(
1452                                         ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
1453                                 app.mProfile.setPendingUiClean(false);
1454                             } catch (RemoteException e) {
1455 
1456                             }
1457                         }
1458                     }
1459                 });
1460     }
1461 
1462     @GuardedBy({"mService", "mProcLock"})
trimMemoryUiHiddenIfNecessaryLSP(ProcessRecord app)1463     private void trimMemoryUiHiddenIfNecessaryLSP(ProcessRecord app) {
1464         if ((app.mState.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
1465                 || app.mState.isSystemNoUi()) && app.mProfile.hasPendingUiClean()) {
1466             // If this application is now in the background and it
1467             // had done UI, then give it the special trim level to
1468             // have it free UI resources.
1469             scheduleTrimMemoryLSP(app, ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN,
1470                     "Trimming memory of bg-ui ");
1471             app.mProfile.setPendingUiClean(false);
1472         }
1473     }
1474 
1475     @GuardedBy({"mService", "mProcLock"})
scheduleTrimMemoryLSP(ProcessRecord app, int level, String msg)1476     private void scheduleTrimMemoryLSP(ProcessRecord app, int level, String msg) {
1477         IApplicationThread thread;
1478         if (app.mProfile.getTrimMemoryLevel() < level && (thread = app.getThread()) != null) {
1479             try {
1480                 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
1481                     Slog.v(TAG_OOM_ADJ, msg + app.processName + " to " + level);
1482                 }
1483                 mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
1484                         CachedAppOptimizer.UNFREEZE_REASON_TRIM_MEMORY);
1485                 thread.scheduleTrimMemory(level);
1486             } catch (RemoteException e) {
1487             }
1488         }
1489     }
1490 
1491     @GuardedBy("mProcLock")
getLowRamTimeSinceIdleLPr(long now)1492     long getLowRamTimeSinceIdleLPr(long now) {
1493         return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now - mLowRamStartTime) : 0);
1494     }
1495 
1496     /**
1497      * Ask a given process to GC right now.
1498      */
1499     @GuardedBy("mProfilerLock")
performAppGcLPf(ProcessRecord app)1500     private void performAppGcLPf(ProcessRecord app) {
1501         try {
1502             final ProcessProfileRecord profile = app.mProfile;
1503             profile.setLastRequestedGc(SystemClock.uptimeMillis());
1504             IApplicationThread thread = profile.getThread();
1505             if (thread != null) {
1506                 if (profile.getReportLowMemory()) {
1507                     profile.setReportLowMemory(false);
1508                     thread.scheduleLowMemory();
1509                 } else {
1510                     thread.processInBackground();
1511                 }
1512             }
1513         } catch (Exception e) {
1514             // whatever.
1515         }
1516     }
1517 
1518     /**
1519      * Perform GCs on all processes that are waiting for it, but only
1520      * if things are idle.
1521      */
1522     @GuardedBy("mProfilerLock")
performAppGcsLPf()1523     private void performAppGcsLPf() {
1524         if (mProcessesToGc.size() <= 0) {
1525             return;
1526         }
1527         while (mProcessesToGc.size() > 0) {
1528             final ProcessRecord proc = mProcessesToGc.remove(0);
1529             final ProcessProfileRecord profile = proc.mProfile;
1530             if (profile.getCurRawAdj() > ProcessList.PERCEPTIBLE_APP_ADJ
1531                     || profile.getReportLowMemory()) {
1532                 if ((profile.getLastRequestedGc() + mService.mConstants.GC_MIN_INTERVAL)
1533                         <= SystemClock.uptimeMillis()) {
1534                     // To avoid spamming the system, we will GC processes one
1535                     // at a time, waiting a few seconds between each.
1536                     performAppGcLPf(proc);
1537                     scheduleAppGcsLPf();
1538                     return;
1539                 } else {
1540                     // It hasn't been long enough since we last GCed this
1541                     // process...  put it in the list to wait for its time.
1542                     addProcessToGcListLPf(proc);
1543                     break;
1544                 }
1545             }
1546         }
1547 
1548         scheduleAppGcsLPf();
1549     }
1550 
1551     /**
1552      * If all looks good, perform GCs on all processes waiting for them.
1553      */
1554     @GuardedBy("mService")
performAppGcsIfAppropriateLocked()1555     final void performAppGcsIfAppropriateLocked() {
1556         synchronized (mProfilerLock) {
1557             if (mService.canGcNowLocked()) {
1558                 performAppGcsLPf();
1559                 return;
1560             }
1561             // Still not idle, wait some more.
1562             scheduleAppGcsLPf();
1563         }
1564     }
1565 
1566     /**
1567      * Schedule the execution of all pending app GCs.
1568      */
1569     @GuardedBy("mProfilerLock")
scheduleAppGcsLPf()1570     final void scheduleAppGcsLPf() {
1571         mService.mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
1572 
1573         if (mProcessesToGc.size() > 0) {
1574             // Schedule a GC for the time to the next process.
1575             ProcessRecord proc = mProcessesToGc.get(0);
1576             Message msg = mService.mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
1577 
1578             long when = proc.mProfile.getLastRequestedGc() + mService.mConstants.GC_MIN_INTERVAL;
1579             long now = SystemClock.uptimeMillis();
1580             if (when < (now + mService.mConstants.GC_TIMEOUT)) {
1581                 when = now + mService.mConstants.GC_TIMEOUT;
1582             }
1583             mService.mHandler.sendMessageAtTime(msg, when);
1584         }
1585     }
1586 
1587     /**
1588      * Add a process to the array of processes waiting to be GCed.  Keeps the
1589      * list in sorted order by the last GC time.  The process can't already be
1590      * on the list.
1591      */
1592     @GuardedBy("mProfilerLock")
addProcessToGcListLPf(ProcessRecord proc)1593     private void addProcessToGcListLPf(ProcessRecord proc) {
1594         boolean added = false;
1595         for (int i = mProcessesToGc.size() - 1; i >= 0; i--) {
1596             if (mProcessesToGc.get(i).mProfile.getLastRequestedGc()
1597                     < proc.mProfile.getLastRequestedGc()) {
1598                 added = true;
1599                 mProcessesToGc.add(i + 1, proc);
1600                 break;
1601             }
1602         }
1603         if (!added) {
1604             mProcessesToGc.add(0, proc);
1605         }
1606     }
1607 
1608     @GuardedBy("mService")
doLowMemReportIfNeededLocked(ProcessRecord dyingProc)1609     final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) {
1610         // If there are no longer any background processes running,
1611         // and the app that died was not running instrumentation,
1612         // then tell everyone we are now low on memory.
1613         if (!mService.mProcessList.haveBackgroundProcessLOSP()) {
1614             boolean doReport = Build.IS_DEBUGGABLE;
1615             final long now = SystemClock.uptimeMillis();
1616             if (doReport) {
1617                 if (now < (mLastMemUsageReportTime + 5 * 60 * 1000)) {
1618                     doReport = false;
1619                 } else {
1620                     mLastMemUsageReportTime = now;
1621                 }
1622             }
1623             final int lruSize = mService.mProcessList.getLruSizeLOSP();
1624             final ArrayList<ProcessMemInfo> memInfos = doReport
1625                     ? new ArrayList<ProcessMemInfo>(lruSize) : null;
1626             EventLogTags.writeAmLowMemory(lruSize);
1627             mService.mProcessList.forEachLruProcessesLOSP(false, rec -> {
1628                 if (rec == dyingProc || rec.getThread() == null) {
1629                     return;
1630                 }
1631                 final ProcessStateRecord state = rec.mState;
1632                 if (memInfos != null) {
1633                     memInfos.add(new ProcessMemInfo(rec.processName, rec.getPid(),
1634                                 state.getSetAdj(), state.getSetProcState(),
1635                                 state.getAdjType(), state.makeAdjReason()));
1636                 }
1637                 final ProcessProfileRecord profile = rec.mProfile;
1638                 if ((profile.getLastLowMemory() + mService.mConstants.GC_MIN_INTERVAL) <= now) {
1639                     // The low memory report is overriding any current
1640                     // state for a GC request.  Make sure to do
1641                     // heavy/important/visible/foreground processes first.
1642                     synchronized (mProfilerLock) {
1643                         if (state.getSetAdj() <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
1644                             profile.setLastRequestedGc(0);
1645                         } else {
1646                             profile.setLastRequestedGc(profile.getLastLowMemory());
1647                         }
1648                         profile.setReportLowMemory(true);
1649                         profile.setLastLowMemory(now);
1650                         mProcessesToGc.remove(rec);
1651                         addProcessToGcListLPf(rec);
1652                     }
1653                 }
1654             });
1655             if (doReport) {
1656                 Message msg = mService.mHandler.obtainMessage(REPORT_MEM_USAGE_MSG, memInfos);
1657                 mService.mHandler.sendMessage(msg);
1658             }
1659         }
1660         synchronized (mProfilerLock) {
1661             scheduleAppGcsLPf();
1662         }
1663     }
1664 
reportMemUsage(ArrayList<ProcessMemInfo> memInfos)1665     void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) {
1666         final SparseArray<ProcessMemInfo> infoMap = new SparseArray<>(memInfos.size());
1667         for (int i = 0, size = memInfos.size(); i < size; i++) {
1668             ProcessMemInfo mi = memInfos.get(i);
1669             infoMap.put(mi.pid, mi);
1670         }
1671         updateCpuStatsNow();
1672         long[] memtrackTmp = new long[4];
1673         long[] swaptrackTmp = new long[2];
1674         // Get a list of Stats that have vsize > 0
1675         final List<ProcessCpuTracker.Stats> stats = getCpuStats(st -> st.vsize > 0);
1676         final int statsCount = stats.size();
1677         long totalMemtrackGraphics = 0;
1678         long totalMemtrackGl = 0;
1679         for (int i = 0; i < statsCount; i++) {
1680             ProcessCpuTracker.Stats st = stats.get(i);
1681             long pss = Debug.getPss(st.pid, swaptrackTmp, memtrackTmp);
1682             if (pss > 0) {
1683                 if (infoMap.indexOfKey(st.pid) < 0) {
1684                     ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
1685                             ProcessList.NATIVE_ADJ, -1, "native", null);
1686                     mi.pss = pss;
1687                     mi.swapPss = swaptrackTmp[1];
1688                     mi.memtrack = memtrackTmp[0];
1689                     totalMemtrackGraphics += memtrackTmp[1];
1690                     totalMemtrackGl += memtrackTmp[2];
1691                     memInfos.add(mi);
1692                 }
1693             }
1694         }
1695 
1696         long totalPss = 0;
1697         long totalSwapPss = 0;
1698         long totalMemtrack = 0;
1699         for (int i = 0, size = memInfos.size(); i < size; i++) {
1700             ProcessMemInfo mi = memInfos.get(i);
1701             if (mi.pss == 0) {
1702                 mi.pss = Debug.getPss(mi.pid, swaptrackTmp, memtrackTmp);
1703                 mi.swapPss = swaptrackTmp[1];
1704                 mi.memtrack = memtrackTmp[0];
1705                 totalMemtrackGraphics += memtrackTmp[1];
1706                 totalMemtrackGl += memtrackTmp[2];
1707             }
1708             totalPss += mi.pss;
1709             totalSwapPss += mi.swapPss;
1710             totalMemtrack += mi.memtrack;
1711         }
1712         Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
1713             @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) {
1714                 if (lhs.oomAdj != rhs.oomAdj) {
1715                     return lhs.oomAdj < rhs.oomAdj ? -1 : 1;
1716                 }
1717                 if (lhs.pss != rhs.pss) {
1718                     return lhs.pss < rhs.pss ? 1 : -1;
1719                 }
1720                 return 0;
1721             }
1722         });
1723 
1724         StringBuilder tag = new StringBuilder(128);
1725         StringBuilder stack = new StringBuilder(128);
1726         tag.append("Low on memory -- ");
1727         appendMemBucket(tag, totalPss, "total", false);
1728         appendMemBucket(stack, totalPss, "total", true);
1729 
1730         StringBuilder fullNativeBuilder = new StringBuilder(1024);
1731         StringBuilder shortNativeBuilder = new StringBuilder(1024);
1732         StringBuilder fullJavaBuilder = new StringBuilder(1024);
1733 
1734         boolean firstLine = true;
1735         int lastOomAdj = Integer.MIN_VALUE;
1736         long extraNativeRam = 0;
1737         long extraNativeMemtrack = 0;
1738         long cachedPss = 0;
1739         for (int i = 0, size = memInfos.size(); i < size; i++) {
1740             ProcessMemInfo mi = memInfos.get(i);
1741 
1742             if (mi.oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
1743                 cachedPss += mi.pss;
1744             }
1745 
1746             if (mi.oomAdj != ProcessList.NATIVE_ADJ
1747                     && (mi.oomAdj < ProcessList.SERVICE_ADJ
1748                             || mi.oomAdj == ProcessList.HOME_APP_ADJ
1749                             || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) {
1750                 if (lastOomAdj != mi.oomAdj) {
1751                     lastOomAdj = mi.oomAdj;
1752                     if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
1753                         tag.append(" / ");
1754                     }
1755                     if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) {
1756                         if (firstLine) {
1757                             stack.append(":");
1758                             firstLine = false;
1759                         }
1760                         stack.append("\n\t at ");
1761                     } else {
1762                         stack.append("$");
1763                     }
1764                 } else {
1765                     tag.append(" ");
1766                     stack.append("$");
1767                 }
1768                 if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
1769                     appendMemBucket(tag, mi.pss, mi.name, false);
1770                 }
1771                 appendMemBucket(stack, mi.pss, mi.name, true);
1772                 if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ
1773                         && ((i + 1) >= size || memInfos.get(i + 1).oomAdj != lastOomAdj)) {
1774                     stack.append("(");
1775                     for (int k = 0; k < DUMP_MEM_OOM_ADJ.length; k++) {
1776                         if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) {
1777                             stack.append(DUMP_MEM_OOM_LABEL[k]);
1778                             stack.append(":");
1779                             stack.append(DUMP_MEM_OOM_ADJ[k]);
1780                         }
1781                     }
1782                     stack.append(")");
1783                 }
1784             }
1785 
1786             appendMemInfo(fullNativeBuilder, mi);
1787             if (mi.oomAdj == ProcessList.NATIVE_ADJ) {
1788                 // The short form only has native processes that are >= 512K.
1789                 if (mi.pss >= 512) {
1790                     appendMemInfo(shortNativeBuilder, mi);
1791                 } else {
1792                     extraNativeRam += mi.pss;
1793                     extraNativeMemtrack += mi.memtrack;
1794                 }
1795             } else {
1796                 // Short form has all other details, but if we have collected RAM
1797                 // from smaller native processes let's dump a summary of that.
1798                 if (extraNativeRam > 0) {
1799                     appendBasicMemEntry(shortNativeBuilder, ProcessList.NATIVE_ADJ,
1800                             -1, extraNativeRam, extraNativeMemtrack, "(Other native)");
1801                     shortNativeBuilder.append('\n');
1802                     extraNativeRam = 0;
1803                 }
1804                 appendMemInfo(fullJavaBuilder, mi);
1805             }
1806         }
1807 
1808         fullJavaBuilder.append("           ");
1809         ProcessList.appendRamKb(fullJavaBuilder, totalPss);
1810         fullJavaBuilder.append(": TOTAL");
1811         if (totalMemtrack > 0) {
1812             fullJavaBuilder.append(" (");
1813             fullJavaBuilder.append(stringifyKBSize(totalMemtrack));
1814             fullJavaBuilder.append(" memtrack)");
1815         }
1816         fullJavaBuilder.append("\n");
1817 
1818         MemInfoReader memInfo = new MemInfoReader();
1819         memInfo.readMemInfo();
1820         final long[] infos = memInfo.getRawInfo();
1821 
1822         StringBuilder memInfoBuilder = new StringBuilder(1024);
1823         Debug.getMemInfo(infos);
1824         memInfoBuilder.append("  MemInfo: ");
1825         memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SLAB])).append(" slab, ");
1826         memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SHMEM])).append(" shmem, ");
1827         memInfoBuilder.append(stringifyKBSize(
1828                                   infos[Debug.MEMINFO_VM_ALLOC_USED])).append(" vm alloc, ");
1829         memInfoBuilder.append(stringifyKBSize(
1830                                   infos[Debug.MEMINFO_PAGE_TABLES])).append(" page tables ");
1831         memInfoBuilder.append(stringifyKBSize(
1832                                   infos[Debug.MEMINFO_KERNEL_STACK])).append(" kernel stack\n");
1833         memInfoBuilder.append("           ");
1834         memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_BUFFERS])).append(" buffers, ");
1835         memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_CACHED])).append(" cached, ");
1836         memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_MAPPED])).append(" mapped, ");
1837         memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_FREE])).append(" free\n");
1838         if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) {
1839             memInfoBuilder.append("  ZRAM: ");
1840             memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_ZRAM_TOTAL]));
1841             memInfoBuilder.append(" RAM, ");
1842             memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SWAP_TOTAL]));
1843             memInfoBuilder.append(" swap total, ");
1844             memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SWAP_FREE]));
1845             memInfoBuilder.append(" swap free\n");
1846         }
1847         final long[] ksm = getKsmInfo();
1848         if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0
1849                 || ksm[KSM_VOLATILE] != 0) {
1850             memInfoBuilder.append("  KSM: ");
1851             memInfoBuilder.append(stringifyKBSize(ksm[KSM_SHARING]));
1852             memInfoBuilder.append(" saved from shared ");
1853             memInfoBuilder.append(stringifyKBSize(ksm[KSM_SHARED]));
1854             memInfoBuilder.append("\n       ");
1855             memInfoBuilder.append(stringifyKBSize(ksm[KSM_UNSHARED]));
1856             memInfoBuilder.append(" unshared; ");
1857             memInfoBuilder.append(stringifyKBSize(ksm[KSM_VOLATILE]));
1858             memInfoBuilder.append(" volatile\n");
1859         }
1860         memInfoBuilder.append("  Free RAM: ");
1861         memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
1862                 + memInfo.getFreeSizeKb()));
1863         memInfoBuilder.append("\n");
1864         long kernelUsed = memInfo.getKernelUsedSizeKb();
1865         final long ionHeap = Debug.getIonHeapsSizeKb();
1866         final long ionPool = Debug.getIonPoolsSizeKb();
1867         final long dmabufMapped = Debug.getDmabufMappedSizeKb();
1868         if (ionHeap >= 0 && ionPool >= 0) {
1869             final long ionUnmapped = ionHeap - dmabufMapped;
1870             memInfoBuilder.append("       ION: ");
1871             memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool));
1872             memInfoBuilder.append("\n");
1873             kernelUsed += ionUnmapped;
1874             // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being
1875             // set on ION VMAs, however it might be included by the memtrack HAL.
1876             // Replace memtrack HAL reported Graphics category with mapped dmabufs
1877             totalPss -= totalMemtrackGraphics;
1878             totalPss += dmabufMapped;
1879         } else {
1880             final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb();
1881             if (totalExportedDmabuf >= 0) {
1882                 final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped;
1883                 memInfoBuilder.append("DMA-BUF: ");
1884                 memInfoBuilder.append(stringifyKBSize(totalExportedDmabuf));
1885                 memInfoBuilder.append("\n");
1886                 // Account unmapped dmabufs as part of kernel memory allocations
1887                 kernelUsed += dmabufUnmapped;
1888                 // Replace memtrack HAL reported Graphics category with mapped dmabufs
1889                 totalPss -= totalMemtrackGraphics;
1890                 totalPss += dmabufMapped;
1891             }
1892             // These are included in the totalExportedDmabuf above and hence do not need to be added
1893             // to kernelUsed.
1894             final long totalExportedDmabufHeap = Debug.getDmabufHeapTotalExportedKb();
1895             if (totalExportedDmabufHeap >= 0) {
1896                 memInfoBuilder.append("DMA-BUF Heap: ");
1897                 memInfoBuilder.append(stringifyKBSize(totalExportedDmabufHeap));
1898                 memInfoBuilder.append("\n");
1899             }
1900 
1901             final long totalDmabufHeapPool = Debug.getDmabufHeapPoolsSizeKb();
1902             if (totalDmabufHeapPool >= 0) {
1903                 memInfoBuilder.append("DMA-BUF Heaps pool: ");
1904                 memInfoBuilder.append(stringifyKBSize(totalDmabufHeapPool));
1905                 memInfoBuilder.append("\n");
1906             }
1907         }
1908 
1909         final long gpuUsage = Debug.getGpuTotalUsageKb();
1910         if (gpuUsage >= 0) {
1911             final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb();
1912             if (gpuPrivateUsage >= 0) {
1913                 final long gpuDmaBufUsage = gpuUsage - gpuPrivateUsage;
1914                 memInfoBuilder.append("      GPU: ");
1915                 memInfoBuilder.append(stringifyKBSize(gpuUsage));
1916                 memInfoBuilder.append(" (");
1917                 memInfoBuilder.append(stringifyKBSize(gpuDmaBufUsage));
1918                 memInfoBuilder.append(" dmabuf + ");
1919                 memInfoBuilder.append(stringifyKBSize(gpuPrivateUsage));
1920                 memInfoBuilder.append(" private)\n");
1921                 // Replace memtrack HAL reported GL category with private GPU allocations and
1922                 // account it as part of kernel memory allocations
1923                 totalPss -= totalMemtrackGl;
1924                 kernelUsed += gpuPrivateUsage;
1925             } else {
1926                 memInfoBuilder.append("       GPU: ");
1927                 memInfoBuilder.append(stringifyKBSize(gpuUsage));
1928                 memInfoBuilder.append("\n");
1929             }
1930 
1931         }
1932         memInfoBuilder.append("  Used RAM: ");
1933         memInfoBuilder.append(stringifyKBSize(
1934                                   totalPss - cachedPss + kernelUsed));
1935         memInfoBuilder.append("\n");
1936 
1937         // Note: ION/DMA-BUF heap pools are reclaimable and hence, they are included as part of
1938         // memInfo.getCachedSizeKb().
1939         memInfoBuilder.append("  Lost RAM: ");
1940         memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb()
1941                 - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
1942                 - kernelUsed - memInfo.getZramTotalSizeKb()));
1943         memInfoBuilder.append("\n");
1944         Slog.i(TAG, "Low on memory:");
1945         Slog.i(TAG, shortNativeBuilder.toString());
1946         Slog.i(TAG, fullJavaBuilder.toString());
1947         Slog.i(TAG, memInfoBuilder.toString());
1948 
1949         StringBuilder dropBuilder = new StringBuilder(1024);
1950         dropBuilder.append("Low on memory:");
1951         dropBuilder.append(stack);
1952         dropBuilder.append('\n');
1953         dropBuilder.append(fullNativeBuilder);
1954         dropBuilder.append(fullJavaBuilder);
1955         dropBuilder.append('\n');
1956         dropBuilder.append(memInfoBuilder);
1957         dropBuilder.append('\n');
1958         StringWriter catSw = new StringWriter();
1959         synchronized (mService) {
1960             PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
1961             String[] emptyArgs = new String[] { };
1962             catPw.println();
1963             synchronized (mProcLock) {
1964                 mService.mProcessList.dumpProcessesLSP(null, catPw, emptyArgs, 0, false, null, -1);
1965             }
1966             catPw.println();
1967             mService.mServices.newServiceDumperLocked(null, catPw, emptyArgs, 0,
1968                     false, null).dumpLocked();
1969             catPw.println();
1970             mService.mAtmInternal.dump(DUMP_ACTIVITIES_CMD, null, catPw, emptyArgs, 0, false, false,
1971                     null, INVALID_DISPLAY);
1972             catPw.flush();
1973         }
1974         dropBuilder.append(catSw.toString());
1975         FrameworkStatsLog.write(FrameworkStatsLog.LOW_MEM_REPORTED);
1976         mService.addErrorToDropBox("lowmem", null, "system_server", null,
1977                 null, null, tag.toString(), dropBuilder.toString(), null, null, null, null, null,
1978                 null);
1979         synchronized (mService) {
1980             long now = SystemClock.uptimeMillis();
1981             if (mLastMemUsageReportTime < now) {
1982                 mLastMemUsageReportTime = now;
1983             }
1984         }
1985     }
1986 
1987     @GuardedBy("mService")
handleMemoryPressureChangedLocked(@emFactor int oldMemFactor, @MemFactor int newMemFactor)1988     private void handleMemoryPressureChangedLocked(@MemFactor int oldMemFactor,
1989             @MemFactor int newMemFactor) {
1990         mService.mServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
1991                 oldMemFactor, newMemFactor, "mem-pressure-event", SystemClock.uptimeMillis());
1992     }
1993 
1994     @GuardedBy("mProfilerLock")
stopProfilerLPf(ProcessRecord proc, ProfilerInfo profilerInfo, int profileType)1995     private void stopProfilerLPf(ProcessRecord proc, ProfilerInfo profilerInfo, int profileType) {
1996         if (proc == null || proc == mProfileData.getProfileProc()) {
1997             proc = mProfileData.getProfileProc();
1998             profileType = mProfileType;
1999             clearProfilerLPf();
2000         }
2001         if (proc == null) {
2002             return;
2003         }
2004         final IApplicationThread thread = proc.mProfile.getThread();
2005         if (thread == null) {
2006             return;
2007         }
2008         try {
2009             thread.profilerControl(false, profilerInfo, profileType);
2010         } catch (RemoteException e) {
2011             throw new IllegalStateException("Process disappeared");
2012         }
2013     }
2014 
2015     @GuardedBy("mProfilerLock")
clearProfilerLPf()2016     void clearProfilerLPf() {
2017         if (mProfileData.getProfilerInfo() != null
2018                 && mProfileData.getProfilerInfo().profileFd != null) {
2019             try {
2020                 mProfileData.getProfilerInfo().profileFd.close();
2021             } catch (IOException e) {
2022             }
2023         }
2024         mProfileData.setProfileApp(null);
2025         mProfileData.setProfileProc(null);
2026         mProfileData.setProfilerInfo(null);
2027     }
2028 
2029     @GuardedBy("mProfilerLock")
clearProfilerLPf(ProcessRecord app)2030     void clearProfilerLPf(ProcessRecord app) {
2031         if (mProfileData.getProfileProc() == null
2032                 || mProfileData.getProfilerInfo() == null
2033                 || mProfileData.getProfileProc() != app) {
2034             return;
2035         }
2036         clearProfilerLPf();
2037     }
2038 
2039     @GuardedBy("mProfilerLock")
profileControlLPf(ProcessRecord proc, boolean start, ProfilerInfo profilerInfo, int profileType)2040     boolean profileControlLPf(ProcessRecord proc, boolean start,
2041             ProfilerInfo profilerInfo, int profileType) {
2042         try {
2043             if (start) {
2044                 boolean needsFile = (profileType == ProfilerInfo.PROFILE_TYPE_REGULAR);
2045                 stopProfilerLPf(null, null, 0);
2046                 mService.setProfileApp(proc.info, proc.processName, profilerInfo,
2047                         proc.isSdkSandbox ? proc.getClientInfoForSdkSandbox() : null, profileType);
2048                 mProfileData.setProfileProc(proc);
2049                 mProfileType = profileType;
2050 
2051                 ParcelFileDescriptor fd = null;
2052                 if (needsFile) {
2053                     fd = profilerInfo.profileFd;
2054                     try {
2055                         fd = fd.dup();
2056                     } catch (IOException e) {
2057                         fd = null;
2058                     }
2059                     profilerInfo.profileFd = fd;
2060                 }
2061 
2062                 proc.mProfile.getThread().profilerControl(start, profilerInfo, profileType);
2063 
2064                 if (needsFile) {
2065                     fd = null;
2066                     try {
2067                         mProfileData.getProfilerInfo().profileFd.close();
2068                     } catch (IOException e) {
2069                     }
2070                     mProfileData.getProfilerInfo().profileFd = null;
2071 
2072                     if (proc.getPid() == mService.MY_PID) {
2073                         // When profiling the system server itself, avoid closing the file
2074                         // descriptor, as profilerControl will not create a copy.
2075                         // Note: it is also not correct to just set profileFd to null, as the
2076                         //       whole ProfilerInfo instance is passed down!
2077                         profilerInfo = null;
2078                     }
2079                 }
2080             } else {
2081                 boolean mayNeedFile = (profileType == ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD);
2082                 if (profilerInfo != null && profilerInfo.profileFd != null) {
2083                     ParcelFileDescriptor fd = profilerInfo.profileFd;
2084                     try {
2085                         if (mayNeedFile) {
2086                             fd = fd.dup();
2087                         } else {
2088                             fd.close();
2089                         }
2090                     } catch (IOException e) {
2091                         fd = null;
2092                     }
2093                     profilerInfo.profileFd = fd;
2094                 }
2095                 stopProfilerLPf(proc, profilerInfo, profileType);
2096             }
2097 
2098             return true;
2099         } catch (RemoteException e) {
2100             throw new IllegalStateException("Process disappeared");
2101         } finally {
2102             if (profilerInfo != null && profilerInfo.profileFd != null) {
2103                 try {
2104                     profilerInfo.profileFd.close();
2105                 } catch (IOException e) {
2106                 }
2107             }
2108         }
2109     }
2110 
2111     @GuardedBy("mProfilerLock")
setProfileAppLPf(String processName, ProfilerInfo profilerInfo, int profileType)2112     void setProfileAppLPf(String processName, ProfilerInfo profilerInfo, int profileType) {
2113         mProfileData.setProfileApp(processName);
2114 
2115         if (mProfileData.getProfilerInfo() != null) {
2116             if (mProfileData.getProfilerInfo().profileFd != null) {
2117                 try {
2118                     mProfileData.getProfilerInfo().profileFd.close();
2119                 } catch (IOException e) {
2120                 }
2121             }
2122         }
2123         if (profilerInfo != null) {
2124             mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
2125         }
2126         mProfileType = profileType;
2127     }
2128 
2129     @GuardedBy("mProfilerLock")
setProfileProcLPf(ProcessRecord proc)2130     void setProfileProcLPf(ProcessRecord proc) {
2131         mProfileData.setProfileProc(proc);
2132     }
2133 
2134     @GuardedBy("mProfilerLock")
setAgentAppLPf(@onNull String packageName, @Nullable String agent)2135     void setAgentAppLPf(@NonNull String packageName, @Nullable String agent) {
2136         if (agent == null) {
2137             if (mAppAgentMap != null) {
2138                 mAppAgentMap.remove(packageName);
2139                 if (mAppAgentMap.isEmpty()) {
2140                     mAppAgentMap = null;
2141                 }
2142             }
2143         } else {
2144             if (mAppAgentMap == null) {
2145                 mAppAgentMap = new HashMap<>();
2146             }
2147             if (mAppAgentMap.size() >= 100) {
2148                 // Limit the size of the map, to avoid OOMEs.
2149                 Slog.e(TAG, "App agent map has too many entries, cannot add " + packageName
2150                         + "/" + agent);
2151                 return;
2152             }
2153             mAppAgentMap.put(packageName, agent);
2154         }
2155     }
2156 
updateCpuStats()2157     void updateCpuStats() {
2158         final long now = SystemClock.uptimeMillis();
2159         if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
2160             return;
2161         }
2162         if (mProcessCpuMutexFree.compareAndSet(true, false)) {
2163             synchronized (mProcessCpuThread) {
2164                 mProcessCpuThread.notify();
2165             }
2166         }
2167     }
2168 
updateCpuStatsNow()2169     void updateCpuStatsNow() {
2170         final boolean monitorPhantomProcs = mService.mSystemReady && FeatureFlagUtils.isEnabled(
2171                 mService.mContext, SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS);
2172         synchronized (mProcessCpuTracker) {
2173             mProcessCpuMutexFree.set(false);
2174             final long now = SystemClock.uptimeMillis();
2175             boolean haveNewCpuStats = false;
2176 
2177             if (MONITOR_CPU_USAGE
2178                     && mLastCpuTime.get() < (now - MONITOR_CPU_MIN_TIME)) {
2179                 mLastCpuTime.set(now);
2180                 mProcessCpuTracker.update();
2181                 if (mProcessCpuTracker.hasGoodLastStats()) {
2182                     haveNewCpuStats = true;
2183                     //Slog.i(TAG, mProcessCpu.printCurrentState());
2184                     //Slog.i(TAG, "Total CPU usage: "
2185                     //        + mProcessCpu.getTotalCpuPercent() + "%");
2186 
2187                     // Slog the cpu usage if the property is set.
2188                     if ("true".equals(SystemProperties.get("events.cpu"))) {
2189                         int user = mProcessCpuTracker.getLastUserTime();
2190                         int system = mProcessCpuTracker.getLastSystemTime();
2191                         int iowait = mProcessCpuTracker.getLastIoWaitTime();
2192                         int irq = mProcessCpuTracker.getLastIrqTime();
2193                         int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
2194                         int idle = mProcessCpuTracker.getLastIdleTime();
2195 
2196                         int total = user + system + iowait + irq + softIrq + idle;
2197                         if (total == 0) total = 1;
2198 
2199                         EventLogTags.writeCpu(
2200                                 ((user + system + iowait + irq + softIrq) * 100) / total,
2201                                 (user * 100) / total,
2202                                 (system * 100) / total,
2203                                 (iowait * 100) / total,
2204                                 (irq * 100) / total,
2205                                 (softIrq * 100) / total);
2206                     }
2207                 }
2208             }
2209 
2210             if (monitorPhantomProcs && haveNewCpuStats) {
2211                 mService.mPhantomProcessList.updateProcessCpuStatesLocked(mProcessCpuTracker);
2212             }
2213 
2214             final BatteryStatsImpl bstats = mService.mBatteryStatsService.getActiveStatistics();
2215             synchronized (bstats) {
2216                 if (haveNewCpuStats) {
2217                     if (bstats.startAddingCpuStatsLocked()) {
2218                         int totalUTime = 0;
2219                         int totalSTime = 0;
2220                         final int statsCount = mProcessCpuTracker.countStats();
2221                         final long elapsedRealtime = SystemClock.elapsedRealtime();
2222                         final long uptime = SystemClock.uptimeMillis();
2223                         synchronized (mService.mPidsSelfLocked) {
2224                             for (int i = 0; i < statsCount; i++) {
2225                                 ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
2226                                 if (!st.working) {
2227                                     continue;
2228                                 }
2229                                 ProcessRecord pr = mService.mPidsSelfLocked.get(st.pid);
2230                                 totalUTime += st.rel_utime;
2231                                 totalSTime += st.rel_stime;
2232                                 if (pr != null) {
2233                                     final ProcessProfileRecord profile = pr.mProfile;
2234                                     BatteryStatsImpl.Uid.Proc ps = profile.getCurProcBatteryStats();
2235                                     if (ps == null || !ps.isActive()) {
2236                                         profile.setCurProcBatteryStats(
2237                                                 ps = bstats.getProcessStatsLocked(
2238                                                 pr.info.uid, pr.processName,
2239                                                 elapsedRealtime, uptime));
2240                                     }
2241                                     ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
2242                                     final long curCpuTime = profile.mCurCpuTime.addAndGet(
2243                                             st.rel_utime + st.rel_stime);
2244                                     profile.mLastCpuTime.compareAndSet(0, curCpuTime);
2245                                 } else {
2246                                     BatteryStatsImpl.Uid.Proc ps =
2247                                             (BatteryStatsImpl.Uid.Proc) st.batteryStats;
2248                                     if (ps == null || !ps.isActive()) {
2249                                         st.batteryStats = ps = bstats.getProcessStatsLocked(
2250                                                 st.uid, st.name, elapsedRealtime, uptime);
2251                                     }
2252                                     ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
2253                                 }
2254                                 EventLogTags.writeAmCpu(st.pid, st.uid, st.baseName,
2255                                         st.rel_uptime, st.rel_utime, st.rel_stime);
2256                             }
2257                         }
2258 
2259                         final int userTime = mProcessCpuTracker.getLastUserTime();
2260                         final int systemTime = mProcessCpuTracker.getLastSystemTime();
2261                         final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime();
2262                         final int irqTime = mProcessCpuTracker.getLastIrqTime();
2263                         final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
2264                         final int idleTime = mProcessCpuTracker.getLastIdleTime();
2265                         bstats.addCpuStatsLocked(totalUTime, totalSTime, userTime,
2266                                 systemTime, iowaitTime, irqTime, softIrqTime, idleTime);
2267                         bstats.finishAddingCpuStatsLocked();
2268                     }
2269                 }
2270 
2271                 if (mLastWriteTime < (now - BATTERY_STATS_TIME)) {
2272                     mLastWriteTime = now;
2273                     mService.mBatteryStatsService.scheduleWriteToDisk();
2274                 }
2275             }
2276         }
2277     }
2278 
getCpuTimeForPid(int pid)2279     long getCpuTimeForPid(int pid) {
2280         return mProcessCpuTracker.getCpuTimeForPid(pid);
2281     }
2282 
getCpuDelayTimeForPid(int pid)2283     long getCpuDelayTimeForPid(int pid) {
2284         return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
2285     }
2286 
getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate)2287     List<ProcessCpuTracker.Stats> getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate) {
2288         synchronized (mProcessCpuTracker) {
2289             return mProcessCpuTracker.getStats(st -> predicate.test(st));
2290         }
2291     }
2292 
forAllCpuStats(Consumer<ProcessCpuTracker.Stats> consumer)2293     void forAllCpuStats(Consumer<ProcessCpuTracker.Stats> consumer) {
2294         synchronized (mProcessCpuTracker) {
2295             final int numOfStats = mProcessCpuTracker.countStats();
2296             for (int i = 0; i < numOfStats; i++) {
2297                 consumer.accept(mProcessCpuTracker.getStats(i));
2298             }
2299         }
2300     }
2301 
2302     private class ProcessCpuThread extends Thread {
ProcessCpuThread(String name)2303         ProcessCpuThread(String name) {
2304             super(name);
2305         }
2306 
2307         @Override
run()2308         public void run() {
2309             synchronized (mProcessCpuTracker) {
2310                 mProcessCpuInitLatch.countDown();
2311                 mProcessCpuTracker.init();
2312             }
2313             while (true) {
2314                 try {
2315                     try {
2316                         synchronized (this) {
2317                             final long now = SystemClock.uptimeMillis();
2318                             long nextCpuDelay = (mLastCpuTime.get() + MONITOR_CPU_MAX_TIME) - now;
2319                             long nextWriteDelay = (mLastWriteTime + BATTERY_STATS_TIME) - now;
2320                             //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
2321                             //        + ", write delay=" + nextWriteDelay);
2322                             if (nextWriteDelay < nextCpuDelay) {
2323                                 nextCpuDelay = nextWriteDelay;
2324                             }
2325                             if (nextCpuDelay > 0) {
2326                                 mProcessCpuMutexFree.set(true);
2327                                 this.wait(nextCpuDelay);
2328                             }
2329                         }
2330                     } catch (InterruptedException e) {
2331                     }
2332                     updateCpuStatsNow();
2333                 } catch (Exception e) {
2334                     Slog.e(TAG, "Unexpected exception collecting process stats", e);
2335                 }
2336             }
2337         }
2338     }
2339 
2340     class CpuBinder extends Binder {
2341         private final PriorityDump.PriorityDumper mPriorityDumper =
2342                 new PriorityDump.PriorityDumper() {
2343             @Override
2344             public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
2345                     boolean asProto) {
2346                 if (!DumpUtils.checkDumpAndUsageStatsPermission(mService.mContext, "cpuinfo", pw)) {
2347                     return;
2348                 }
2349                 synchronized (mProcessCpuTracker) {
2350                     if (asProto) {
2351                         mProcessCpuTracker.dumpProto(fd);
2352                         return;
2353                     }
2354                     pw.print(mProcessCpuTracker.printCurrentLoad());
2355                     pw.print(mProcessCpuTracker.printCurrentState(
2356                             SystemClock.uptimeMillis()));
2357                 }
2358             }
2359         };
2360 
2361         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2362         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2363             PriorityDump.dump(mPriorityDumper, fd, pw, args);
2364         }
2365     }
2366 
setCpuInfoService()2367     void setCpuInfoService() {
2368         if (MONITOR_CPU_USAGE) {
2369             ServiceManager.addService("cpuinfo", new CpuBinder(),
2370                     /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
2371         }
2372     }
2373 
AppProfiler(ActivityManagerService service, Looper bgLooper, LowMemDetector detector)2374     AppProfiler(ActivityManagerService service, Looper bgLooper, LowMemDetector detector) {
2375         mService = service;
2376         mProcLock = service.mProcLock;
2377         mBgHandler = new BgHandler(bgLooper);
2378         mLowMemDetector = detector;
2379         mProcessCpuThread = new ProcessCpuThread("CpuTracker");
2380     }
2381 
retrieveSettings()2382     void retrieveSettings() {
2383         final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
2384                 ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
2385         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
2386                 ActivityThread.currentApplication().getMainExecutor(),
2387                 mPssDelayConfigListener);
2388         mPssDeferralTime = pssDeferralMs;
2389     }
2390 
onActivityManagerInternalAdded()2391     void onActivityManagerInternalAdded() {
2392         mProcessCpuThread.start();
2393         // Wait for the synchronized block started in mProcessCpuThread,
2394         // so that any other access to mProcessCpuTracker from main thread
2395         // will be blocked during mProcessCpuTracker initialization.
2396         try {
2397             mProcessCpuInitLatch.await();
2398         } catch (InterruptedException e) {
2399             Slog.wtf(TAG, "Interrupted wait during start", e);
2400             Thread.currentThread().interrupt();
2401             throw new IllegalStateException("Interrupted wait during start");
2402         }
2403     }
2404 
onActivityLaunched()2405     void onActivityLaunched() {
2406         // This is safe to force to the head of the queue because it relies only
2407         // on refcounting to track begin/end of deferrals, not on actual
2408         // message ordering.  We don't care *what* activity is being
2409         // launched; only that we're doing so.
2410         if (mPssDeferralTime > 0) {
2411             final Message msg = mBgHandler.obtainMessage(BgHandler.DEFER_PSS_MSG);
2412             mBgHandler.sendMessageAtFrontOfQueue(msg);
2413         }
2414     }
2415 
2416     @GuardedBy("mService")
setupProfilerInfoLocked(@onNull IApplicationThread thread, ProcessRecord app, ActiveInstrumentation instr)2417     ProfilerInfo setupProfilerInfoLocked(@NonNull IApplicationThread thread, ProcessRecord app,
2418             ActiveInstrumentation instr) throws IOException, RemoteException {
2419         ProfilerInfo profilerInfo = null;
2420         String preBindAgent = null;
2421         final String processName = app.processName;
2422         synchronized (mProfilerLock) {
2423             if (mProfileData.getProfileApp() != null
2424                     && mProfileData.getProfileApp().equals(processName)) {
2425                 mProfileData.setProfileProc(app);
2426                 if (mProfileData.getProfilerInfo() != null) {
2427                     // Send a profiler info object to the app if either a file is given, or
2428                     // an agent should be loaded at bind-time.
2429                     boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null
2430                             || mProfileData.getProfilerInfo().attachAgentDuringBind;
2431                     profilerInfo = needsInfo
2432                             ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null;
2433                     if (mProfileData.getProfilerInfo().agent != null) {
2434                         preBindAgent = mProfileData.getProfilerInfo().agent;
2435                     }
2436                 }
2437             } else if (instr != null && instr.mProfileFile != null) {
2438                 profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false, null,
2439                         false, 0, ProfilerInfo.OUTPUT_VERSION_DEFAULT);
2440             }
2441             if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
2442                 // We need to do a debuggable check here. See setAgentApp for why the check is
2443                 // postponed to here.
2444                 if (app.isDebuggable()) {
2445                     String agent = mAppAgentMap.get(processName);
2446                     // Do not overwrite already requested agent.
2447                     if (profilerInfo == null) {
2448                         profilerInfo = new ProfilerInfo(null, null, 0, false, false,
2449                                 mAppAgentMap.get(processName), true, 0,
2450                                 ProfilerInfo.OUTPUT_VERSION_DEFAULT);
2451                     } else if (profilerInfo.agent == null) {
2452                         profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
2453                     }
2454                 }
2455             }
2456 
2457             if (profilerInfo != null && profilerInfo.profileFd != null) {
2458                 profilerInfo.profileFd = profilerInfo.profileFd.dup();
2459                 if (TextUtils.equals(mProfileData.getProfileApp(), processName)
2460                         && mProfileData.getProfilerInfo() != null) {
2461                     clearProfilerLPf();
2462                 }
2463             }
2464         }
2465 
2466         // Check if this is a secondary process that should be incorporated into some
2467         // currently active instrumentation.  (Note we do this AFTER all of the profiling
2468         // stuff above because profiling can currently happen only in the primary
2469         // instrumentation process.)
2470         if (mService.mActiveInstrumentation.size() > 0 && instr == null) {
2471             for (int i = mService.mActiveInstrumentation.size() - 1;
2472                     i >= 0 && app.getActiveInstrumentation() == null; i--) {
2473                 ActiveInstrumentation aInstr = mService.mActiveInstrumentation.get(i);
2474                 if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
2475                     synchronized (mProcLock) {
2476                         if (aInstr.mTargetProcesses.length == 0) {
2477                             // This is the wildcard mode, where every process brought up for
2478                             // the target instrumentation should be included.
2479                             if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
2480                                 mService.mProcessStateController.setActiveInstrumentation(app,
2481                                         aInstr);
2482                                 aInstr.mRunningProcesses.add(app);
2483                             }
2484                         } else {
2485                             for (String proc : aInstr.mTargetProcesses) {
2486                                 if (proc.equals(app.processName)) {
2487                                     mService.mProcessStateController.setActiveInstrumentation(app,
2488                                             aInstr);
2489                                     aInstr.mRunningProcesses.add(app);
2490                                     break;
2491                                 }
2492                             }
2493                         }
2494                     }
2495                 }
2496             }
2497         }
2498 
2499         // If we were asked to attach an agent on startup, do so now, before we're binding
2500         // application code.
2501         if (preBindAgent != null) {
2502             thread.attachAgent(preBindAgent);
2503         }
2504         if (app.isDebuggable()) {
2505             thread.attachStartupAgents(app.info.dataDir);
2506         }
2507         return profilerInfo;
2508     }
2509 
2510     @GuardedBy("mService")
onCleanupApplicationRecordLocked(ProcessRecord app)2511     void onCleanupApplicationRecordLocked(ProcessRecord app) {
2512         synchronized (mProfilerLock) {
2513             final ProcessProfileRecord profile = app.mProfile;
2514             mProcessesToGc.remove(app);
2515             mPendingPssOrRssProfiles.remove(profile);
2516             profile.abortNextPssTime();
2517         }
2518     }
2519 
2520     @GuardedBy("mService")
onAppDiedLocked(ProcessRecord app)2521     void onAppDiedLocked(ProcessRecord app) {
2522         synchronized (mProfilerLock) {
2523             if (mProfileData.getProfileProc() == app) {
2524                 clearProfilerLPf();
2525             }
2526         }
2527     }
2528 
2529     @GuardedBy("mProfilerLock")
dumpMemWatchProcessesLPf(PrintWriter pw, boolean needSep)2530     boolean dumpMemWatchProcessesLPf(PrintWriter pw, boolean needSep) {
2531         if (mMemWatchProcesses.getMap().size() > 0) {
2532             pw.println("  Mem watch processes:");
2533             final ArrayMap<String, SparseArray<Pair<Long, String>>> procs =
2534                     mMemWatchProcesses.getMap();
2535             for (int i = procs.size() - 1; i >= 0; i--) {
2536                 final String proc = procs.keyAt(i);
2537                 final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
2538                 for (int j = uids.size() - 1; j >= 0; j--) {
2539                     if (needSep) {
2540                         pw.println();
2541                         needSep = false;
2542                     }
2543                     StringBuilder sb = new StringBuilder();
2544                     sb.append("    ").append(proc).append('/');
2545                     UserHandle.formatUid(sb, uids.keyAt(j));
2546                     Pair<Long, String> val = uids.valueAt(j);
2547                     sb.append(": "); DebugUtils.sizeValueToString(val.first, sb);
2548                     if (val.second != null) {
2549                         sb.append(", report to ").append(val.second);
2550                     }
2551                     pw.println(sb.toString());
2552                 }
2553             }
2554             pw.print("  mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName);
2555             pw.print("  mMemWatchDumpUri="); pw.println(mMemWatchDumpUri);
2556             pw.print("  mMemWatchDumpPid="); pw.println(mMemWatchDumpPid);
2557             pw.print("  mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
2558             pw.print("  mMemWatchIsUserInitiated="); pw.println(mMemWatchIsUserInitiated);
2559         }
2560         return needSep;
2561     }
2562 
2563     @GuardedBy("mService")
dumpProfileDataLocked(PrintWriter pw, String dumpPackage, boolean needSep)2564     boolean dumpProfileDataLocked(PrintWriter pw, String dumpPackage, boolean needSep) {
2565         if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
2566                 || (mProfileData.getProfilerInfo() != null
2567                 && (mProfileData.getProfilerInfo().profileFile != null
2568                         || mProfileData.getProfilerInfo().profileFd != null))) {
2569             if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
2570                 if (needSep) {
2571                     pw.println();
2572                     needSep = false;
2573                 }
2574                 pw.println("  mProfileApp=" + mProfileData.getProfileApp()
2575                         + " mProfileProc=" + mProfileData.getProfileProc());
2576                 if (mProfileData.getProfilerInfo() != null) {
2577                     pw.println("  mProfileFile=" + mProfileData.getProfilerInfo().profileFile
2578                             + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
2579                     pw.println(
2580                             "  mSamplingInterval=" + mProfileData.getProfilerInfo().samplingInterval
2581                             + " mAutoStopProfiler="
2582                             + mProfileData.getProfilerInfo().autoStopProfiler
2583                             + " mStreamingOutput="
2584                             + mProfileData.getProfilerInfo().streamingOutput
2585                             + " mClockType="
2586                             + mProfileData.getProfilerInfo().clockType
2587                             + " mProfilerOutputVersion="
2588                             + mProfileData.getProfilerInfo().profilerOutputVersion);
2589                     pw.println("  mProfileType=" + mProfileType);
2590                 }
2591             }
2592         }
2593         return needSep;
2594     }
2595 
2596     @GuardedBy("mService")
dumpLastMemoryLevelLocked(PrintWriter pw)2597     void dumpLastMemoryLevelLocked(PrintWriter pw) {
2598         switch (mLastMemoryLevel) {
2599             case ADJ_MEM_FACTOR_NORMAL:
2600                 pw.println("normal)");
2601                 break;
2602             case ADJ_MEM_FACTOR_MODERATE:
2603                 pw.println("moderate)");
2604                 break;
2605             case ADJ_MEM_FACTOR_LOW:
2606                 pw.println("low)");
2607                 break;
2608             case ADJ_MEM_FACTOR_CRITICAL:
2609                 pw.println("critical)");
2610                 break;
2611             default:
2612                 pw.print(mLastMemoryLevel);
2613                 pw.println(")");
2614                 break;
2615         }
2616     }
2617 
2618     @GuardedBy("mService")
dumpMemoryLevelsLocked(PrintWriter pw)2619     void dumpMemoryLevelsLocked(PrintWriter pw) {
2620         pw.println("  mAllowLowerMemLevel=" + mAllowLowerMemLevel
2621                 + " mLastMemoryLevel=" + mLastMemoryLevel
2622                 + " mLastNumProcesses=" + mLastNumProcesses);
2623     }
2624 
2625     @GuardedBy("mProfilerLock")
writeMemWatchProcessToProtoLPf(ProtoOutputStream proto)2626     void writeMemWatchProcessToProtoLPf(ProtoOutputStream proto) {
2627         if (mMemWatchProcesses.getMap().size() > 0) {
2628             final long token = proto.start(
2629                     ActivityManagerServiceDumpProcessesProto.MEM_WATCH_PROCESSES);
2630             ArrayMap<String, SparseArray<Pair<Long, String>>> procs = mMemWatchProcesses.getMap();
2631             for (int i = 0; i < procs.size(); i++) {
2632                 final String proc = procs.keyAt(i);
2633                 final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
2634                 final long ptoken = proto.start(
2635                         ActivityManagerServiceDumpProcessesProto.MemWatchProcess.PROCS);
2636                 proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.NAME,
2637                         proc);
2638                 for (int j = uids.size() - 1; j >= 0; j--) {
2639                     final long utoken = proto.start(ActivityManagerServiceDumpProcessesProto
2640                             .MemWatchProcess.Process.MEM_STATS);
2641                     Pair<Long, String> val = uids.valueAt(j);
2642                     proto.write(ActivityManagerServiceDumpProcessesProto
2643                             .MemWatchProcess.Process.MemStats.UID, uids.keyAt(j));
2644                     proto.write(ActivityManagerServiceDumpProcessesProto
2645                             .MemWatchProcess.Process.MemStats.SIZE,
2646                             DebugUtils.sizeValueToString(val.first, new StringBuilder()));
2647                     proto.write(ActivityManagerServiceDumpProcessesProto
2648                             .MemWatchProcess.Process.MemStats.REPORT_TO, val.second);
2649                     proto.end(utoken);
2650                 }
2651                 proto.end(ptoken);
2652             }
2653 
2654             final long dtoken = proto.start(
2655                     ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP);
2656             proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME,
2657                     mMemWatchDumpProcName);
2658             proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.URI,
2659                     mMemWatchDumpUri.toString());
2660             proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID,
2661                     mMemWatchDumpPid);
2662             proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID,
2663                     mMemWatchDumpUid);
2664             proto.write(
2665                     ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.IS_USER_INITIATED,
2666                     mMemWatchIsUserInitiated);
2667             proto.end(dtoken);
2668 
2669             proto.end(token);
2670         }
2671     }
2672 
2673     @GuardedBy("mService")
writeProfileDataToProtoLocked(ProtoOutputStream proto, String dumpPackage)2674     void writeProfileDataToProtoLocked(ProtoOutputStream proto, String dumpPackage) {
2675         if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
2676                 || (mProfileData.getProfilerInfo() != null
2677                 && (mProfileData.getProfilerInfo().profileFile != null
2678                         || mProfileData.getProfilerInfo().profileFd != null))) {
2679             if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
2680                 final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE);
2681                 proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME,
2682                         mProfileData.getProfileApp());
2683                 mProfileData.getProfileProc().dumpDebug(proto,
2684                         ActivityManagerServiceDumpProcessesProto.Profile.PROC);
2685                 if (mProfileData.getProfilerInfo() != null) {
2686                     mProfileData.getProfilerInfo().dumpDebug(proto,
2687                             ActivityManagerServiceDumpProcessesProto.Profile.INFO);
2688                     proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE,
2689                             mProfileType);
2690                 }
2691                 proto.end(token);
2692             }
2693         }
2694     }
2695 
2696     @GuardedBy("mService")
writeMemoryLevelsToProtoLocked(ProtoOutputStream proto)2697     void writeMemoryLevelsToProtoLocked(ProtoOutputStream proto) {
2698         proto.write(ActivityManagerServiceDumpProcessesProto.ALLOW_LOWER_MEM_LEVEL,
2699                 mAllowLowerMemLevel);
2700         proto.write(ActivityManagerServiceDumpProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel);
2701         proto.write(ActivityManagerServiceDumpProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses);
2702     }
2703 
printCurrentCpuState(StringBuilder report, long time)2704     void printCurrentCpuState(StringBuilder report, long time) {
2705         synchronized (mProcessCpuTracker) {
2706             // Only print the first 10 processes
2707             report.append(mProcessCpuTracker.printCurrentState(time, /* maxProcesses= */10));
2708         }
2709     }
2710 
getAppProfileStatsForDebugging(long time, int linesOfStats)2711     Pair<String, String> getAppProfileStatsForDebugging(long time, int linesOfStats) {
2712         String cpuLoad = null;
2713         String stats = null;
2714         synchronized (mProcessCpuTracker) {
2715             updateCpuStatsNow();
2716             cpuLoad = mProcessCpuTracker.printCurrentLoad();
2717             stats = mProcessCpuTracker.printCurrentState(time);
2718         }
2719         // Only return linesOfStats lines of Cpu stats.
2720         int toIndex = 0;
2721         for (int i = 0; i <= linesOfStats; i++) {
2722             int nextIndex = stats.indexOf('\n', toIndex);
2723             if (nextIndex == -1) {
2724                 toIndex = stats.length();
2725                 break;
2726             }
2727             toIndex = nextIndex + 1;
2728         }
2729         return new Pair(cpuLoad, stats.substring(0, toIndex));
2730     }
2731 
2732     @GuardedBy("mProfilerLock")
writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage)2733     void writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
2734         if (mProcessesToGc.size() > 0) {
2735             long now = SystemClock.uptimeMillis();
2736             for (int i = 0, size = mProcessesToGc.size(); i < size; i++) {
2737                 ProcessRecord r = mProcessesToGc.get(i);
2738                 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
2739                     continue;
2740                 }
2741                 final long token = proto.start(fieldId);
2742                 final ProcessProfileRecord profile = r.mProfile;
2743                 r.dumpDebug(proto, ProcessToGcProto.PROC);
2744                 proto.write(ProcessToGcProto.REPORT_LOW_MEMORY, profile.getReportLowMemory());
2745                 proto.write(ProcessToGcProto.NOW_UPTIME_MS, now);
2746                 proto.write(ProcessToGcProto.LAST_GCED_MS, profile.getLastRequestedGc());
2747                 proto.write(ProcessToGcProto.LAST_LOW_MEMORY_MS, profile.getLastLowMemory());
2748                 proto.end(token);
2749             }
2750         }
2751     }
2752 
2753     @GuardedBy("mProfilerLock")
dumpProcessesToGc(PrintWriter pw, boolean needSep, String dumpPackage)2754     boolean dumpProcessesToGc(PrintWriter pw, boolean needSep, String dumpPackage) {
2755         if (mProcessesToGc.size() > 0) {
2756             boolean printed = false;
2757             long now = SystemClock.uptimeMillis();
2758             for (int i = 0, size = mProcessesToGc.size(); i < size; i++) {
2759                 ProcessRecord proc = mProcessesToGc.get(i);
2760                 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
2761                     continue;
2762                 }
2763                 if (!printed) {
2764                     if (needSep) pw.println();
2765                     needSep = true;
2766                     pw.println("  Processes that are waiting to GC:");
2767                     printed = true;
2768                 }
2769                 pw.print("    Process "); pw.println(proc);
2770                 final ProcessProfileRecord profile = proc.mProfile;
2771                 pw.print("      lowMem="); pw.print(profile.getReportLowMemory());
2772                 pw.print(", last gced=");
2773                 pw.print(now - profile.getLastRequestedGc());
2774                 pw.print(" ms ago, last lowMem=");
2775                 pw.print(now - profile.getLastLowMemory());
2776                 pw.println(" ms ago");
2777 
2778             }
2779         }
2780         return needSep;
2781     }
2782 }
2783