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