1 /*
2  * Copyright (C) 2019 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_CAPABILITY_ALL;
20 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
21 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
22 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
23 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
24 import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
25 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
26 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
27 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
28 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
29 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
30 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
31 import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
32 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
33 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
34 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
35 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
36 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
37 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
38 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
39 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
40 import static android.app.ActivityManager.PROCESS_STATE_TOP;
41 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
42 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
43 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
44 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
45 import static android.os.Process.SCHED_OTHER;
46 import static android.os.Process.THREAD_GROUP_BACKGROUND;
47 import static android.os.Process.THREAD_GROUP_DEFAULT;
48 import static android.os.Process.THREAD_GROUP_RESTRICTED;
49 import static android.os.Process.THREAD_GROUP_TOP_APP;
50 import static android.os.Process.THREAD_PRIORITY_DISPLAY;
51 import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
52 import static android.os.Process.setProcessGroup;
53 import static android.os.Process.setThreadPriority;
54 import static android.os.Process.setThreadScheduler;
55 
56 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
58 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
59 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON;
61 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
62 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
63 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
64 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
65 import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG;
66 import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG;
67 import static com.android.server.am.ActivityManagerService.TAG_BACKUP;
68 import static com.android.server.am.ActivityManagerService.TAG_LRU;
69 import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ;
70 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
71 import static com.android.server.am.AppProfiler.TAG_PSS;
72 import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS;
73 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
74 
75 import android.annotation.IntDef;
76 import android.annotation.Nullable;
77 import android.app.ActivityManager;
78 import android.app.ActivityThread;
79 import android.app.ApplicationExitInfo;
80 import android.app.usage.UsageEvents;
81 import android.compat.annotation.ChangeId;
82 import android.compat.annotation.EnabledAfter;
83 import android.compat.annotation.EnabledSince;
84 import android.content.BroadcastReceiver;
85 import android.content.ComponentName;
86 import android.content.Context;
87 import android.content.Intent;
88 import android.content.IntentFilter;
89 import android.content.pm.ApplicationInfo;
90 import android.content.pm.ServiceInfo;
91 import android.os.Handler;
92 import android.os.IBinder;
93 import android.os.PowerManagerInternal;
94 import android.os.Process;
95 import android.os.RemoteException;
96 import android.os.ServiceManager;
97 import android.os.SystemClock;
98 import android.os.Trace;
99 import android.util.ArrayMap;
100 import android.util.ArraySet;
101 import android.util.LongSparseArray;
102 import android.util.Pair;
103 import android.util.Slog;
104 import android.util.proto.ProtoOutputStream;
105 
106 import com.android.internal.annotations.CompositeRWLock;
107 import com.android.internal.annotations.GuardedBy;
108 import com.android.internal.annotations.VisibleForTesting;
109 import com.android.internal.compat.IPlatformCompat;
110 import com.android.server.LocalServices;
111 import com.android.server.ServiceThread;
112 import com.android.server.compat.CompatChange;
113 import com.android.server.compat.PlatformCompat;
114 import com.android.server.wm.ActivityServiceConnectionsHolder;
115 import com.android.server.wm.WindowProcessController;
116 
117 import java.io.PrintWriter;
118 import java.lang.annotation.Retention;
119 import java.lang.annotation.RetentionPolicy;
120 import java.lang.ref.WeakReference;
121 import java.util.ArrayDeque;
122 import java.util.ArrayList;
123 import java.util.Arrays;
124 
125 /**
126  * All of the code required to compute proc states and oom_adj values.
127  */
128 public class OomAdjuster {
129     static final String TAG = "OomAdjuster";
130     static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
131     static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
132     static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
133     static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
134     static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
135     static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
136     static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
137     static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
138     static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
139     static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
140     static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
141     static final String OOM_ADJ_REASON_ALLOWLIST = OOM_ADJ_REASON_METHOD + "_allowlistChange";
142     static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
143     static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";
144 
145     /**
146      * Flag {@link android.content.Context#BIND_INCLUDE_CAPABILITIES} is used
147      * to pass while-in-use capabilities from client process to bound service. In targetSdkVersion
148      * R and above, if client is a TOP activity, when this flag is present, bound service gets all
149      * while-in-use capabilities; when this flag is not present, bound service gets no while-in-use
150      * capability from client.
151      */
152     @ChangeId
153     @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
154     static final long PROCESS_CAPABILITY_CHANGE_ID = 136274596L;
155 
156     /**
157      * In targetSdkVersion R and above, foreground service has camera and microphone while-in-use
158      * capability only when the {@link android.R.attr#foregroundServiceType} is configured as
159      * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and
160      * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the
161      * manifest file.
162      * In targetSdkVersion below R, foreground service automatically have camera and microphone
163      * capabilities.
164      */
165     @ChangeId
166     @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
167     static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
168 
169     /**
170      * For apps targeting S+, this determines whether to use a shorter timeout before elevating the
171      * standby bucket to ACTIVE when apps start a foreground service.
172      */
173     @ChangeId
174     @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
175     static final long USE_SHORT_FGS_USAGE_INTERACTION_TIME = 183972877L;
176 
177     static final int CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY = 0;
178     static final int CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY = 1;
179     static final int CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME = 2;
180 
181     @IntDef(prefix = { "CACHED_COMPAT_CHANGE_" }, value = {
182         CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY,
183         CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY,
184         CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME,
185     })
186     @Retention(RetentionPolicy.SOURCE)
187     static @interface CachedCompatChangeId{}
188 
189     /**
190      * Mapping from CACHED_COMPAT_CHANGE_* to the actual compat change id.
191      */
192     static final long[] CACHED_COMPAT_CHANGE_IDS_MAPPING = new long[] {
193         PROCESS_CAPABILITY_CHANGE_ID,
194         CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID,
195         USE_SHORT_FGS_USAGE_INTERACTION_TIME,
196     };
197 
198     /**
199      * For some direct access we need to power manager.
200      */
201     PowerManagerInternal mLocalPowerManager;
202 
203     /**
204      * Service for optimizing resource usage from background apps.
205      */
206     CachedAppOptimizer mCachedAppOptimizer;
207 
208     /**
209      * Re-rank apps getting a cache oom adjustment from lru to weighted order
210      * based on weighted scores for LRU, PSS and cache use count.
211      */
212     CacheOomRanker mCacheOomRanker;
213 
214     ActivityManagerConstants mConstants;
215 
216     final long[] mTmpLong = new long[3];
217 
218     /**
219      * Current sequence id for oom_adj computation traversal.
220      */
221     int mAdjSeq = 0;
222 
223     /**
224      * Keep track of the number of service processes we last found, to
225      * determine on the next iteration which should be B services.
226      */
227     int mNumServiceProcs = 0;
228     int mNewNumAServiceProcs = 0;
229     int mNewNumServiceProcs = 0;
230 
231     /**
232      * Keep track of the non-cached/empty process we last found, to help
233      * determine how to distribute cached/empty processes next time.
234      */
235     int mNumNonCachedProcs = 0;
236 
237     /**
238      * Keep track of the number of cached hidden procs, to balance oom adj
239      * distribution between those and empty procs.
240      */
241     int mNumCachedHiddenProcs = 0;
242 
243     /** Track all uids that have actively running processes. */
244     @CompositeRWLock({"mService", "mProcLock"})
245     ActiveUids mActiveUids;
246 
247     /**
248      * The handler to execute {@link #setProcessGroup} (it may be heavy if the process has many
249      * threads) for reducing the time spent in {@link #applyOomAdjLSP}.
250      */
251     private final Handler mProcessGroupHandler;
252 
253     private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
254 
255     private final ActivityManagerService mService;
256     private final ProcessList mProcessList;
257     private final ActivityManagerGlobalLock mProcLock;
258 
259     private final int mNumSlots;
260     private final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
261     private final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
262     private final ActiveUids mTmpUidRecords;
263     private final ArrayDeque<ProcessRecord> mTmpQueue;
264     private final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>();
265     private final ArraySet<ProcessRecord> mProcessesInCycle = new ArraySet<>();
266 
267     /**
268      * Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate
269      * could be called recursively because of the indirect calls during the update;
270      * however the oomAdjUpdate itself doesn't support recursion - in this case we'd
271      * have to queue up the new targets found during the update, and perform another
272      * round of oomAdjUpdate at the end of last update.
273      */
274     @GuardedBy("mService")
275     private boolean mOomAdjUpdateOngoing = false;
276 
277     /**
278      * Flag to mark if there is a pending full oomAdjUpdate.
279      */
280     @GuardedBy("mService")
281     private boolean mPendingFullOomAdjUpdate = false;
282 
283     private final PlatformCompatCache mPlatformCompatCache;
284 
285     /** Overrideable by a test */
286     @VisibleForTesting
287     static class PlatformCompatCache {
288         private final PlatformCompat mPlatformCompat;
289         private final IPlatformCompat mIPlatformCompatProxy;
290         private final LongSparseArray<CacheItem> mCaches = new LongSparseArray<>();
291         private final boolean mCacheEnabled;
292 
PlatformCompatCache(long[] compatChanges)293         PlatformCompatCache(long[] compatChanges) {
294             IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
295             if (b instanceof PlatformCompat) {
296                 mPlatformCompat = (PlatformCompat) ServiceManager.getService(
297                         Context.PLATFORM_COMPAT_SERVICE);
298                 for (long changeId: compatChanges) {
299                     mCaches.put(changeId, new CacheItem(mPlatformCompat, changeId));
300                 }
301                 mIPlatformCompatProxy = null;
302                 mCacheEnabled = true;
303             } else {
304                 // we are in UT where the platform_compat is not running within the same process
305                 mIPlatformCompatProxy = IPlatformCompat.Stub.asInterface(b);
306                 mPlatformCompat = null;
307                 mCacheEnabled = false;
308             }
309         }
310 
isChangeEnabled(long changeId, ApplicationInfo app)311         boolean isChangeEnabled(long changeId, ApplicationInfo app) throws RemoteException {
312             return mCacheEnabled ? mCaches.get(changeId).isChangeEnabled(app)
313                     : mIPlatformCompatProxy.isChangeEnabled(changeId, app);
314         }
315 
316         /**
317          * Same as {@link #isChangeEnabled(long, ApplicationInfo)} but instead of throwing a
318          * RemoteException from platform compat, it returns the default value provided.
319          */
isChangeEnabled(long changeId, ApplicationInfo app, boolean defaultValue)320         boolean isChangeEnabled(long changeId, ApplicationInfo app, boolean defaultValue) {
321             try {
322                 return mCacheEnabled ? mCaches.get(changeId).isChangeEnabled(app)
323                         : mIPlatformCompatProxy.isChangeEnabled(changeId, app);
324             } catch (RemoteException e) {
325                 Slog.w(TAG, "Error reading platform compat change " + changeId, e);
326                 return defaultValue;
327             }
328         }
329 
invalidate(ApplicationInfo app)330         void invalidate(ApplicationInfo app) {
331             for (int i = mCaches.size() - 1; i >= 0; i--) {
332                 mCaches.valueAt(i).invalidate(app);
333             }
334         }
335 
336         static class CacheItem implements CompatChange.ChangeListener {
337             private final PlatformCompat mPlatformCompat;
338             private final long mChangeId;
339             private final Object mLock = new Object();
340 
341             private final ArrayMap<String, Pair<Boolean, WeakReference<ApplicationInfo>>> mCache =
342                     new ArrayMap<>();
343 
CacheItem(PlatformCompat platformCompat, long changeId)344             CacheItem(PlatformCompat platformCompat, long changeId) {
345                 mPlatformCompat = platformCompat;
346                 mChangeId = changeId;
347                 mPlatformCompat.registerListener(changeId, this);
348             }
349 
isChangeEnabled(ApplicationInfo app)350             boolean isChangeEnabled(ApplicationInfo app) {
351                 synchronized (mLock) {
352                     final int index = mCache.indexOfKey(app.packageName);
353                     Pair<Boolean, WeakReference<ApplicationInfo>> p;
354                     if (index < 0) {
355                         p = new Pair<>(mPlatformCompat.isChangeEnabledInternalNoLogging(mChangeId,
356                                                                                         app),
357                                 new WeakReference<>(app));
358                         mCache.put(app.packageName, p);
359                         return p.first;
360                     }
361                     p = mCache.valueAt(index);
362                     if (p.second.get() == app) {
363                         return p.first;
364                     }
365                     // Cache is invalid, regenerate it
366                     p = new Pair<>(mPlatformCompat.isChangeEnabledInternalNoLogging(mChangeId,
367                                                                                     app),
368                             new WeakReference<>(app));
369                     mCache.setValueAt(index, p);
370                     return p.first;
371                 }
372             }
373 
invalidate(ApplicationInfo app)374             void invalidate(ApplicationInfo app) {
375                 synchronized (mLock) {
376                     mCache.remove(app.packageName);
377                 }
378             }
379 
380             @Override
onCompatChange(String packageName)381             public void onCompatChange(String packageName) {
382                 synchronized (mLock) {
383                     mCache.remove(packageName);
384                 }
385             }
386         }
387     }
388 
389     /** Overrideable by a test */
390     @VisibleForTesting
getPlatformCompatCache()391     protected PlatformCompatCache getPlatformCompatCache() {
392         return mPlatformCompatCache;
393     }
394 
isChangeEnabled(@achedCompatChangeId int cachedCompatChangeId, ApplicationInfo app, boolean defaultValue)395     boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, ApplicationInfo app,
396             boolean defaultValue) {
397         return getPlatformCompatCache().isChangeEnabled(
398                 CACHED_COMPAT_CHANGE_IDS_MAPPING[cachedCompatChangeId], app, defaultValue);
399     }
400 
OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids)401     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
402         this(service, processList, activeUids, createAdjusterThread());
403     }
404 
createAdjusterThread()405     private static ServiceThread createAdjusterThread() {
406         // The process group is usually critical to the response time of foreground app, so the
407         // setter should apply it as soon as possible.
408         final ServiceThread adjusterThread =
409                 new ServiceThread(TAG, THREAD_PRIORITY_TOP_APP_BOOST, false /* allowIo */);
410         adjusterThread.start();
411         return adjusterThread;
412     }
413 
OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, ServiceThread adjusterThread)414     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
415             ServiceThread adjusterThread) {
416         mService = service;
417         mProcessList = processList;
418         mProcLock = service.mProcLock;
419         mActiveUids = activeUids;
420 
421         mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
422         mConstants = mService.mConstants;
423         mCachedAppOptimizer = new CachedAppOptimizer(mService);
424         mCacheOomRanker = new CacheOomRanker(service);
425 
426         mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
427             final int pid = msg.arg1;
428             final int group = msg.arg2;
429             if (pid == ActivityManagerService.MY_PID) {
430                 // Skip setting the process group for system_server, keep it as default.
431                 return true;
432             }
433             if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
434                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup "
435                         + msg.obj + " to " + group);
436             }
437             try {
438                 setProcessGroup(pid, group);
439             } catch (Exception e) {
440                 if (DEBUG_ALL) {
441                     Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e);
442                 }
443             } finally {
444                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
445             }
446             return true;
447         });
448         mTmpUidRecords = new ActiveUids(service, false);
449         mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1);
450         mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1)
451                 / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
452         mPlatformCompatCache = new PlatformCompatCache(new long[] {
453                 PROCESS_CAPABILITY_CHANGE_ID, CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID,
454                 USE_SHORT_FGS_USAGE_INTERACTION_TIME
455         });
456     }
457 
initSettings()458     void initSettings() {
459         mCachedAppOptimizer.init();
460         mCacheOomRanker.init(ActivityThread.currentApplication().getMainExecutor());
461         if (mService.mConstants.KEEP_WARMING_SERVICES.size() > 0) {
462             final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
463             mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
464                 @Override
465                 public void onReceive(Context context, Intent intent) {
466                     synchronized (mService) {
467                         handleUserSwitchedLocked();
468                     }
469                 }
470             }, filter, null, mService.mHandler);
471         }
472     }
473 
474     /**
475      * Update the keep-warming service flags upon user switches
476      */
477     @VisibleForTesting
478     @GuardedBy("mService")
handleUserSwitchedLocked()479     void handleUserSwitchedLocked() {
480         mProcessList.forEachLruProcessesLOSP(false,
481                 this::updateKeepWarmIfNecessaryForProcessLocked);
482     }
483 
484     @GuardedBy("mService")
updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app)485     private void updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app) {
486         final ArraySet<ComponentName> warmServices = mService.mConstants.KEEP_WARMING_SERVICES;
487         boolean includeWarmPkg = false;
488         final PackageList pkgList = app.getPkgList();
489         for (int j = warmServices.size() - 1; j >= 0; j--) {
490             if (pkgList.containsKey(warmServices.valueAt(j).getPackageName())) {
491                 includeWarmPkg = true;
492                 break;
493             }
494         }
495         if (!includeWarmPkg) {
496             return;
497         }
498         final ProcessServiceRecord psr = app.mServices;
499         for (int j = psr.numberOfRunningServices() - 1; j >= 0; j--) {
500             psr.getRunningServiceAt(j).updateKeepWarmLocked();
501         }
502     }
503 
504     /**
505      * Perform oom adj update on the given process. It does NOT do the re-computation
506      * if there is a cycle, caller should check {@link #mProcessesInCycle} and do it on its own.
507      */
508     @GuardedBy({"mService", "mProcLock"})
performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj, ProcessRecord topApp, long now)509     private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj,
510             ProcessRecord topApp, long now) {
511         if (app.getThread() == null) {
512             return false;
513         }
514 
515         app.mState.resetCachedInfo();
516         UidRecord uidRec = app.getUidRecord();
517         if (uidRec != null) {
518             if (DEBUG_UID_OBSERVERS) {
519                 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
520             }
521             uidRec.reset();
522         }
523 
524         // Check if this process is in the pending list too, remove from pending list if so.
525         mPendingProcessSet.remove(app);
526 
527         mProcessesInCycle.clear();
528         computeOomAdjLSP(app, cachedAdj, topApp, false, now, false, true);
529         if (!mProcessesInCycle.isEmpty()) {
530             // We can't use the score here if there is a cycle, abort.
531             for (int i = mProcessesInCycle.size() - 1; i >= 0; i--) {
532                 // Reset the adj seq
533                 mProcessesInCycle.valueAt(i).mState.setCompletedAdjSeq(mAdjSeq - 1);
534             }
535             return true;
536         }
537 
538         if (uidRec != null) {
539             // After uidRec.reset() above, for UidRecord with multiple processes (ProcessRecord),
540             // we need to apply all ProcessRecord into UidRecord.
541             uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP);
542             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
543                     && (uidRec.getSetProcState() != uidRec.getCurProcState()
544                     || uidRec.getSetCapability() != uidRec.getCurCapability()
545                     || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) {
546                 ActiveUids uids = mTmpUidRecords;
547                 uids.clear();
548                 uids.put(uidRec.getUid(), uidRec);
549                 updateUidsLSP(uids, SystemClock.elapsedRealtime());
550                 mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(uids);
551             }
552         }
553 
554         return applyOomAdjLSP(app, false, now, SystemClock.elapsedRealtime());
555     }
556 
557     /**
558      * Update OomAdj for all processes in LRU list
559      */
560     @GuardedBy("mService")
updateOomAdjLocked(String oomAdjReason)561     void updateOomAdjLocked(String oomAdjReason) {
562         synchronized (mProcLock) {
563             updateOomAdjLSP(oomAdjReason);
564         }
565     }
566 
567     @GuardedBy({"mService", "mProcLock"})
updateOomAdjLSP(String oomAdjReason)568     private void updateOomAdjLSP(String oomAdjReason) {
569         if (checkAndEnqueueOomAdjTargetLocked(null)) {
570             // Simply return as there is an oomAdjUpdate ongoing
571             return;
572         }
573         try {
574             mOomAdjUpdateOngoing = true;
575             performUpdateOomAdjLSP(oomAdjReason);
576         } finally {
577             // Kick off the handling of any pending targets enqueued during the above update
578             mOomAdjUpdateOngoing = false;
579             updateOomAdjPendingTargetsLocked(oomAdjReason);
580         }
581     }
582 
583     @GuardedBy({"mService", "mProcLock"})
performUpdateOomAdjLSP(String oomAdjReason)584     private void performUpdateOomAdjLSP(String oomAdjReason) {
585         final ProcessRecord topApp = mService.getTopApp();
586         // Clear any pending ones because we are doing a full update now.
587         mPendingProcessSet.clear();
588         mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false;
589         updateOomAdjInnerLSP(oomAdjReason, topApp , null, null, true, true);
590     }
591 
592     /**
593      * Update OomAdj for specific process and its reachable processes (with direction/indirect
594      * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc
595      * is hosting any service/content provider.
596      *
597      * @param app The process to update, or null to update all processes
598      * @param oomAdjReason
599      */
600     @GuardedBy("mService")
updateOomAdjLocked(ProcessRecord app, String oomAdjReason)601     boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
602         synchronized (mProcLock) {
603             return updateOomAdjLSP(app, oomAdjReason);
604         }
605     }
606 
607     @GuardedBy({"mService", "mProcLock"})
updateOomAdjLSP(ProcessRecord app, String oomAdjReason)608     private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
609         if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
610             updateOomAdjLSP(oomAdjReason);
611             return true;
612         }
613 
614         if (checkAndEnqueueOomAdjTargetLocked(app)) {
615             // Simply return true as there is an oomAdjUpdate ongoing
616             return true;
617         }
618 
619         try {
620             mOomAdjUpdateOngoing = true;
621             return performUpdateOomAdjLSP(app, oomAdjReason);
622         } finally {
623             // Kick off the handling of any pending targets enqueued during the above update
624             mOomAdjUpdateOngoing = false;
625             updateOomAdjPendingTargetsLocked(oomAdjReason);
626         }
627     }
628 
629     @GuardedBy({"mService", "mProcLock"})
performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason)630     private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
631         final ProcessRecord topApp = mService.getTopApp();
632 
633         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
634         mService.mOomAdjProfiler.oomAdjStarted();
635         mAdjSeq++;
636 
637         // Firstly, try to see if the importance of itself gets changed
638         final ProcessStateRecord state = app.mState;
639         final boolean wasCached = state.isCached();
640         final int oldAdj = state.getCurRawAdj();
641         final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
642                 ? oldAdj : ProcessList.UNKNOWN_ADJ;
643         final boolean wasBackground = ActivityManager.isProcStateBackground(
644                 state.getSetProcState());
645         final int oldCap = state.getSetCapability();
646         state.setContainsCycle(false);
647         state.setProcStateChanged(false);
648         state.resetCachedInfo();
649         // Check if this process is in the pending list too, remove from pending list if so.
650         mPendingProcessSet.remove(app);
651         boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp,
652                 SystemClock.uptimeMillis());
653         // The 'app' here itself might or might not be in the cycle, for example,
654         // the case A <=> B vs. A -> B <=> C; anyway, if we spot a cycle here, re-compute them.
655         if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ
656                 && mProcessesInCycle.isEmpty() /* Force re-compute if there is a cycle */
657                 && oldCap == state.getCurCapability()
658                 && wasBackground == ActivityManager.isProcStateBackground(
659                         state.getSetProcState()))) {
660             mProcessesInCycle.clear();
661             // Okay, it's unchanged, it won't impact any service it binds to, we're done here.
662             if (DEBUG_OOM_ADJ) {
663                 Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
664             }
665             mService.mOomAdjProfiler.oomAdjEnded();
666             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
667             return success;
668         }
669 
670         // Next to find out all its reachable processes
671         ArrayList<ProcessRecord> processes = mTmpProcessList;
672         ActiveUids uids = mTmpUidRecords;
673         mPendingProcessSet.add(app);
674 
675         // Add all processes with cycles into the list to scan
676         for (int i = mProcessesInCycle.size() - 1; i >= 0; i--) {
677             mPendingProcessSet.add(mProcessesInCycle.valueAt(i));
678         }
679         mProcessesInCycle.clear();
680 
681         boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet,
682                 processes, uids);
683 
684         // Clear the pending set as they should've been included in 'processes'.
685         mPendingProcessSet.clear();
686 
687         if (!containsCycle) {
688             // Reset the flag
689             state.setReachable(false);
690             // Remove this app from the return list because we've done the computation on it.
691             processes.remove(app);
692         }
693 
694         int size = processes.size();
695         if (size > 0) {
696             mAdjSeq--;
697             // Update these reachable processes
698             updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
699         } else if (state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
700             // In case the app goes from non-cached to cached but it doesn't have other reachable
701             // processes, its adj could be still unknown as of now, assign one.
702             processes.add(app);
703             assignCachedAdjIfNecessary(processes);
704             applyOomAdjLSP(app, false, SystemClock.uptimeMillis(),
705                     SystemClock.elapsedRealtime());
706         }
707         mTmpProcessList.clear();
708         mService.mOomAdjProfiler.oomAdjEnded();
709         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
710         return true;
711     }
712 
713     @GuardedBy("mService")
collectReachableProcessesLocked(ArraySet<ProcessRecord> apps, ArrayList<ProcessRecord> processes, ActiveUids uids)714     private boolean collectReachableProcessesLocked(ArraySet<ProcessRecord> apps,
715             ArrayList<ProcessRecord> processes, ActiveUids uids) {
716         final ArrayDeque<ProcessRecord> queue = mTmpQueue;
717         queue.clear();
718         processes.clear();
719         for (int i = 0, size = apps.size(); i < size; i++) {
720             final ProcessRecord app = apps.valueAt(i);
721             app.mState.setReachable(true);
722             queue.offer(app);
723         }
724 
725         uids.clear();
726 
727         // Track if any of them reachables could include a cycle
728         boolean containsCycle = false;
729         // Scan downstreams of the process record
730         for (ProcessRecord pr = queue.poll(); pr != null; pr = queue.poll()) {
731             processes.add(pr);
732             final UidRecord uidRec = pr.getUidRecord();
733             if (uidRec != null) {
734                 uids.put(uidRec.getUid(), uidRec);
735             }
736             final ProcessServiceRecord psr = pr.mServices;
737             for (int i = psr.numberOfConnections() - 1; i >= 0; i--) {
738                 ConnectionRecord cr = psr.getConnectionAt(i);
739                 ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
740                         ? cr.binding.service.isolatedProc : cr.binding.service.app;
741                 if (service == null || service == pr) {
742                     continue;
743                 }
744                 containsCycle |= service.mState.isReachable();
745                 if (service.mState.isReachable()) {
746                     continue;
747                 }
748                 if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
749                         | Context.BIND_TREAT_LIKE_ACTIVITY
750                         | Context.BIND_ADJUST_WITH_ACTIVITY))
751                         == Context.BIND_WAIVE_PRIORITY) {
752                     continue;
753                 }
754                 queue.offer(service);
755                 service.mState.setReachable(true);
756             }
757             final ProcessProviderRecord ppr = pr.mProviders;
758             for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) {
759                 ContentProviderConnection cpc = ppr.getProviderConnectionAt(i);
760                 ProcessRecord provider = cpc.provider.proc;
761                 if (provider == null || provider == pr) {
762                     continue;
763                 }
764                 containsCycle |= provider.mState.isReachable();
765                 if (provider.mState.isReachable()) {
766                     continue;
767                 }
768                 queue.offer(provider);
769                 provider.mState.setReachable(true);
770             }
771         }
772 
773         int size = processes.size();
774         if (size > 0) {
775             // Reverse the process list, since the updateOomAdjInnerLSP scans from the end of it.
776             for (int l = 0, r = size - 1; l < r; l++, r--) {
777                 ProcessRecord t = processes.get(l);
778                 processes.set(l, processes.get(r));
779                 processes.set(r, t);
780             }
781         }
782         return containsCycle;
783     }
784 
785     /**
786      * Enqueue the given process for a later oom adj update
787      */
788     @GuardedBy("mService")
enqueueOomAdjTargetLocked(ProcessRecord app)789     void enqueueOomAdjTargetLocked(ProcessRecord app) {
790         if (app != null) {
791             mPendingProcessSet.add(app);
792         }
793     }
794 
795     @GuardedBy("mService")
removeOomAdjTargetLocked(ProcessRecord app, boolean procDied)796     void removeOomAdjTargetLocked(ProcessRecord app, boolean procDied) {
797         if (app != null) {
798             mPendingProcessSet.remove(app);
799             if (procDied) {
800                 getPlatformCompatCache().invalidate(app.info);
801             }
802         }
803     }
804 
805     /**
806      * Check if there is an ongoing oomAdjUpdate, enqueue the given process record
807      * to {@link #mPendingProcessSet} if there is one.
808      *
809      * @param app The target app to get an oomAdjUpdate, or a full oomAdjUpdate if it's null.
810      * @return {@code true} if there is an ongoing oomAdjUpdate.
811      */
812     @GuardedBy("mService")
checkAndEnqueueOomAdjTargetLocked(@ullable ProcessRecord app)813     private boolean checkAndEnqueueOomAdjTargetLocked(@Nullable ProcessRecord app) {
814         if (!mOomAdjUpdateOngoing) {
815             return false;
816         }
817         if (app != null) {
818             mPendingProcessSet.add(app);
819         } else {
820             mPendingFullOomAdjUpdate = true;
821         }
822         return true;
823     }
824 
825     /**
826      * Kick off an oom adj update pass for the pending targets which are enqueued via
827      * {@link #enqueueOomAdjTargetLocked}.
828      */
829     @GuardedBy("mService")
updateOomAdjPendingTargetsLocked(String oomAdjReason)830     void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
831         // First check if there is pending full update
832         if (mPendingFullOomAdjUpdate) {
833             mPendingFullOomAdjUpdate = false;
834             mPendingProcessSet.clear();
835             updateOomAdjLocked(oomAdjReason);
836             return;
837         }
838         if (mPendingProcessSet.isEmpty()) {
839             return;
840         }
841 
842         if (mOomAdjUpdateOngoing) {
843             // There's another oomAdjUpdate ongoing, return from here now;
844             // that ongoing update would call us again at the end of it.
845             return;
846         }
847         try {
848             mOomAdjUpdateOngoing = true;
849             performUpdateOomAdjPendingTargetsLocked(oomAdjReason);
850         } finally {
851             // Kick off the handling of any pending targets enqueued during the above update
852             mOomAdjUpdateOngoing = false;
853             updateOomAdjPendingTargetsLocked(oomAdjReason);
854         }
855     }
856 
857     @GuardedBy("mService")
performUpdateOomAdjPendingTargetsLocked(String oomAdjReason)858     private void performUpdateOomAdjPendingTargetsLocked(String oomAdjReason) {
859         final ProcessRecord topApp = mService.getTopApp();
860 
861         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
862         mService.mOomAdjProfiler.oomAdjStarted();
863 
864         final ArrayList<ProcessRecord> processes = mTmpProcessList;
865         final ActiveUids uids = mTmpUidRecords;
866         collectReachableProcessesLocked(mPendingProcessSet, processes, uids);
867         mPendingProcessSet.clear();
868         synchronized (mProcLock) {
869             updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false);
870         }
871         processes.clear();
872 
873         mService.mOomAdjProfiler.oomAdjEnded();
874         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
875     }
876 
877     /**
878      * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
879      * list if the given list is null; when it's partial update, each process's client proc won't
880      * get evaluated recursively here.
881      */
882     @GuardedBy({"mService", "mProcLock"})
updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp, ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles, boolean startProfiling)883     private void updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp,
884             ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
885             boolean startProfiling) {
886         if (startProfiling) {
887             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
888             mService.mOomAdjProfiler.oomAdjStarted();
889         }
890         final long now = SystemClock.uptimeMillis();
891         final long nowElapsed = SystemClock.elapsedRealtime();
892         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
893         final boolean fullUpdate = processes == null;
894         ActiveUids activeUids = uids;
895         ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP()
896                 : processes;
897         final int numProc = activeProcesses.size();
898 
899         if (activeUids == null) {
900             final int numUids = mActiveUids.size();
901             activeUids = mTmpUidRecords;
902             activeUids.clear();
903             for (int i = 0; i < numUids; i++) {
904                 UidRecord uidRec = mActiveUids.valueAt(i);
905                 activeUids.put(uidRec.getUid(), uidRec);
906             }
907         }
908 
909         // Reset state in all uid records.
910         for (int  i = activeUids.size() - 1; i >= 0; i--) {
911             final UidRecord uidRec = activeUids.valueAt(i);
912             if (DEBUG_UID_OBSERVERS) {
913                 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
914             }
915             uidRec.reset();
916         }
917 
918         mAdjSeq++;
919         if (fullUpdate) {
920             mNewNumServiceProcs = 0;
921             mNewNumAServiceProcs = 0;
922         }
923 
924         boolean retryCycles = false;
925         boolean computeClients = fullUpdate || potentialCycles;
926 
927         // need to reset cycle state before calling computeOomAdjLSP because of service conns
928         for (int i = numProc - 1; i >= 0; i--) {
929             ProcessRecord app = activeProcesses.get(i);
930             final ProcessStateRecord state = app.mState;
931             state.setReachable(false);
932             // No need to compute again it has been evaluated in previous iteration
933             if (state.getAdjSeq() != mAdjSeq) {
934                 state.setContainsCycle(false);
935                 state.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
936                 state.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
937                 state.setSetCapability(PROCESS_CAPABILITY_NONE);
938                 state.resetCachedInfo();
939             }
940         }
941         mProcessesInCycle.clear();
942         for (int i = numProc - 1; i >= 0; i--) {
943             ProcessRecord app = activeProcesses.get(i);
944             final ProcessStateRecord state = app.mState;
945             if (!app.isKilledByAm() && app.getThread() != null) {
946                 state.setProcStateChanged(false);
947                 computeOomAdjLSP(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
948                         computeClients); // It won't enter cycle if not computing clients.
949                 // if any app encountered a cycle, we need to perform an additional loop later
950                 retryCycles |= state.containsCycle();
951                 // Keep the completedAdjSeq to up to date.
952                 state.setCompletedAdjSeq(mAdjSeq);
953             }
954         }
955 
956         if (mCacheOomRanker.useOomReranking()) {
957             mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(),
958                     mProcessList.getLruProcessServiceStartLOSP());
959         }
960         assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
961 
962         if (computeClients) { // There won't be cycles if we didn't compute clients above.
963             // Cycle strategy:
964             // - Retry computing any process that has encountered a cycle.
965             // - Continue retrying until no process was promoted.
966             // - Iterate from least important to most important.
967             int cycleCount = 0;
968             while (retryCycles && cycleCount < 10) {
969                 cycleCount++;
970                 retryCycles = false;
971 
972                 for (int i = 0; i < numProc; i++) {
973                     ProcessRecord app = activeProcesses.get(i);
974                     final ProcessStateRecord state = app.mState;
975                     if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
976                         state.decAdjSeq();
977                         state.decCompletedAdjSeq();
978                     }
979                 }
980 
981                 for (int i = 0; i < numProc; i++) {
982                     ProcessRecord app = activeProcesses.get(i);
983                     final ProcessStateRecord state = app.mState;
984                     if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
985                         if (computeOomAdjLSP(app, state.getCurRawAdj(), topApp, true, now,
986                                 true, true)) {
987                             retryCycles = true;
988                         }
989                     }
990                 }
991             }
992         }
993         mProcessesInCycle.clear();
994 
995         mNumNonCachedProcs = 0;
996         mNumCachedHiddenProcs = 0;
997 
998         boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids);
999         mNumServiceProcs = mNewNumServiceProcs;
1000 
1001         if (mService.mAlwaysFinishActivities) {
1002             // Need to do this on its own message because the stack may not
1003             // be in a consistent state at this point.
1004             mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
1005         }
1006 
1007         if (allChanged) {
1008             mService.mAppProfiler.requestPssAllProcsLPr(now, false,
1009                     mService.mProcessStats.isMemFactorLowered());
1010         }
1011 
1012         updateUidsLSP(activeUids, nowElapsed);
1013 
1014         synchronized (mService.mProcessStats.mLock) {
1015             if (mService.mProcessStats.shouldWriteNowLocked(now)) {
1016                 mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
1017                         mService.mProcessStats));
1018             }
1019 
1020             // Run this after making sure all procstates are updated.
1021             mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
1022         }
1023 
1024         if (DEBUG_OOM_ADJ) {
1025             final long duration = SystemClock.uptimeMillis() - now;
1026             if (false) {
1027                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
1028                         new RuntimeException("here").fillInStackTrace());
1029             } else {
1030                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
1031             }
1032         }
1033         if (startProfiling) {
1034             mService.mOomAdjProfiler.oomAdjEnded();
1035             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1036         }
1037     }
1038 
1039     @GuardedBy({"mService", "mProcLock"})
assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList)1040     private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
1041         final int numLru = lruList.size();
1042 
1043         // First update the OOM adjustment for each of the
1044         // application processes based on their current state.
1045         int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
1046         int nextCachedAdj = curCachedAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
1047         int curCachedImpAdj = 0;
1048         int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
1049         int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
1050 
1051         final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
1052         final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
1053                 - emptyProcessLimit;
1054         // Let's determine how many processes we have running vs.
1055         // how many slots we have for background processes; we may want
1056         // to put multiple processes in a slot of there are enough of
1057         // them.
1058         int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
1059         if (numEmptyProcs > cachedProcessLimit) {
1060             // If there are more empty processes than our limit on cached
1061             // processes, then use the cached process limit for the factor.
1062             // This ensures that the really old empty processes get pushed
1063             // down to the bottom, so if we are running low on memory we will
1064             // have a better chance at keeping around more cached processes
1065             // instead of a gazillion empty processes.
1066             numEmptyProcs = cachedProcessLimit;
1067         }
1068         int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
1069                 / mNumSlots;
1070         if (cachedFactor < 1) cachedFactor = 1;
1071 
1072         int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
1073         if (emptyFactor < 1) emptyFactor = 1;
1074 
1075         int stepCached = -1;
1076         int stepEmpty = -1;
1077         int lastCachedGroup = 0;
1078         int lastCachedGroupImportance = 0;
1079         int lastCachedGroupUid = 0;
1080 
1081         for (int i = numLru - 1; i >= 0; i--) {
1082             ProcessRecord app = lruList.get(i);
1083             final ProcessStateRecord state = app.mState;
1084             // If we haven't yet assigned the final cached adj
1085             // to the process, do that now.
1086             if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
1087                     >= ProcessList.UNKNOWN_ADJ) {
1088                 final ProcessServiceRecord psr = app.mServices;
1089                 switch (state.getCurProcState()) {
1090                     case PROCESS_STATE_CACHED_ACTIVITY:
1091                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
1092                     case ActivityManager.PROCESS_STATE_CACHED_RECENT:
1093                         // Figure out the next cached level, taking into account groups.
1094                         boolean inGroup = false;
1095                         final int connectionGroup = psr.getConnectionGroup();
1096                         if (connectionGroup != 0) {
1097                             final int connectionImportance = psr.getConnectionImportance();
1098                             if (lastCachedGroupUid == app.uid
1099                                     && lastCachedGroup == connectionGroup) {
1100                                 // This is in the same group as the last process, just tweak
1101                                 // adjustment by importance.
1102                                 if (connectionImportance > lastCachedGroupImportance) {
1103                                     lastCachedGroupImportance = connectionImportance;
1104                                     if (curCachedAdj < nextCachedAdj
1105                                             && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
1106                                         curCachedImpAdj++;
1107                                     }
1108                                 }
1109                                 inGroup = true;
1110                             } else {
1111                                 lastCachedGroupUid = app.uid;
1112                                 lastCachedGroup = connectionGroup;
1113                                 lastCachedGroupImportance = connectionImportance;
1114                             }
1115                         }
1116                         if (!inGroup && curCachedAdj != nextCachedAdj) {
1117                             stepCached++;
1118                             curCachedImpAdj = 0;
1119                             if (stepCached >= cachedFactor) {
1120                                 stepCached = 0;
1121                                 curCachedAdj = nextCachedAdj;
1122                                 nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
1123                                 if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
1124                                     nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
1125                                 }
1126                             }
1127                         }
1128                         // This process is a cached process holding activities...
1129                         // assign it the next cached value for that type, and then
1130                         // step that cached level.
1131                         state.setCurRawAdj(curCachedAdj + curCachedImpAdj);
1132                         state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj));
1133                         if (DEBUG_LRU) {
1134                             Slog.d(TAG_LRU, "Assigning activity LRU #" + i
1135                                     + " adj: " + state.getCurAdj()
1136                                     + " (curCachedAdj=" + curCachedAdj
1137                                     + " curCachedImpAdj=" + curCachedImpAdj + ")");
1138                         }
1139                         break;
1140                     default:
1141                         // Figure out the next cached level.
1142                         if (curEmptyAdj != nextEmptyAdj) {
1143                             stepEmpty++;
1144                             if (stepEmpty >= emptyFactor) {
1145                                 stepEmpty = 0;
1146                                 curEmptyAdj = nextEmptyAdj;
1147                                 nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
1148                                 if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
1149                                     nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
1150                                 }
1151                             }
1152                         }
1153                         // For everything else, assign next empty cached process
1154                         // level and bump that up.  Note that this means that
1155                         // long-running services that have dropped down to the
1156                         // cached level will be treated as empty (since their process
1157                         // state is still as a service), which is what we want.
1158                         state.setCurRawAdj(curEmptyAdj);
1159                         state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
1160                         if (DEBUG_LRU) {
1161                             Slog.d(TAG_LRU, "Assigning empty LRU #" + i
1162                                     + " adj: " + state.getCurAdj() + " (curEmptyAdj=" + curEmptyAdj
1163                                     + ")");
1164                         }
1165                         break;
1166                 }
1167             }
1168         }
1169     }
1170 
1171     @GuardedBy({"mService", "mProcLock"})
updateAndTrimProcessLSP(final long now, final long nowElapsed, final long oldTime, final ActiveUids activeUids)1172     private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
1173             final long oldTime, final ActiveUids activeUids) {
1174         ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP();
1175         final int numLru = lruList.size();
1176 
1177         final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
1178         final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
1179                 - emptyProcessLimit;
1180         int lastCachedGroup = 0;
1181         int lastCachedGroupUid = 0;
1182         int numCached = 0;
1183         int numCachedExtraGroup = 0;
1184         int numEmpty = 0;
1185         int numTrimming = 0;
1186 
1187         for (int i = numLru - 1; i >= 0; i--) {
1188             ProcessRecord app = lruList.get(i);
1189             final ProcessStateRecord state = app.mState;
1190             if (!app.isKilledByAm() && app.getThread() != null) {
1191                 // We don't need to apply the update for the process which didn't get computed
1192                 if (state.getCompletedAdjSeq() == mAdjSeq) {
1193                     applyOomAdjLSP(app, true, now, nowElapsed);
1194                 }
1195 
1196                 final ProcessServiceRecord psr = app.mServices;
1197                 // Count the number of process types.
1198                 switch (state.getCurProcState()) {
1199                     case PROCESS_STATE_CACHED_ACTIVITY:
1200                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
1201                         mNumCachedHiddenProcs++;
1202                         numCached++;
1203                         final int connectionGroup = psr.getConnectionGroup();
1204                         if (connectionGroup != 0) {
1205                             if (lastCachedGroupUid == app.info.uid
1206                                     && lastCachedGroup == connectionGroup) {
1207                                 // If this process is the next in the same group, we don't
1208                                 // want it to count against our limit of the number of cached
1209                                 // processes, so bump up the group count to account for it.
1210                                 numCachedExtraGroup++;
1211                             } else {
1212                                 lastCachedGroupUid = app.info.uid;
1213                                 lastCachedGroup = connectionGroup;
1214                             }
1215                         } else {
1216                             lastCachedGroupUid = lastCachedGroup = 0;
1217                         }
1218                         if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
1219                             app.killLocked("cached #" + numCached,
1220                                     ApplicationExitInfo.REASON_OTHER,
1221                                     ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
1222                                     true);
1223                         }
1224                         break;
1225                     case PROCESS_STATE_CACHED_EMPTY:
1226                         if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
1227                                 && app.getLastActivityTime() < oldTime) {
1228                             app.killLocked("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME
1229                                     - app.getLastActivityTime()) / 1000) + "s",
1230                                     ApplicationExitInfo.REASON_OTHER,
1231                                     ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
1232                                     true);
1233                         } else {
1234                             numEmpty++;
1235                             if (numEmpty > emptyProcessLimit) {
1236                                 app.killLocked("empty #" + numEmpty,
1237                                         ApplicationExitInfo.REASON_OTHER,
1238                                         ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
1239                                         true);
1240                             }
1241                         }
1242                         break;
1243                     default:
1244                         mNumNonCachedProcs++;
1245                         break;
1246                 }
1247 
1248                 if (app.isolated && psr.numberOfRunningServices() <= 0
1249                         && app.getIsolatedEntryPoint() == null) {
1250                     // If this is an isolated process, there are no services
1251                     // running in it, and it's not a special process with a
1252                     // custom entry point, then the process is no longer
1253                     // needed.  We agressively kill these because we can by
1254                     // definition not re-use the same process again, and it is
1255                     // good to avoid having whatever code was running in them
1256                     // left sitting around after no longer needed.
1257                     app.killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER,
1258                             ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
1259                 } else {
1260                     // Keeping this process, update its uid.
1261                     updateAppUidRecLSP(app);
1262                 }
1263 
1264                 if (state.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
1265                         && !app.isKilledByAm()) {
1266                     numTrimming++;
1267                 }
1268             }
1269         }
1270 
1271         mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
1272 
1273         return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
1274     }
1275 
1276     @GuardedBy({"mService", "mProcLock"})
updateAppUidRecIfNecessaryLSP(final ProcessRecord app)1277     private void updateAppUidRecIfNecessaryLSP(final ProcessRecord app) {
1278         if (!app.isKilledByAm() && app.getThread() != null) {
1279             if (app.isolated && app.mServices.numberOfRunningServices() <= 0
1280                     && app.getIsolatedEntryPoint() == null) {
1281                 // No op.
1282             } else {
1283                 // Keeping this process, update its uid.
1284                 updateAppUidRecLSP(app);
1285             }
1286         }
1287     }
1288 
1289     @GuardedBy({"mService", "mProcLock"})
updateAppUidRecLSP(ProcessRecord app)1290     private void updateAppUidRecLSP(ProcessRecord app) {
1291         final UidRecord uidRec = app.getUidRecord();
1292         if (uidRec != null) {
1293             final ProcessStateRecord state = app.mState;
1294             uidRec.setEphemeral(app.info.isInstantApp());
1295             if (uidRec.getCurProcState() > state.getCurProcState()) {
1296                 uidRec.setCurProcState(state.getCurProcState());
1297             }
1298             if (app.mServices.hasForegroundServices()) {
1299                 uidRec.setForegroundServices(true);
1300             }
1301             uidRec.setCurCapability(uidRec.getCurCapability() | state.getCurCapability());
1302         }
1303     }
1304 
1305     @GuardedBy({"mService", "mProcLock"})
updateUidsLSP(ActiveUids activeUids, final long nowElapsed)1306     private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
1307         ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
1308         becameIdle.clear();
1309 
1310         // Update from any uid changes.
1311         if (mLocalPowerManager != null) {
1312             mLocalPowerManager.startUidChanges();
1313         }
1314         for (int i = activeUids.size() - 1; i >= 0; i--) {
1315             final UidRecord uidRec = activeUids.valueAt(i);
1316             int uidChange = UidRecord.CHANGE_PROCSTATE;
1317             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
1318                     && (uidRec.getSetProcState() != uidRec.getCurProcState()
1319                     || uidRec.getSetCapability() != uidRec.getCurCapability()
1320                     || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) {
1321                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
1322                         + ": proc state from " + uidRec.getSetProcState() + " to "
1323                         + uidRec.getCurProcState() + ", capability from "
1324                         + uidRec.getSetCapability() + " to " + uidRec.getCurCapability()
1325                         + ", allowlist from " + uidRec.isSetAllowListed()
1326                         + " to " + uidRec.isCurAllowListed());
1327                 if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
1328                         && !uidRec.isCurAllowListed()) {
1329                     // UID is now in the background (and not on the temp allowlist).  Was it
1330                     // previously in the foreground (or on the temp allowlist)?
1331                     if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState())
1332                             || uidRec.isSetAllowListed()) {
1333                         uidRec.setLastBackgroundTime(nowElapsed);
1334                         if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
1335                             // Note: the background settle time is in elapsed realtime, while
1336                             // the handler time base is uptime.  All this means is that we may
1337                             // stop background uids later than we had intended, but that only
1338                             // happens because the device was sleeping so we are okay anyway.
1339                             mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
1340                                     mConstants.BACKGROUND_SETTLE_TIME);
1341                         }
1342                     }
1343                     if (uidRec.isIdle() && !uidRec.isSetIdle()) {
1344                         uidChange = UidRecord.CHANGE_IDLE;
1345                         becameIdle.add(uidRec);
1346                     }
1347                 } else {
1348                     if (uidRec.isIdle()) {
1349                         uidChange = UidRecord.CHANGE_ACTIVE;
1350                         EventLogTags.writeAmUidActive(uidRec.getUid());
1351                         uidRec.setIdle(false);
1352                     }
1353                     uidRec.setLastBackgroundTime(0);
1354                 }
1355                 final boolean wasCached = uidRec.getSetProcState()
1356                         > ActivityManager.PROCESS_STATE_RECEIVER;
1357                 final boolean isCached = uidRec.getCurProcState()
1358                         > ActivityManager.PROCESS_STATE_RECEIVER;
1359                 if (wasCached != isCached
1360                         || uidRec.getSetProcState() == PROCESS_STATE_NONEXISTENT) {
1361                     uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
1362                 }
1363                 if (uidRec.getSetCapability() != uidRec.getCurCapability()) {
1364                     uidChange |= UidRecord.CHANGE_CAPABILITY;
1365                 }
1366                 uidRec.setSetProcState(uidRec.getCurProcState());
1367                 uidRec.setSetCapability(uidRec.getCurCapability());
1368                 uidRec.setSetAllowListed(uidRec.isCurAllowListed());
1369                 uidRec.setSetIdle(uidRec.isIdle());
1370                 mService.mAtmInternal.onUidProcStateChanged(
1371                         uidRec.getUid(), uidRec.getSetProcState());
1372                 mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
1373                 mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState(),
1374                         uidRec.getCurCapability());
1375                 if (uidRec.hasForegroundServices()) {
1376                     mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
1377                 }
1378             }
1379             mService.mInternal.deletePendingTopUid(uidRec.getUid());
1380         }
1381         if (mLocalPowerManager != null) {
1382             mLocalPowerManager.finishUidChanges();
1383         }
1384 
1385         int size = becameIdle.size();
1386         if (size > 0) {
1387             // If we have any new uids that became idle this time, we need to make sure
1388             // they aren't left with running services.
1389             for (int i = size - 1; i >= 0; i--) {
1390                 mService.mServices.stopInBackgroundLocked(becameIdle.get(i).getUid());
1391             }
1392         }
1393     }
1394 
1395     private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
1396             new ComputeOomAdjWindowCallback();
1397 
1398     /** These methods are called inline during computeOomAdjLSP(), on the same thread */
1399     final class ComputeOomAdjWindowCallback
1400             implements WindowProcessController.ComputeOomAdjCallback {
1401 
1402         ProcessRecord app;
1403         int adj;
1404         boolean foregroundActivities;
1405         boolean mHasVisibleActivities;
1406         int procState;
1407         int schedGroup;
1408         int appUid;
1409         int logUid;
1410         int processStateCurTop;
1411         ProcessStateRecord mState;
1412 
initialize(ProcessRecord app, int adj, boolean foregroundActivities, boolean hasVisibleActivities, int procState, int schedGroup, int appUid, int logUid, int processStateCurTop)1413         void initialize(ProcessRecord app, int adj, boolean foregroundActivities,
1414                 boolean hasVisibleActivities, int procState, int schedGroup, int appUid,
1415                 int logUid, int processStateCurTop) {
1416             this.app = app;
1417             this.adj = adj;
1418             this.foregroundActivities = foregroundActivities;
1419             this.mHasVisibleActivities = hasVisibleActivities;
1420             this.procState = procState;
1421             this.schedGroup = schedGroup;
1422             this.appUid = appUid;
1423             this.logUid = logUid;
1424             this.processStateCurTop = processStateCurTop;
1425             this.mState = app.mState;
1426         }
1427 
1428         @Override
onVisibleActivity()1429         public void onVisibleActivity() {
1430             // App has a visible activity; only upgrade adjustment.
1431             if (adj > ProcessList.VISIBLE_APP_ADJ) {
1432                 adj = ProcessList.VISIBLE_APP_ADJ;
1433                 mState.setAdjType("vis-activity");
1434                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1435                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app);
1436                 }
1437             }
1438             if (procState > processStateCurTop) {
1439                 procState = processStateCurTop;
1440                 mState.setAdjType("vis-activity");
1441                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1442                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1443                             "Raise procstate to vis-activity (top): " + app);
1444                 }
1445             }
1446             if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
1447                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1448             }
1449             mState.setCached(false);
1450             mState.setEmpty(false);
1451             foregroundActivities = true;
1452             mHasVisibleActivities = true;
1453         }
1454 
1455         @Override
onPausedActivity()1456         public void onPausedActivity() {
1457             if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1458                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1459                 mState.setAdjType("pause-activity");
1460                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1461                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: "  + app);
1462                 }
1463             }
1464             if (procState > processStateCurTop) {
1465                 procState = processStateCurTop;
1466                 mState.setAdjType("pause-activity");
1467                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1468                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1469                             "Raise procstate to pause-activity (top): "  + app);
1470                 }
1471             }
1472             if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
1473                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1474             }
1475             mState.setCached(false);
1476             mState.setEmpty(false);
1477             foregroundActivities = true;
1478             mHasVisibleActivities = false;
1479         }
1480 
1481         @Override
onStoppingActivity(boolean finishing)1482         public void onStoppingActivity(boolean finishing) {
1483             if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1484                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1485                 mState.setAdjType("stop-activity");
1486                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1487                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1488                             "Raise adj to stop-activity: "  + app);
1489                 }
1490             }
1491 
1492             // For the process state, we will at this point consider the process to be cached. It
1493             // will be cached either as an activity or empty depending on whether the activity is
1494             // finishing. We do this so that we can treat the process as cached for purposes of
1495             // memory trimming (determining current memory level, trim command to send to process)
1496             // since there can be an arbitrary number of stopping processes and they should soon all
1497             // go into the cached state.
1498             if (!finishing) {
1499                 if (procState > PROCESS_STATE_LAST_ACTIVITY) {
1500                     procState = PROCESS_STATE_LAST_ACTIVITY;
1501                     mState.setAdjType("stop-activity");
1502                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1503                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
1504                                 "Raise procstate to stop-activity: " + app);
1505                     }
1506                 }
1507             }
1508             mState.setCached(false);
1509             mState.setEmpty(false);
1510             foregroundActivities = true;
1511             mHasVisibleActivities = false;
1512         }
1513 
1514         @Override
onOtherActivity()1515         public void onOtherActivity() {
1516             if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
1517                 procState = PROCESS_STATE_CACHED_ACTIVITY;
1518                 mState.setAdjType("cch-act");
1519                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1520                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1521                             "Raise procstate to cached activity: " + app);
1522                 }
1523             }
1524             mHasVisibleActivities = false;
1525         }
1526     }
1527 
1528     @GuardedBy({"mService", "mProcLock"})
computeOomAdjLSP(ProcessRecord app, int cachedAdj, ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval, boolean computeClients)1529     private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
1530             ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
1531             boolean computeClients) {
1532         final ProcessStateRecord state = app.mState;
1533         if (mAdjSeq == state.getAdjSeq()) {
1534             if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
1535                 // This adjustment has already been computed successfully.
1536                 return false;
1537             } else {
1538                 // The process is being computed, so there is a cycle. We cannot
1539                 // rely on this process's state.
1540                 state.setContainsCycle(true);
1541                 mProcessesInCycle.add(app);
1542 
1543                 return false;
1544             }
1545         }
1546 
1547         if (app.getThread() == null) {
1548             state.setAdjSeq(mAdjSeq);
1549             state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
1550             state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
1551             state.setCurAdj(ProcessList.CACHED_APP_MAX_ADJ);
1552             state.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
1553             state.setCompletedAdjSeq(state.getAdjSeq());
1554             state.setCurCapability(PROCESS_CAPABILITY_NONE);
1555             return false;
1556         }
1557 
1558         state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
1559         state.setAdjSource(null);
1560         state.setAdjTarget(null);
1561         state.setEmpty(false);
1562         state.setCached(false);
1563         state.resetAllowStartFgsState();
1564         if (!cycleReEval) {
1565             // Don't reset this flag when doing cycles re-evaluation.
1566             app.mOptRecord.setShouldNotFreeze(false);
1567         }
1568 
1569         final int appUid = app.info.uid;
1570         final int logUid = mService.mCurOomAdjUid;
1571 
1572         int prevAppAdj = state.getCurAdj();
1573         int prevProcState = state.getCurProcState();
1574         int prevCapability = state.getCurCapability();
1575         final ProcessServiceRecord psr = app.mServices;
1576 
1577         if (state.getMaxAdj() <= ProcessList.FOREGROUND_APP_ADJ) {
1578             // The max adjustment doesn't allow this app to be anything
1579             // below foreground, so it is not worth doing work for it.
1580             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1581                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app);
1582             }
1583             state.setAdjType("fixed");
1584             state.setAdjSeq(mAdjSeq);
1585             state.setCurRawAdj(state.getMaxAdj());
1586             state.setHasForegroundActivities(false);
1587             state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
1588             state.setCurCapability(PROCESS_CAPABILITY_ALL);
1589             state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
1590             // System processes can do UI, and when they do we want to have
1591             // them trim their memory after the user leaves the UI.  To
1592             // facilitate this, here we need to determine whether or not it
1593             // is currently showing UI.
1594             state.setSystemNoUi(true);
1595             if (app == topApp) {
1596                 state.setSystemNoUi(false);
1597                 state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
1598                 state.setAdjType("pers-top-activity");
1599             } else if (state.hasTopUi()) {
1600                 // sched group/proc state adjustment is below
1601                 state.setSystemNoUi(false);
1602                 state.setAdjType("pers-top-ui");
1603             } else if (state.getCachedHasVisibleActivities()) {
1604                 state.setSystemNoUi(false);
1605             }
1606             if (!state.isSystemNoUi()) {
1607                 if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
1608                         || state.isRunningRemoteAnimation()) {
1609                     // screen on or animating, promote UI
1610                     state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
1611                     state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
1612                 } else {
1613                     // screen off, restrict UI scheduling
1614                     state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
1615                     state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
1616                 }
1617             }
1618             state.setCurRawProcState(state.getCurProcState());
1619             state.setCurAdj(state.getMaxAdj());
1620             state.setCompletedAdjSeq(state.getAdjSeq());
1621             state.bumpAllowStartFgsState(state.getCurProcState());
1622             // if curAdj is less than prevAppAdj, then this process was promoted
1623             return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
1624         }
1625 
1626         state.setSystemNoUi(false);
1627 
1628         final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState();
1629 
1630         // Determine the importance of the process, starting with most
1631         // important to least, and assign an appropriate OOM adjustment.
1632         int adj;
1633         int schedGroup;
1634         int procState;
1635         int cachedAdjSeq;
1636         int capability = cycleReEval ? app.mState.getCurCapability() : 0;
1637 
1638         boolean foregroundActivities = false;
1639         boolean hasVisibleActivities = false;
1640         if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
1641             // The last app on the list is the foreground app.
1642             adj = ProcessList.FOREGROUND_APP_ADJ;
1643             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
1644             state.setAdjType("top-activity");
1645             foregroundActivities = true;
1646             hasVisibleActivities = true;
1647             procState = PROCESS_STATE_CUR_TOP;
1648             state.bumpAllowStartFgsState(PROCESS_STATE_TOP);
1649             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1650                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
1651             }
1652         } else if (state.isRunningRemoteAnimation()) {
1653             adj = ProcessList.VISIBLE_APP_ADJ;
1654             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
1655             state.setAdjType("running-remote-anim");
1656             procState = PROCESS_STATE_CUR_TOP;
1657             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1658                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
1659             }
1660         } else if (app.getActiveInstrumentation() != null) {
1661             // Don't want to kill running instrumentation.
1662             adj = ProcessList.FOREGROUND_APP_ADJ;
1663             schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1664             state.setAdjType("instrumentation");
1665             procState = PROCESS_STATE_FOREGROUND_SERVICE;
1666             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1667                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
1668             }
1669         } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
1670             // An app that is currently receiving a broadcast also
1671             // counts as being in the foreground for OOM killer purposes.
1672             // It's placed in a sched group based on the nature of the
1673             // broadcast as reflected by which queue it's active in.
1674             adj = ProcessList.FOREGROUND_APP_ADJ;
1675             schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue))
1676                     ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
1677             state.setAdjType("broadcast");
1678             procState = ActivityManager.PROCESS_STATE_RECEIVER;
1679             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1680                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
1681             }
1682         } else if (psr.numberOfExecutingServices() > 0) {
1683             // An app that is currently executing a service callback also
1684             // counts as being in the foreground.
1685             adj = ProcessList.FOREGROUND_APP_ADJ;
1686             schedGroup = psr.shouldExecServicesFg()
1687                     ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
1688             state.setAdjType("exec-service");
1689             procState = PROCESS_STATE_SERVICE;
1690             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1691                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
1692             }
1693         } else if (app == topApp) {
1694             adj = ProcessList.FOREGROUND_APP_ADJ;
1695             schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1696             state.setAdjType("top-sleeping");
1697             foregroundActivities = true;
1698             procState = PROCESS_STATE_CUR_TOP;
1699             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1700                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app);
1701             }
1702         } else {
1703             // As far as we know the process is empty.  We may change our mind later.
1704             schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1705             // At this point we don't actually know the adjustment.  Use the cached adj
1706             // value that the caller wants us to.
1707             adj = cachedAdj;
1708             procState = PROCESS_STATE_CACHED_EMPTY;
1709             if (!state.containsCycle()) {
1710                 state.setCached(true);
1711                 state.setEmpty(true);
1712                 state.setAdjType("cch-empty");
1713             }
1714             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1715                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
1716             }
1717         }
1718 
1719         // Examine all activities if not already foreground.
1720         if (!foregroundActivities && state.getCachedHasActivities()) {
1721             state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
1722                     adj, foregroundActivities, hasVisibleActivities, procState, schedGroup,
1723                     appUid, logUid, PROCESS_STATE_CUR_TOP);
1724 
1725             adj = state.getCachedAdj();
1726             foregroundActivities = state.getCachedForegroundActivities();
1727             hasVisibleActivities = state.getCachedHasVisibleActivities();
1728             procState = state.getCachedProcState();
1729             schedGroup = state.getCachedSchedGroup();
1730         }
1731 
1732         if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) {
1733             procState = PROCESS_STATE_CACHED_RECENT;
1734             state.setAdjType("cch-rec");
1735             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1736                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
1737             }
1738         }
1739 
1740         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
1741                 || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
1742             if (psr.hasForegroundServices()) {
1743                 // The user is aware of this app, so make it visible.
1744                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1745                 procState = PROCESS_STATE_FOREGROUND_SERVICE;
1746                 state.bumpAllowStartFgsState(PROCESS_STATE_FOREGROUND_SERVICE);
1747                 state.setAdjType("fg-service");
1748                 state.setCached(false);
1749                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1750                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1751                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + state.getAdjType() + ": "
1752                             + app + " ");
1753                 }
1754             } else if (state.hasOverlayUi()) {
1755                 // The process is display an overlay UI.
1756                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1757                 procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
1758                 state.setCached(false);
1759                 state.setAdjType("has-overlay-ui");
1760                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1761                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1762                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app);
1763                 }
1764             }
1765         }
1766 
1767         // If the app was recently in the foreground and moved to a foreground service status,
1768         // allow it to get a higher rank in memory for some time, compared to other foreground
1769         // services so that it can finish performing any persistence/processing of in-memory state.
1770         if (psr.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
1771                 && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now
1772                 || state.getSetProcState() <= PROCESS_STATE_TOP)) {
1773             adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
1774             state.setAdjType("fg-service-act");
1775             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1776                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
1777             }
1778         }
1779 
1780         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
1781                 || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
1782             if (state.getForcingToImportant() != null) {
1783                 // This is currently used for toasts...  they are not interactive, and
1784                 // we don't want them to cause the app to become fully foreground (and
1785                 // thus out of background check), so we yes the best background level we can.
1786                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1787                 procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
1788                 state.setCached(false);
1789                 state.setAdjType("force-imp");
1790                 state.setAdjSource(state.getForcingToImportant());
1791                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1792                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1793                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
1794                 }
1795             }
1796         }
1797 
1798         if (state.getCachedIsHeavyWeight()) {
1799             if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
1800                 // We don't want to kill the current heavy-weight process.
1801                 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
1802                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1803                 state.setCached(false);
1804                 state.setAdjType("heavy");
1805                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1806                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
1807                 }
1808             }
1809             if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
1810                 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
1811                 state.setAdjType("heavy");
1812                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1813                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
1814                 }
1815             }
1816         }
1817 
1818         if (state.getCachedIsHomeProcess()) {
1819             if (adj > ProcessList.HOME_APP_ADJ) {
1820                 // This process is hosting what we currently consider to be the
1821                 // home app, so we don't want to let it go into the background.
1822                 adj = ProcessList.HOME_APP_ADJ;
1823                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1824                 state.setCached(false);
1825                 state.setAdjType("home");
1826                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1827                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
1828                 }
1829             }
1830             if (procState > ActivityManager.PROCESS_STATE_HOME) {
1831                 procState = ActivityManager.PROCESS_STATE_HOME;
1832                 state.setAdjType("home");
1833                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1834                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
1835                 }
1836             }
1837         }
1838 
1839         if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
1840             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
1841                 // This was the previous process that showed UI to the user.
1842                 // We want to try to keep it around more aggressively, to give
1843                 // a good experience around switching between two apps.
1844                 adj = ProcessList.PREVIOUS_APP_ADJ;
1845                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1846                 state.setCached(false);
1847                 state.setAdjType("previous");
1848                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1849                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
1850                 }
1851             }
1852             if (procState > PROCESS_STATE_LAST_ACTIVITY) {
1853                 procState = PROCESS_STATE_LAST_ACTIVITY;
1854                 state.setAdjType("previous");
1855                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1856                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
1857                 }
1858             }
1859         }
1860 
1861         if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
1862                 + " reason=" + state.getAdjType());
1863 
1864         // By default, we use the computed adjustment.  It may be changed if
1865         // there are applications dependent on our services or providers, but
1866         // this gives us a baseline and makes sure we don't get into an
1867         // infinite recursion. If we're re-evaluating due to cycles, use the previously computed
1868         // values.
1869         if (cycleReEval) {
1870             procState = Math.min(procState, state.getCurRawProcState());
1871             adj = Math.min(adj, state.getCurRawAdj());
1872             schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup());
1873         }
1874         state.setCurRawAdj(adj);
1875         state.setCurRawProcState(procState);
1876 
1877         state.setHasStartedServices(false);
1878         state.setAdjSeq(mAdjSeq);
1879 
1880         final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
1881         if (backupTarget != null && app == backupTarget.app) {
1882             // If possible we want to avoid killing apps while they're being backed up
1883             if (adj > ProcessList.BACKUP_APP_ADJ) {
1884                 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
1885                 adj = ProcessList.BACKUP_APP_ADJ;
1886                 if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
1887                     procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
1888                 }
1889                 state.setAdjType("backup");
1890                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1891                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
1892                 }
1893                 state.setCached(false);
1894             }
1895             if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
1896                 procState = ActivityManager.PROCESS_STATE_BACKUP;
1897                 state.setAdjType("backup");
1898                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1899                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
1900                 }
1901             }
1902         }
1903 
1904         int capabilityFromFGS = 0; // capability from foreground service.
1905         boolean scheduleLikeTopApp = false;
1906         for (int is = psr.numberOfRunningServices() - 1;
1907                 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
1908                         || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1909                         || procState > PROCESS_STATE_TOP);
1910                 is--) {
1911             ServiceRecord s = psr.getRunningServiceAt(is);
1912             if (s.startRequested) {
1913                 state.setHasStartedServices(true);
1914                 if (procState > PROCESS_STATE_SERVICE) {
1915                     procState = PROCESS_STATE_SERVICE;
1916                     state.setAdjType("started-services");
1917                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1918                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
1919                                 "Raise procstate to started service: " + app);
1920                     }
1921                 }
1922                 if (!s.mKeepWarming && state.hasShownUi() && !state.getCachedIsHomeProcess()) {
1923                     // If this process has shown some UI, let it immediately
1924                     // go to the LRU list because it may be pretty heavy with
1925                     // UI stuff.  We'll tag it with a label just to help
1926                     // debug and understand what is going on.
1927                     if (adj > ProcessList.SERVICE_ADJ) {
1928                         state.setAdjType("cch-started-ui-services");
1929                     }
1930                 } else {
1931                     if (s.mKeepWarming
1932                             || now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
1933                         // This service has seen some activity within
1934                         // recent memory, so we will keep its process ahead
1935                         // of the background processes.
1936                         if (adj > ProcessList.SERVICE_ADJ) {
1937                             adj = ProcessList.SERVICE_ADJ;
1938                             state.setAdjType("started-services");
1939                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1940                                 reportOomAdjMessageLocked(TAG_OOM_ADJ,
1941                                         "Raise adj to started service: " + app);
1942                             }
1943                             state.setCached(false);
1944                         }
1945                     }
1946                     // If we have let the service slide into the background
1947                     // state, still have some text describing what it is doing
1948                     // even though the service no longer has an impact.
1949                     if (adj > ProcessList.SERVICE_ADJ) {
1950                         state.setAdjType("cch-started-services");
1951                     }
1952                 }
1953             }
1954 
1955             if (s.isForeground) {
1956                 final int fgsType = s.foregroundServiceType;
1957                 if (s.mAllowWhileInUsePermissionInFgs) {
1958                     capabilityFromFGS |=
1959                             (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
1960                                     != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
1961 
1962                     final boolean enabled = state.getCachedCompatChange(
1963                             CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY);
1964                     if (enabled) {
1965                         capabilityFromFGS |=
1966                                 (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
1967                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
1968                         capabilityFromFGS |=
1969                                 (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
1970                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
1971                     } else {
1972                         capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
1973                                 | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
1974                     }
1975                 }
1976             }
1977 
1978             ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
1979             for (int conni = serviceConnections.size() - 1;
1980                     conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
1981                             || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1982                             || procState > PROCESS_STATE_TOP);
1983                     conni--) {
1984                 ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
1985                 for (int i = 0;
1986                         i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
1987                                 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1988                                 || procState > PROCESS_STATE_TOP);
1989                         i++) {
1990                     // XXX should compute this based on the max of
1991                     // all connected clients.
1992                     ConnectionRecord cr = clist.get(i);
1993                     if (cr.binding.client == app) {
1994                         // Binding to oneself is not interesting.
1995                         continue;
1996                     }
1997 
1998                     boolean trackedProcState = false;
1999 
2000                     ProcessRecord client = cr.binding.client;
2001                     final ProcessStateRecord cstate = client.mState;
2002                     if (computeClients) {
2003                         computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
2004                                 cycleReEval, true);
2005                     } else {
2006                         cstate.setCurRawAdj(cstate.getCurAdj());
2007                         cstate.setCurRawProcState(cstate.getCurProcState());
2008                     }
2009 
2010                     int clientAdj = cstate.getCurRawAdj();
2011                     int clientProcState = cstate.getCurRawProcState();
2012 
2013                     final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
2014 
2015                     if (client.mOptRecord.shouldNotFreeze()) {
2016                         // Propagate the shouldNotFreeze flag down the bindings.
2017                         app.mOptRecord.setShouldNotFreeze(true);
2018                     }
2019 
2020                     if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
2021                         if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
2022                             capability |= cstate.getCurCapability();
2023                         }
2024 
2025                         // If an app has network capability by default
2026                         // (by having procstate <= BFGS), then the apps it binds to will get
2027                         // elevated to a high enough procstate anyway to get network unless they
2028                         // request otherwise, so don't propagate the network capability by default
2029                         // in this case unless they explicitly request it.
2030                         if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) {
2031                             if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
2032                                 if ((cr.flags & Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)
2033                                         != 0) {
2034                                     capability |= PROCESS_CAPABILITY_NETWORK;
2035                                 }
2036                             } else {
2037                                 capability |= PROCESS_CAPABILITY_NETWORK;
2038                             }
2039                         }
2040 
2041                         if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
2042                             continue;
2043                         }
2044 
2045                         if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
2046                             // If the other app is cached for any reason, for purposes here
2047                             // we are going to consider it empty.  The specific cached state
2048                             // doesn't propagate except under certain conditions.
2049                             clientProcState = PROCESS_STATE_CACHED_EMPTY;
2050                         }
2051                         String adjType = null;
2052                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
2053                             // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
2054                             if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
2055                                 app.mOptRecord.setShouldNotFreeze(true);
2056                             }
2057                             // Not doing bind OOM management, so treat
2058                             // this guy more like a started service.
2059                             if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
2060                                 // If this process has shown some UI, let it immediately
2061                                 // go to the LRU list because it may be pretty heavy with
2062                                 // UI stuff.  We'll tag it with a label just to help
2063                                 // debug and understand what is going on.
2064                                 if (adj > clientAdj) {
2065                                     adjType = "cch-bound-ui-services";
2066                                 }
2067                                 state.setCached(false);
2068                                 clientAdj = adj;
2069                                 clientProcState = procState;
2070                             } else {
2071                                 if (now >= (s.lastActivity
2072                                         + mConstants.MAX_SERVICE_INACTIVITY)) {
2073                                     // This service has not seen activity within
2074                                     // recent memory, so allow it to drop to the
2075                                     // LRU list if there is no other reason to keep
2076                                     // it around.  We'll also tag it with a label just
2077                                     // to help debug and undertand what is going on.
2078                                     if (adj > clientAdj) {
2079                                         adjType = "cch-bound-services";
2080                                     }
2081                                     clientAdj = adj;
2082                                 }
2083                             }
2084                         }
2085                         if (adj > clientAdj) {
2086                             // If this process has recently shown UI, and
2087                             // the process that is binding to it is less
2088                             // important than being visible, then we don't
2089                             // care about the binding as much as we care
2090                             // about letting this process get into the LRU
2091                             // list to be killed and restarted if needed for
2092                             // memory.
2093                             if (state.hasShownUi() && !state.getCachedIsHomeProcess()
2094                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
2095                                 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
2096                                     adjType = "cch-bound-ui-services";
2097                                 }
2098                             } else {
2099                                 int newAdj;
2100                                 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
2101                                         |Context.BIND_IMPORTANT)) != 0) {
2102                                     if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
2103                                         newAdj = clientAdj;
2104                                     } else {
2105                                         // make this service persistent
2106                                         newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
2107                                         schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2108                                         procState = ActivityManager.PROCESS_STATE_PERSISTENT;
2109                                         cr.trackProcState(procState, mAdjSeq, now);
2110                                         trackedProcState = true;
2111                                     }
2112                                 } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0
2113                                         && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
2114                                         && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
2115                                     newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
2116                                 } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
2117                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
2118                                         && adj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
2119                                     newAdj = ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
2120                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
2121                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
2122                                         && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
2123                                     newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
2124                                 } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
2125                                     newAdj = clientAdj;
2126                                 } else {
2127                                     if (adj > ProcessList.VISIBLE_APP_ADJ) {
2128                                         // TODO: Is this too limiting for apps bound from TOP?
2129                                         newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
2130                                     } else {
2131                                         newAdj = adj;
2132                                     }
2133                                 }
2134                                 if (!cstate.isCached()) {
2135                                     state.setCached(false);
2136                                 }
2137                                 if (adj >  newAdj) {
2138                                     adj = newAdj;
2139                                     state.setCurRawAdj(adj);
2140                                     adjType = "service";
2141                                 }
2142                             }
2143                         }
2144                         if ((cr.flags & (Context.BIND_NOT_FOREGROUND
2145                                 | Context.BIND_IMPORTANT_BACKGROUND)) == 0) {
2146                             // This will treat important bound services identically to
2147                             // the top app, which may behave differently than generic
2148                             // foreground work.
2149                             final int curSchedGroup = cstate.getCurrentSchedulingGroup();
2150                             if (curSchedGroup > schedGroup) {
2151                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
2152                                     schedGroup = curSchedGroup;
2153                                 } else {
2154                                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2155                                 }
2156                             }
2157                             if (clientProcState < PROCESS_STATE_TOP) {
2158                                 // Special handling for above-top states (persistent
2159                                 // processes).  These should not bring the current process
2160                                 // into the top state, since they are not on top.  Instead
2161                                 // give them the best bound state after that.
2162                                 if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
2163                                     clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
2164                                     state.bumpAllowStartFgsState(
2165                                             PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
2166                                 } else if (mService.mWakefulness.get()
2167                                         == PowerManagerInternal.WAKEFULNESS_AWAKE
2168                                         && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
2169                                                 != 0) {
2170                                     clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
2171                                 } else {
2172                                     clientProcState =
2173                                             PROCESS_STATE_IMPORTANT_FOREGROUND;
2174                                 }
2175                             } else if (clientProcState == PROCESS_STATE_TOP) {
2176                                 // Go at most to BOUND_TOP, unless requested to elevate
2177                                 // to client's state.
2178                                 clientProcState = PROCESS_STATE_BOUND_TOP;
2179                                 state.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP);
2180                                 final boolean enabled = cstate.getCachedCompatChange(
2181                                         CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY);
2182                                 if (enabled) {
2183                                     if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
2184                                         // TOP process passes all capabilities to the service.
2185                                         capability |= cstate.getCurCapability();
2186                                     } else {
2187                                         // TOP process passes no capability to the service.
2188                                     }
2189                                 } else {
2190                                     // TOP process passes all capabilities to the service.
2191                                     capability |= cstate.getCurCapability();
2192                                 }
2193                             }
2194                         } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
2195                             if (clientProcState <
2196                                     PROCESS_STATE_TRANSIENT_BACKGROUND) {
2197                                 clientProcState =
2198                                         PROCESS_STATE_TRANSIENT_BACKGROUND;
2199                             }
2200                         } else {
2201                             if (clientProcState <
2202                                     PROCESS_STATE_IMPORTANT_BACKGROUND) {
2203                                 clientProcState =
2204                                         PROCESS_STATE_IMPORTANT_BACKGROUND;
2205                             }
2206                         }
2207 
2208                         if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP
2209                                 && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0
2210                                 && clientIsSystem) {
2211                             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
2212                             scheduleLikeTopApp = true;
2213                         }
2214 
2215                         if (!trackedProcState) {
2216                             cr.trackProcState(clientProcState, mAdjSeq, now);
2217                         }
2218 
2219                         if (procState > clientProcState) {
2220                             procState = clientProcState;
2221                             state.setCurRawProcState(procState);
2222                             if (adjType == null) {
2223                                 adjType = "service";
2224                             }
2225                         }
2226                         if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND
2227                                 && (cr.flags & Context.BIND_SHOWING_UI) != 0) {
2228                             app.setPendingUiClean(true);
2229                         }
2230                         if (adjType != null) {
2231                             state.setAdjType(adjType);
2232                             state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
2233                                     .REASON_SERVICE_IN_USE);
2234                             state.setAdjSource(cr.binding.client);
2235                             state.setAdjSourceProcState(clientProcState);
2236                             state.setAdjTarget(s.instanceName);
2237                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2238                                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
2239                                         + ": " + app + ", due to " + cr.binding.client
2240                                         + " adj=" + adj + " procState="
2241                                         + ProcessList.makeProcStateString(procState));
2242                             }
2243                         }
2244                     } else { // BIND_WAIVE_PRIORITY == true
2245                         // BIND_WAIVE_PRIORITY bindings are special when it comes to the
2246                         // freezer. Processes bound via WPRI are expected to be running,
2247                         // but they are not promoted in the LRU list to keep them out of
2248                         // cached. As a result, they can freeze based on oom_adj alone.
2249                         // Normally, bindToDeath would fire when a cached app would die
2250                         // in the background, but nothing will fire when a running process
2251                         // pings a frozen process. Accordingly, any cached app that is
2252                         // bound by an unfrozen app via a WPRI binding has to remain
2253                         // unfrozen.
2254                         if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
2255                             app.mOptRecord.setShouldNotFreeze(true);
2256                         }
2257                     }
2258                     if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
2259                         psr.setTreatLikeActivity(true);
2260                     }
2261                     final ActivityServiceConnectionsHolder a = cr.activity;
2262                     if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
2263                         if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ
2264                                 && a.isActivityVisible()) {
2265                             adj = ProcessList.FOREGROUND_APP_ADJ;
2266                             state.setCurRawAdj(adj);
2267                             if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
2268                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
2269                                     schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
2270                                 } else {
2271                                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2272                                 }
2273                             }
2274                             state.setCached(false);
2275                             state.setAdjType("service");
2276                             state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
2277                                     .REASON_SERVICE_IN_USE);
2278                             state.setAdjSource(a);
2279                             state.setAdjSourceProcState(procState);
2280                             state.setAdjTarget(s.instanceName);
2281                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2282                                 reportOomAdjMessageLocked(TAG_OOM_ADJ,
2283                                         "Raise to service w/activity: " + app);
2284                             }
2285                         }
2286                     }
2287                 }
2288             }
2289         }
2290 
2291         final ProcessProviderRecord ppr = app.mProviders;
2292         for (int provi = ppr.numberOfProviders() - 1;
2293                 provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
2294                         || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
2295                         || procState > PROCESS_STATE_TOP);
2296                 provi--) {
2297             ContentProviderRecord cpr = ppr.getProviderAt(provi);
2298             for (int i = cpr.connections.size() - 1;
2299                     i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
2300                             || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
2301                             || procState > PROCESS_STATE_TOP);
2302                     i--) {
2303                 ContentProviderConnection conn = cpr.connections.get(i);
2304                 ProcessRecord client = conn.client;
2305                 final ProcessStateRecord cstate = client.mState;
2306                 if (client == app) {
2307                     // Being our own client is not interesting.
2308                     continue;
2309                 }
2310                 if (computeClients) {
2311                     computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
2312                 } else {
2313                     cstate.setCurRawAdj(cstate.getCurAdj());
2314                     cstate.setCurRawProcState(cstate.getCurProcState());
2315                 }
2316 
2317                 if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
2318                     continue;
2319                 }
2320 
2321                 int clientAdj = cstate.getCurRawAdj();
2322                 int clientProcState = cstate.getCurRawProcState();
2323 
2324                 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
2325                     // If the other app is cached for any reason, for purposes here
2326                     // we are going to consider it empty.
2327                     clientProcState = PROCESS_STATE_CACHED_EMPTY;
2328                 }
2329                 if (client.mOptRecord.shouldNotFreeze()) {
2330                     // Propagate the shouldNotFreeze flag down the bindings.
2331                     app.mOptRecord.setShouldNotFreeze(true);
2332                 }
2333                 String adjType = null;
2334                 if (adj > clientAdj) {
2335                     if (state.hasShownUi() && !state.getCachedIsHomeProcess()
2336                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
2337                         adjType = "cch-ui-provider";
2338                     } else {
2339                         adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
2340                                 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
2341                         state.setCurRawAdj(adj);
2342                         adjType = "provider";
2343                     }
2344                     state.setCached(state.isCached() & cstate.isCached());
2345                 }
2346 
2347                 if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
2348                     if (adjType == null) {
2349                         adjType = "provider";
2350                     }
2351                     if (clientProcState == PROCESS_STATE_TOP) {
2352                         clientProcState = PROCESS_STATE_BOUND_TOP;
2353                     } else {
2354                         clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
2355                     }
2356                 }
2357 
2358                 conn.trackProcState(clientProcState, mAdjSeq, now);
2359                 if (procState > clientProcState) {
2360                     procState = clientProcState;
2361                     state.setCurRawProcState(procState);
2362                 }
2363                 if (cstate.getCurrentSchedulingGroup() > schedGroup) {
2364                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2365                 }
2366                 if (adjType != null) {
2367                     state.setAdjType(adjType);
2368                     state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
2369                             .REASON_PROVIDER_IN_USE);
2370                     state.setAdjSource(client);
2371                     state.setAdjSourceProcState(clientProcState);
2372                     state.setAdjTarget(cpr.name);
2373                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2374                         reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
2375                                 + ": " + app + ", due to " + client
2376                                 + " adj=" + adj + " procState="
2377                                 + ProcessList.makeProcStateString(procState));
2378                     }
2379                 }
2380             }
2381             // If the provider has external (non-framework) process
2382             // dependencies, ensure that its adjustment is at least
2383             // FOREGROUND_APP_ADJ.
2384             if (cpr.hasExternalProcessHandles()) {
2385                 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
2386                     adj = ProcessList.FOREGROUND_APP_ADJ;
2387                     state.setCurRawAdj(adj);
2388                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2389                     state.setCached(false);
2390                     state.setAdjType("ext-provider");
2391                     state.setAdjTarget(cpr.name);
2392                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2393                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
2394                                 "Raise adj to external provider: " + app);
2395                     }
2396                 }
2397                 if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
2398                     procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
2399                     state.setCurRawProcState(procState);
2400                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2401                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
2402                                 "Raise procstate to external provider: " + app);
2403                     }
2404                 }
2405             }
2406         }
2407 
2408         if (ppr.getLastProviderTime() > 0
2409                 && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
2410             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
2411                 adj = ProcessList.PREVIOUS_APP_ADJ;
2412                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
2413                 state.setCached(false);
2414                 state.setAdjType("recent-provider");
2415                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2416                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
2417                             "Raise adj to recent provider: " + app);
2418                 }
2419             }
2420             if (procState > PROCESS_STATE_LAST_ACTIVITY) {
2421                 procState = PROCESS_STATE_LAST_ACTIVITY;
2422                 state.setAdjType("recent-provider");
2423                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
2424                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
2425                             "Raise procstate to recent provider: " + app);
2426                 }
2427             }
2428         }
2429 
2430         if (procState >= PROCESS_STATE_CACHED_EMPTY) {
2431             if (psr.hasClientActivities()) {
2432                 // This is a cached process, but with client activities.  Mark it so.
2433                 procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
2434                 state.setAdjType("cch-client-act");
2435             } else if (psr.isTreatedLikeActivity()) {
2436                 // This is a cached process, but somebody wants us to treat it like it has
2437                 // an activity, okay!
2438                 procState = PROCESS_STATE_CACHED_ACTIVITY;
2439                 state.setAdjType("cch-as-act");
2440             }
2441         }
2442 
2443         if (adj == ProcessList.SERVICE_ADJ) {
2444             if (doingAll && !cycleReEval) {
2445                 state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3));
2446                 mNewNumServiceProcs++;
2447                 if (!state.isServiceB()) {
2448                     // This service isn't far enough down on the LRU list to
2449                     // normally be a B service, but if we are low on RAM and it
2450                     // is large we want to force it down since we would prefer to
2451                     // keep launcher over it.
2452                     if (!mService.mAppProfiler.isLastMemoryLevelNormal()
2453                             && app.mProfile.getLastPss()
2454                             >= mProcessList.getCachedRestoreThresholdKb()) {
2455                         state.setServiceHighRam(true);
2456                         state.setServiceB(true);
2457                         //Slog.i(TAG, "ADJ " + app + " high ram!");
2458                     } else {
2459                         mNewNumAServiceProcs++;
2460                         //Slog.i(TAG, "ADJ " + app + " not high ram!");
2461                     }
2462                 } else {
2463                     state.setServiceHighRam(false);
2464                 }
2465             }
2466             if (state.isServiceB()) {
2467                 adj = ProcessList.SERVICE_B_ADJ;
2468             }
2469         }
2470 
2471         state.setCurRawAdj(adj);
2472 
2473         if (adj > state.getMaxAdj()) {
2474             adj = state.getMaxAdj();
2475             if (adj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
2476                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2477             }
2478         }
2479 
2480         // Put bound foreground services in a special sched group for additional
2481         // restrictions on screen off
2482         if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
2483                 && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
2484                 && !scheduleLikeTopApp) {
2485             if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) {
2486                 schedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
2487             }
2488         }
2489 
2490         // apply capability from FGS.
2491         if (psr.hasForegroundServices()) {
2492             capability |= capabilityFromFGS;
2493         }
2494 
2495         capability |= getDefaultCapability(psr, procState);
2496 
2497         // Do final modification to adj.  Everything we do between here and applying
2498         // the final setAdj must be done in this function, because we will also use
2499         // it when computing the final cached adj later.  Note that we don't need to
2500         // worry about this for max adj above, since max adj will always be used to
2501         // keep it out of the cached vaues.
2502         state.setCurAdj(psr.modifyRawOomAdj(adj));
2503         state.setCurCapability(capability);
2504         state.setCurrentSchedulingGroup(schedGroup);
2505         state.setCurProcState(procState);
2506         state.setCurRawProcState(procState);
2507         state.updateLastInvisibleTime(hasVisibleActivities);
2508         state.setHasForegroundActivities(foregroundActivities);
2509         state.setCompletedAdjSeq(mAdjSeq);
2510 
2511         // if curAdj or curProcState improved, then this process was promoted
2512         return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
2513                 || state.getCurCapability() != prevCapability;
2514     }
2515 
getDefaultCapability(ProcessServiceRecord psr, int procState)2516     private int getDefaultCapability(ProcessServiceRecord psr, int procState) {
2517         switch (procState) {
2518             case PROCESS_STATE_PERSISTENT:
2519             case PROCESS_STATE_PERSISTENT_UI:
2520             case PROCESS_STATE_TOP:
2521                 return PROCESS_CAPABILITY_ALL;
2522             case PROCESS_STATE_BOUND_TOP:
2523                 return PROCESS_CAPABILITY_NETWORK;
2524             case PROCESS_STATE_FOREGROUND_SERVICE:
2525                 if (psr.hasForegroundServices()) {
2526                     // Capability from FGS are conditional depending on foreground service type in
2527                     // manifest file and the mAllowWhileInUsePermissionInFgs flag.
2528                     return PROCESS_CAPABILITY_NETWORK;
2529                 } else {
2530                     // process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client.
2531                     // the implicit capability could be removed in the future, client should use
2532                     // BIND_INCLUDE_CAPABILITY flag.
2533                     return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK;
2534                 }
2535             case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
2536                 return PROCESS_CAPABILITY_NETWORK;
2537             default:
2538                 return PROCESS_CAPABILITY_NONE;
2539         }
2540     }
2541 
2542     /**
2543      * Checks if for the given app and client, there's a cycle that should skip over the client
2544      * for now or use partial values to evaluate the effect of the client binding.
2545      * @param app
2546      * @param client
2547      * @param procState procstate evaluated so far for this app
2548      * @param adj oom_adj evaluated so far for this app
2549      * @param cycleReEval whether we're currently re-evaluating due to a cycle, and not the first
2550      *                    evaluation.
2551      * @return whether to skip using the client connection at this time
2552      */
shouldSkipDueToCycle(ProcessRecord app, ProcessStateRecord client, int procState, int adj, boolean cycleReEval)2553     private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessStateRecord client,
2554             int procState, int adj, boolean cycleReEval) {
2555         if (client.containsCycle()) {
2556             // We've detected a cycle. We should retry computeOomAdjLSP later in
2557             // case a later-checked connection from a client  would raise its
2558             // priority legitimately.
2559             app.mState.setContainsCycle(true);
2560             mProcessesInCycle.add(app);
2561             // If the client has not been completely evaluated, check if it's worth
2562             // using the partial values.
2563             if (client.getCompletedAdjSeq() < mAdjSeq) {
2564                 if (cycleReEval) {
2565                     // If the partial values are no better, skip until the next
2566                     // attempt
2567                     if (client.getCurRawProcState() >= procState
2568                             && client.getCurRawAdj() >= adj) {
2569                         return true;
2570                     }
2571                     // Else use the client's partial procstate and adj to adjust the
2572                     // effect of the binding
2573                 } else {
2574                     return true;
2575                 }
2576             }
2577         }
2578         return false;
2579     }
2580 
2581     /** Inform the oomadj observer of changes to oomadj. Used by tests. */
2582     @GuardedBy("mService")
reportOomAdjMessageLocked(String tag, String msg)2583     private void reportOomAdjMessageLocked(String tag, String msg) {
2584         Slog.d(tag, msg);
2585         synchronized (mService.mOomAdjObserverLock) {
2586             if (mService.mCurOomAdjObserver != null) {
2587                 mService.mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg)
2588                         .sendToTarget();
2589             }
2590         }
2591     }
2592 
2593     /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
2594     @GuardedBy({"mService", "mProcLock"})
applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, long nowElapsed)2595     private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
2596             long nowElapsed) {
2597         boolean success = true;
2598         final ProcessStateRecord state = app.mState;
2599 
2600         if (state.getCurRawAdj() != state.getSetRawAdj()) {
2601             state.setSetRawAdj(state.getCurRawAdj());
2602         }
2603 
2604         int changes = 0;
2605 
2606         // don't compact during bootup
2607         if (mCachedAppOptimizer.useCompaction() && mService.mBooted) {
2608             // Cached and prev/home compaction
2609             // reminder: here, setAdj is previous state, curAdj is upcoming state
2610             if (state.getCurAdj() != state.getSetAdj()) {
2611                 mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app);
2612             } else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
2613                     && state.getSetAdj() < ProcessList.FOREGROUND_APP_ADJ
2614                     // Because these can fire independent of oom_adj/procstate changes, we need
2615                     // to throttle the actual dispatch of these requests in addition to the
2616                     // processing of the requests. As a result, there is throttling both here
2617                     // and in CachedAppOptimizer.
2618                     && mCachedAppOptimizer.shouldCompactPersistent(app, now)) {
2619                 mCachedAppOptimizer.compactAppPersistent(app);
2620             } else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
2621                     && state.getCurProcState()
2622                         == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
2623                     && mCachedAppOptimizer.shouldCompactBFGS(app, now)) {
2624                 mCachedAppOptimizer.compactAppBfgs(app);
2625             }
2626         }
2627 
2628         if (state.getCurAdj() != state.getSetAdj()) {
2629             ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj());
2630             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
2631                 String msg = "Set " + app.getPid() + " " + app.processName + " adj "
2632                         + state.getCurAdj() + ": " + state.getAdjType();
2633                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
2634             }
2635             state.setSetAdj(state.getCurAdj());
2636             state.setVerifiedAdj(ProcessList.INVALID_ADJ);
2637         }
2638 
2639         final int curSchedGroup = state.getCurrentSchedulingGroup();
2640         if (state.getSetSchedGroup() != curSchedGroup) {
2641             int oldSchedGroup = state.getSetSchedGroup();
2642             state.setSetSchedGroup(curSchedGroup);
2643             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
2644                 String msg = "Setting sched group of " + app.processName
2645                         + " to " + curSchedGroup + ": " + state.getAdjType();
2646                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
2647             }
2648             if (app.getWaitingToKill() != null && app.mReceivers.numberOfCurReceivers() == 0
2649                     && state.getSetSchedGroup() == ProcessList.SCHED_GROUP_BACKGROUND) {
2650                 app.killLocked(app.getWaitingToKill(), ApplicationExitInfo.REASON_USER_REQUESTED,
2651                         ApplicationExitInfo.SUBREASON_UNKNOWN, true);
2652                 success = false;
2653             } else {
2654                 int processGroup;
2655                 switch (curSchedGroup) {
2656                     case ProcessList.SCHED_GROUP_BACKGROUND:
2657                         processGroup = THREAD_GROUP_BACKGROUND;
2658                         break;
2659                     case ProcessList.SCHED_GROUP_TOP_APP:
2660                     case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
2661                         processGroup = THREAD_GROUP_TOP_APP;
2662                         break;
2663                     case ProcessList.SCHED_GROUP_RESTRICTED:
2664                         processGroup = THREAD_GROUP_RESTRICTED;
2665                         break;
2666                     default:
2667                         processGroup = THREAD_GROUP_DEFAULT;
2668                         break;
2669                 }
2670                 mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
2671                         0 /* unused */, app.getPid(), processGroup, app.processName));
2672                 try {
2673                     final int renderThreadTid = app.getRenderThreadTid();
2674                     if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
2675                         // do nothing if we already switched to RT
2676                         if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
2677                             app.getWindowProcessController().onTopProcChanged();
2678                             if (mService.mUseFifoUiScheduling) {
2679                                 // Switch UI pipeline for app to SCHED_FIFO
2680                                 state.setSavedPriority(Process.getThreadPriority(app.getPid()));
2681                                 mService.scheduleAsFifoPriority(app.getPid(), true);
2682                                 if (renderThreadTid != 0) {
2683                                     mService.scheduleAsFifoPriority(renderThreadTid,
2684                                             /* suppressLogs */true);
2685                                     if (DEBUG_OOM_ADJ) {
2686                                         Slog.d("UI_FIFO", "Set RenderThread (TID " +
2687                                                 renderThreadTid + ") to FIFO");
2688                                     }
2689                                 } else {
2690                                     if (DEBUG_OOM_ADJ) {
2691                                         Slog.d("UI_FIFO", "Not setting RenderThread TID");
2692                                     }
2693                                 }
2694                             } else {
2695                                 // Boost priority for top app UI and render threads
2696                                 setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
2697                                 if (renderThreadTid != 0) {
2698                                     try {
2699                                         setThreadPriority(renderThreadTid,
2700                                                 THREAD_PRIORITY_TOP_APP_BOOST);
2701                                     } catch (IllegalArgumentException e) {
2702                                         // thread died, ignore
2703                                     }
2704                                 }
2705                             }
2706                         }
2707                     } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
2708                             curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
2709                         app.getWindowProcessController().onTopProcChanged();
2710                         if (mService.mUseFifoUiScheduling) {
2711                             try {
2712                                 // Reset UI pipeline to SCHED_OTHER
2713                                 setThreadScheduler(app.getPid(), SCHED_OTHER, 0);
2714                                 setThreadPriority(app.getPid(), state.getSavedPriority());
2715                                 if (renderThreadTid != 0) {
2716                                     setThreadScheduler(renderThreadTid,
2717                                             SCHED_OTHER, 0);
2718                                 }
2719                             } catch (IllegalArgumentException e) {
2720                                 Slog.w(TAG,
2721                                         "Failed to set scheduling policy, thread does not exist:\n"
2722                                                 + e);
2723                             } catch (SecurityException e) {
2724                                 Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
2725                             }
2726                         } else {
2727                             // Reset priority for top app UI and render threads
2728                             setThreadPriority(app.getPid(), 0);
2729                         }
2730 
2731                         if (renderThreadTid != 0) {
2732                             setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY);
2733                         }
2734                     }
2735                 } catch (Exception e) {
2736                     if (DEBUG_ALL) {
2737                         Slog.w(TAG, "Failed setting thread priority of " + app.getPid(), e);
2738                     }
2739                 }
2740             }
2741         }
2742         if (state.hasRepForegroundActivities() != state.hasForegroundActivities()) {
2743             state.setRepForegroundActivities(state.hasForegroundActivities());
2744             changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES;
2745         }
2746 
2747         updateAppFreezeStateLSP(app);
2748 
2749         if (state.getReportedProcState() != state.getCurProcState()) {
2750             state.setReportedProcState(state.getCurProcState());
2751             if (app.getThread() != null) {
2752                 try {
2753                     if (false) {
2754                         //RuntimeException h = new RuntimeException("here");
2755                         Slog.i(TAG, "Sending new process state " + state.getReportedProcState()
2756                                 + " to " + app /*, h*/);
2757                     }
2758                     app.getThread().setProcessState(state.getReportedProcState());
2759                 } catch (RemoteException e) {
2760                 }
2761             }
2762         }
2763         boolean forceUpdatePssTime = false;
2764         if (state.getSetProcState() == PROCESS_STATE_NONEXISTENT
2765                 || ProcessList.procStatesDifferForMem(
2766                         state.getCurProcState(), state.getSetProcState())) {
2767             state.setLastStateTime(now);
2768             forceUpdatePssTime = true;
2769             if (DEBUG_PSS) {
2770                 Slog.d(TAG_PSS, "Process state change from "
2771                         + ProcessList.makeProcStateString(state.getSetProcState()) + " to "
2772                         + ProcessList.makeProcStateString(state.getCurProcState()) + " next pss in "
2773                         + (app.mProfile.getNextPssTime() - now) + ": " + app);
2774             }
2775         }
2776         synchronized (mService.mAppProfiler.mProfilerLock) {
2777             app.mProfile.updateProcState(app.mState);
2778             mService.mAppProfiler.updateNextPssTimeLPf(
2779                     state.getCurProcState(), app.mProfile, now, forceUpdatePssTime);
2780         }
2781         if (state.getSetProcState() != state.getCurProcState()) {
2782             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
2783                 String msg = "Proc state change of " + app.processName
2784                         + " to " + ProcessList.makeProcStateString(state.getCurProcState())
2785                         + " (" + state.getCurProcState() + ")" + ": " + state.getAdjType();
2786                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
2787             }
2788             boolean setImportant = state.getSetProcState() < PROCESS_STATE_SERVICE;
2789             boolean curImportant = state.getCurProcState() < PROCESS_STATE_SERVICE;
2790             if (setImportant && !curImportant) {
2791                 // This app is no longer something we consider important enough to allow to use
2792                 // arbitrary amounts of battery power. Note its current CPU time to later know to
2793                 // kill it if it is not behaving well.
2794                 state.setWhenUnimportant(now);
2795                 app.mProfile.mLastCpuTime.set(0);
2796             }
2797             // Inform UsageStats of important process state change
2798             // Must be called before updating setProcState
2799             maybeUpdateUsageStatsLSP(app, nowElapsed);
2800 
2801             maybeUpdateLastTopTime(state, now);
2802 
2803             state.setSetProcState(state.getCurProcState());
2804             if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) {
2805                 state.setNotCachedSinceIdle(false);
2806             }
2807             if (!doingAll) {
2808                 synchronized (mService.mProcessStats.mLock) {
2809                     mService.setProcessTrackerStateLOSP(app,
2810                             mService.mProcessStats.getMemFactorLocked(), now);
2811                 }
2812             } else {
2813                 state.setProcStateChanged(true);
2814             }
2815         } else if (state.hasReportedInteraction()) {
2816             final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange(
2817                     CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME);
2818             final long interactionThreshold = fgsInteractionChangeEnabled
2819                     ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S
2820                     : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S;
2821             // For apps that sit around for a long time in the interactive state, we need
2822             // to report this at least once a day so they don't go idle.
2823             if ((nowElapsed - state.getInteractionEventTime()) > interactionThreshold) {
2824                 maybeUpdateUsageStatsLSP(app, nowElapsed);
2825             }
2826         } else {
2827             final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange(
2828                     CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME);
2829             final long interactionThreshold = fgsInteractionChangeEnabled
2830                     ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S
2831                     : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S;
2832             // For foreground services that sit around for a long time but are not interacted with.
2833             if ((nowElapsed - state.getFgInteractionTime()) > interactionThreshold) {
2834                 maybeUpdateUsageStatsLSP(app, nowElapsed);
2835             }
2836         }
2837 
2838         if (state.getCurCapability() != state.getSetCapability()) {
2839             changes |= ActivityManagerService.ProcessChangeItem.CHANGE_CAPABILITY;
2840             state.setSetCapability(state.getCurCapability());
2841         }
2842 
2843         if (changes != 0) {
2844             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
2845                     "Changes in " + app + ": " + changes);
2846             ActivityManagerService.ProcessChangeItem item =
2847                     mProcessList.enqueueProcessChangeItemLocked(app.getPid(), app.info.uid);
2848             item.changes |= changes;
2849             item.foregroundActivities = state.hasRepForegroundActivities();
2850             item.capability = state.getSetCapability();
2851             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
2852                     "Item " + Integer.toHexString(System.identityHashCode(item))
2853                             + " " + app.toShortString() + ": changes=" + item.changes
2854                             + " foreground=" + item.foregroundActivities
2855                             + " type=" + state.getAdjType() + " source=" + state.getAdjSource()
2856                             + " target=" + state.getAdjTarget() + " capability=" + item.capability);
2857         }
2858 
2859         return success;
2860     }
2861 
2862     @GuardedBy({"mService", "mProcLock"})
setAttachingSchedGroupLSP(ProcessRecord app)2863     void setAttachingSchedGroupLSP(ProcessRecord app) {
2864         int initialSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2865         final ProcessStateRecord state = app.mState;
2866         // If the process has been marked as foreground via Zygote.START_FLAG_USE_TOP_APP_PRIORITY,
2867         // then verify that the top priority is actually is applied.
2868         if (state.hasForegroundActivities()) {
2869             String fallbackReason = null;
2870             try {
2871                 // The priority must be the same as how does {@link #applyOomAdjLSP} set for
2872                 // {@link ProcessList.SCHED_GROUP_TOP_APP}. We don't check render thread because it
2873                 // is not ready when attaching.
2874                 if (Process.getProcessGroup(app.getPid()) == THREAD_GROUP_TOP_APP) {
2875                     app.getWindowProcessController().onTopProcChanged();
2876                     setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
2877                 } else {
2878                     fallbackReason = "not expected top priority";
2879                 }
2880             } catch (Exception e) {
2881                 fallbackReason = e.toString();
2882             }
2883             if (fallbackReason == null) {
2884                 initialSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
2885             } else {
2886                 // The real scheduling group will depend on if there is any component of the process
2887                 // did something during attaching.
2888                 Slog.w(TAG, "Fallback pre-set sched group to default: " + fallbackReason);
2889             }
2890         }
2891 
2892         state.setSetSchedGroup(initialSchedGroup);
2893         state.setCurrentSchedulingGroup(initialSchedGroup);
2894     }
2895 
2896     // ONLY used for unit testing in OomAdjusterTests.java
2897     @VisibleForTesting
maybeUpdateUsageStats(ProcessRecord app, long nowElapsed)2898     void maybeUpdateUsageStats(ProcessRecord app, long nowElapsed) {
2899         synchronized (mService) {
2900             synchronized (mProcLock) {
2901                 maybeUpdateUsageStatsLSP(app, nowElapsed);
2902             }
2903         }
2904     }
2905 
2906     @GuardedBy({"mService", "mProcLock"})
maybeUpdateUsageStatsLSP(ProcessRecord app, long nowElapsed)2907     private void maybeUpdateUsageStatsLSP(ProcessRecord app, long nowElapsed) {
2908         final ProcessStateRecord state = app.mState;
2909         if (DEBUG_USAGE_STATS) {
2910             Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList())
2911                     + "] state changes: old = " + state.getSetProcState() + ", new = "
2912                     + state.getCurProcState());
2913         }
2914         if (mService.mUsageStatsService == null) {
2915             return;
2916         }
2917         final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange(
2918                 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME);
2919         boolean isInteraction;
2920         // To avoid some abuse patterns, we are going to be careful about what we consider
2921         // to be an app interaction.  Being the top activity doesn't count while the display
2922         // is sleeping, nor do short foreground services.
2923         if (state.getCurProcState() <= PROCESS_STATE_TOP
2924                 || state.getCurProcState() == PROCESS_STATE_BOUND_TOP) {
2925             isInteraction = true;
2926             state.setFgInteractionTime(0);
2927         } else if (state.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) {
2928             if (state.getFgInteractionTime() == 0) {
2929                 state.setFgInteractionTime(nowElapsed);
2930                 isInteraction = false;
2931             } else {
2932                 final long interactionTime = fgsInteractionChangeEnabled
2933                         ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S
2934                         : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S;
2935                 isInteraction = nowElapsed > state.getFgInteractionTime() + interactionTime;
2936             }
2937         } else {
2938             isInteraction =
2939                     state.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND;
2940             state.setFgInteractionTime(0);
2941         }
2942         final long interactionThreshold = fgsInteractionChangeEnabled
2943                 ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S
2944                 : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S;
2945         if (isInteraction
2946                 && (!state.hasReportedInteraction()
2947                     || (nowElapsed - state.getInteractionEventTime()) > interactionThreshold)) {
2948             state.setInteractionEventTime(nowElapsed);
2949             String[] packages = app.getPackageList();
2950             if (packages != null) {
2951                 for (int i = 0; i < packages.length; i++) {
2952                     mService.mUsageStatsService.reportEvent(packages[i], app.userId,
2953                             UsageEvents.Event.SYSTEM_INTERACTION);
2954                 }
2955             }
2956         }
2957         state.setReportedInteraction(isInteraction);
2958         if (!isInteraction) {
2959             state.setInteractionEventTime(0);
2960         }
2961     }
2962 
maybeUpdateLastTopTime(ProcessStateRecord state, long nowUptime)2963     private void maybeUpdateLastTopTime(ProcessStateRecord state, long nowUptime) {
2964         if (state.getSetProcState() <= PROCESS_STATE_TOP
2965                 && state.getCurProcState() > PROCESS_STATE_TOP) {
2966             state.setLastTopTime(nowUptime);
2967         }
2968     }
2969 
2970     /**
2971      * Look for recently inactive apps and mark them idle after a grace period. If idled, stop
2972      * any background services and inform listeners.
2973      */
2974     @GuardedBy("mService")
idleUidsLocked()2975     void idleUidsLocked() {
2976         final int N = mActiveUids.size();
2977         if (N <= 0) {
2978             return;
2979         }
2980         final long nowElapsed = SystemClock.elapsedRealtime();
2981         final long maxBgTime = nowElapsed - mConstants.BACKGROUND_SETTLE_TIME;
2982         long nextTime = 0;
2983         if (mLocalPowerManager != null) {
2984             mLocalPowerManager.startUidChanges();
2985         }
2986         for (int i = N - 1; i >= 0; i--) {
2987             final UidRecord uidRec = mActiveUids.valueAt(i);
2988             final long bgTime = uidRec.getLastBackgroundTime();
2989             if (bgTime > 0 && !uidRec.isIdle()) {
2990                 if (bgTime <= maxBgTime) {
2991                     EventLogTags.writeAmUidIdle(uidRec.getUid());
2992                     synchronized (mProcLock) {
2993                         uidRec.setIdle(true);
2994                         uidRec.setSetIdle(true);
2995                     }
2996                     mService.doStopUidLocked(uidRec.getUid(), uidRec);
2997                 } else {
2998                     if (nextTime == 0 || nextTime > bgTime) {
2999                         nextTime = bgTime;
3000                     }
3001                 }
3002             }
3003         }
3004         if (mLocalPowerManager != null) {
3005             mLocalPowerManager.finishUidChanges();
3006         }
3007         if (nextTime > 0) {
3008             mService.mHandler.removeMessages(IDLE_UIDS_MSG);
3009             mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
3010                     nextTime + mConstants.BACKGROUND_SETTLE_TIME - nowElapsed);
3011         }
3012     }
3013 
3014     @GuardedBy({"mService", "mProcLock"})
setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist)3015     void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
3016         boolean changed = false;
3017         for (int i = mActiveUids.size() - 1; i >= 0; i--) {
3018             final UidRecord uidRec = mActiveUids.valueAt(i);
3019             if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) {
3020                 uidRec.setCurAllowListed(onAllowlist);
3021                 changed = true;
3022             }
3023         }
3024         if (changed) {
3025             updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
3026         }
3027     }
3028 
3029     @GuardedBy({"mService", "mProcLock"})
setUidTempAllowlistStateLSP(int uid, boolean onAllowlist)3030     void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
3031         boolean changed = false;
3032         final UidRecord uidRec = mActiveUids.get(uid);
3033         if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) {
3034             uidRec.setCurAllowListed(onAllowlist);
3035             updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
3036         }
3037     }
3038 
3039     @GuardedBy("mService")
dumpProcessListVariablesLocked(ProtoOutputStream proto)3040     void dumpProcessListVariablesLocked(ProtoOutputStream proto) {
3041         proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq);
3042         proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.getLruSeqLOSP());
3043         proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS,
3044                 mNumNonCachedProcs);
3045         proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs);
3046         proto.write(ActivityManagerServiceDumpProcessesProto.NEW_NUM_SERVICE_PROCS,
3047                 mNewNumServiceProcs);
3048 
3049     }
3050 
3051     @GuardedBy("mService")
dumpSequenceNumbersLocked(PrintWriter pw)3052     void dumpSequenceNumbersLocked(PrintWriter pw) {
3053         pw.println("  mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.getLruSeqLOSP());
3054     }
3055 
3056     @GuardedBy("mService")
dumpProcCountsLocked(PrintWriter pw)3057     void dumpProcCountsLocked(PrintWriter pw) {
3058         pw.println("  mNumNonCachedProcs=" + mNumNonCachedProcs
3059                 + " (" + mProcessList.getLruSizeLOSP() + " total)"
3060                 + " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
3061                 + " mNumServiceProcs=" + mNumServiceProcs
3062                 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
3063     }
3064 
3065     @GuardedBy("mProcLock")
dumpCachedAppOptimizerSettings(PrintWriter pw)3066     void dumpCachedAppOptimizerSettings(PrintWriter pw) {
3067         mCachedAppOptimizer.dump(pw);
3068     }
3069 
3070     @GuardedBy("mService")
dumpCacheOomRankerSettings(PrintWriter pw)3071     void dumpCacheOomRankerSettings(PrintWriter pw) {
3072         mCacheOomRanker.dump(pw);
3073     }
3074 
3075     @GuardedBy({"mService", "mProcLock"})
updateAppFreezeStateLSP(ProcessRecord app)3076     private void updateAppFreezeStateLSP(ProcessRecord app) {
3077         if (!mCachedAppOptimizer.useFreezer()) {
3078             return;
3079         }
3080 
3081         if (app.mOptRecord.isFreezeExempt()) {
3082             return;
3083         }
3084 
3085         final ProcessCachedOptimizerRecord opt = app.mOptRecord;
3086         // if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze
3087         if (opt.isFrozen() && opt.shouldNotFreeze()) {
3088             mCachedAppOptimizer.unfreezeAppLSP(app);
3089             return;
3090         }
3091 
3092         final ProcessStateRecord state = app.mState;
3093         // Use current adjustment when freezing, set adjustment when unfreezing.
3094         if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
3095                 && !opt.shouldNotFreeze()) {
3096             mCachedAppOptimizer.freezeAppAsyncLSP(app);
3097         } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
3098             mCachedAppOptimizer.unfreezeAppLSP(app);
3099         }
3100     }
3101 }
3102