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