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