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