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