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_NONE;
25 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
26 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
27 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
28 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
29 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
30 import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
31 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
32 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
33 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
34 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
35 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
36 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
37 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
38 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
39 import static android.app.ActivityManager.PROCESS_STATE_TOP;
40 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
41 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
42 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
43 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
44 import static android.os.Process.SCHED_OTHER;
45 import static android.os.Process.THREAD_GROUP_BACKGROUND;
46 import static android.os.Process.THREAD_GROUP_DEFAULT;
47 import static android.os.Process.THREAD_GROUP_RESTRICTED;
48 import static android.os.Process.THREAD_GROUP_TOP_APP;
49 import static android.os.Process.THREAD_PRIORITY_DISPLAY;
50 import static android.os.Process.setProcessGroup;
51 import static android.os.Process.setThreadPriority;
52 import static android.os.Process.setThreadScheduler;
53 
54 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
55 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
56 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
58 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON;
59 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
61 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
62 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
63 import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG;
64 import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG;
65 import static com.android.server.am.ActivityManagerService.TAG_BACKUP;
66 import static com.android.server.am.ActivityManagerService.TAG_LRU;
67 import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ;
68 import static com.android.server.am.ActivityManagerService.TAG_PROCESS_OBSERVERS;
69 import static com.android.server.am.ActivityManagerService.TAG_PSS;
70 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
71 import static com.android.server.am.ActivityManagerService.TOP_APP_PRIORITY_BOOST;
72 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
73 
74 import android.app.ActivityManager;
75 import android.app.ApplicationExitInfo;
76 import android.app.usage.UsageEvents;
77 import android.compat.annotation.ChangeId;
78 import android.compat.annotation.EnabledAfter;
79 import android.content.Context;
80 import android.content.pm.ServiceInfo;
81 import android.os.Debug;
82 import android.os.Handler;
83 import android.os.IBinder;
84 import android.os.PowerManagerInternal;
85 import android.os.Process;
86 import android.os.RemoteException;
87 import android.os.ServiceManager;
88 import android.os.SystemClock;
89 import android.os.Trace;
90 import android.os.UserHandle;
91 import android.util.ArrayMap;
92 import android.util.ArraySet;
93 import android.util.Slog;
94 import android.util.proto.ProtoOutputStream;
95 
96 import com.android.internal.annotations.GuardedBy;
97 import com.android.internal.annotations.VisibleForTesting;
98 import com.android.internal.app.procstats.ProcessStats;
99 import com.android.internal.compat.IPlatformCompat;
100 import com.android.server.LocalServices;
101 import com.android.server.ServiceThread;
102 import com.android.server.wm.ActivityServiceConnectionsHolder;
103 import com.android.server.wm.WindowProcessController;
104 
105 import java.io.PrintWriter;
106 import java.util.ArrayDeque;
107 import java.util.ArrayList;
108 import java.util.Arrays;
109 
110 /**
111  * All of the code required to compute proc states and oom_adj values.
112  */
113 public final class OomAdjuster {
114     private static final String TAG = "OomAdjuster";
115     static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
116     static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
117     static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
118     static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
119     static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
120     static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
121     static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
122     static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
123     static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
124     static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
125     static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
126     static final String OOM_ADJ_REASON_WHITELIST = OOM_ADJ_REASON_METHOD + "_whitelistChange";
127     static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
128     static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";
129 
130     /**
131      * Flag {@link android.content.Context#BIND_INCLUDE_CAPABILITIES} is used
132      * to pass while-in-use capabilities from client process to bound service. In targetSdkVersion
133      * R and above, if client is a TOP activity, when this flag is present, bound service gets all
134      * while-in-use capabilities; when this flag is not present, bound service gets no while-in-use
135      * capability from client.
136      */
137     @ChangeId
138     @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
139     static final long PROCESS_CAPABILITY_CHANGE_ID = 136274596L;
140 
141     /**
142      * In targetSdkVersion R and above, foreground service has camera and microphone while-in-use
143      * capability only when the {@link android.R.attr#foregroundServiceType} is configured as
144      * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and
145      * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the
146      * manifest file.
147      * In targetSdkVersion below R, foreground service automatically have camera and microphone
148      * capabilities.
149      */
150     @ChangeId
151     @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
152     static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
153 
154     /**
155      * For some direct access we need to power manager.
156      */
157     PowerManagerInternal mLocalPowerManager;
158 
159     /**
160      * Service for optimizing resource usage from background apps.
161      */
162     CachedAppOptimizer mCachedAppOptimizer;
163 
164     ActivityManagerConstants mConstants;
165 
166     final long[] mTmpLong = new long[3];
167 
168     /**
169      * Current sequence id for oom_adj computation traversal.
170      */
171     int mAdjSeq = 0;
172 
173     /**
174      * Keep track of the number of service processes we last found, to
175      * determine on the next iteration which should be B services.
176      */
177     int mNumServiceProcs = 0;
178     int mNewNumAServiceProcs = 0;
179     int mNewNumServiceProcs = 0;
180 
181     /**
182      * Keep track of the non-cached/empty process we last found, to help
183      * determine how to distribute cached/empty processes next time.
184      */
185     int mNumNonCachedProcs = 0;
186 
187     /**
188      * Keep track of the number of cached hidden procs, to balance oom adj
189      * distribution between those and empty procs.
190      */
191     int mNumCachedHiddenProcs = 0;
192 
193     /** Track all uids that have actively running processes. */
194     ActiveUids mActiveUids;
195 
196     /**
197      * The handler to execute {@link #setProcessGroup} (it may be heavy if the process has many
198      * threads) for reducing the time spent in {@link #applyOomAdjLocked}.
199      */
200     private final Handler mProcessGroupHandler;
201 
202     private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
203 
204     private final ActivityManagerService mService;
205     private final ProcessList mProcessList;
206 
207     private final int mNumSlots;
208     private ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
209     private ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
210     private ActiveUids mTmpUidRecords;
211     private ArrayDeque<ProcessRecord> mTmpQueue;
212 
213     private final IPlatformCompat mPlatformCompat;
214 
OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids)215     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
216         this(service, processList, activeUids, createAdjusterThread());
217     }
218 
createAdjusterThread()219     private static ServiceThread createAdjusterThread() {
220         // The process group is usually critical to the response time of foreground app, so the
221         // setter should apply it as soon as possible.
222         final ServiceThread adjusterThread =
223                 new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST, false /* allowIo */);
224         adjusterThread.start();
225         adjusterThread.getThreadHandler().post(() -> Process.setThreadGroupAndCpuset(
226                 adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP));
227         return adjusterThread;
228     }
229 
OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, ServiceThread adjusterThread)230     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
231             ServiceThread adjusterThread) {
232         mService = service;
233         mProcessList = processList;
234         mActiveUids = activeUids;
235 
236         mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
237         mConstants = mService.mConstants;
238         mCachedAppOptimizer = new CachedAppOptimizer(mService);
239 
240         mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
241             final int pid = msg.arg1;
242             final int group = msg.arg2;
243             if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
244                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup "
245                         + msg.obj + " to " + group);
246             }
247             try {
248                 setProcessGroup(pid, group);
249             } catch (Exception e) {
250                 if (DEBUG_ALL) {
251                     Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e);
252                 }
253             } finally {
254                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
255             }
256             return true;
257         });
258         mTmpUidRecords = new ActiveUids(service, false);
259         mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1);
260         mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1)
261                 / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
262         IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
263         mPlatformCompat = IPlatformCompat.Stub.asInterface(b);
264     }
265 
initSettings()266     void initSettings() {
267         mCachedAppOptimizer.init();
268     }
269 
270     /**
271      * Update OomAdj for a specific process.
272      * @param app The process to update
273      * @param oomAdjAll If it's ok to call updateOomAdjLocked() for all running apps
274      *                  if necessary, or skip.
275      * @param oomAdjReason
276      * @return whether updateOomAdjLocked(app) was successful.
277      */
278     @GuardedBy("mService")
updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll, String oomAdjReason)279     boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
280             String oomAdjReason) {
281         if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
282             return updateOomAdjLocked(app, oomAdjReason);
283         }
284         final ProcessRecord TOP_APP = mService.getTopAppLocked();
285         final boolean wasCached = app.isCached();
286 
287         mAdjSeq++;
288 
289         // This is the desired cached adjusment we want to tell it to use.
290         // If our app is currently cached, we know it, and that is it.  Otherwise,
291         // we don't know it yet, and it needs to now be cached we will then
292         // need to do a complete oom adj.
293         final int cachedAdj = app.getCurRawAdj() >= ProcessList.CACHED_APP_MIN_ADJ
294                 ? app.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
295         boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
296                 SystemClock.uptimeMillis());
297         if (oomAdjAll
298                 && (wasCached != app.isCached() || app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
299             // Changed to/from cached state, so apps after it in the LRU
300             // list may also be changed.
301             updateOomAdjLocked(oomAdjReason);
302         }
303         return success;
304     }
305 
306     @GuardedBy("mService")
updateOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now)307     private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
308             ProcessRecord TOP_APP, boolean doingAll, long now) {
309         if (app.thread == null) {
310             return false;
311         }
312 
313         app.resetCachedInfo();
314         UidRecord uidRec = app.uidRecord;
315         if (uidRec != null) {
316             if (DEBUG_UID_OBSERVERS) {
317                 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
318             }
319             uidRec.reset();
320         }
321 
322         computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false, true);
323 
324         boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
325 
326         if (uidRec != null) {
327             // After uidRec.reset() above, for UidRecord that has multiple processes (ProcessRecord)
328             // , We need to apply all ProcessRecord into UidRecord.
329             final ArraySet<ProcessRecord> procRecords = app.uidRecord.procRecords;
330             for (int i = procRecords.size() - 1; i >= 0; i--) {
331                 final ProcessRecord pr = procRecords.valueAt(i);
332                 if (!pr.killedByAm && pr.thread != null) {
333                     if (pr.isolated && pr.numberOfRunningServices() <= 0
334                             && pr.isolatedEntryPoint == null) {
335                         // No op.
336                     } else {
337                         // Keeping this process, update its uid.
338                         updateAppUidRecLocked(pr);
339                     }
340                 }
341             }
342             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
343                     && (uidRec.setProcState != uidRec.getCurProcState()
344                     || uidRec.setCapability != uidRec.curCapability
345                     || uidRec.setWhitelist != uidRec.curWhitelist)) {
346                 ActiveUids uids = mTmpUidRecords;
347                 uids.clear();
348                 uids.put(uidRec.uid, uidRec);
349                 updateUidsLocked(uids, now);
350                 mProcessList.incrementProcStateSeqAndNotifyAppsLocked(uids);
351             }
352         }
353 
354         return success;
355     }
356 
357     /**
358      * Update OomAdj for all processes in LRU list
359      */
360     @GuardedBy("mService")
updateOomAdjLocked(String oomAdjReason)361     void updateOomAdjLocked(String oomAdjReason) {
362         final ProcessRecord topApp = mService.getTopAppLocked();
363         updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
364     }
365 
366     /**
367      * Update OomAdj for specific process and its reachable processes (with direction/indirect
368      * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc
369      * is hosting any service/content provider.
370      *
371      * @param app The process to update, or null to update all processes
372      * @param oomAdjReason
373      */
374     @GuardedBy("mService")
updateOomAdjLocked(ProcessRecord app, String oomAdjReason)375     boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
376         if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
377             updateOomAdjLocked(oomAdjReason);
378             return true;
379         }
380 
381         final ProcessRecord topApp = mService.getTopAppLocked();
382 
383         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
384         mService.mOomAdjProfiler.oomAdjStarted();
385         mAdjSeq++;
386 
387         // Firstly, try to see if the importance of itself gets changed
388         final boolean wasCached = app.isCached();
389         final int oldAdj = app.getCurRawAdj();
390         final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
391                 ? oldAdj : ProcessList.UNKNOWN_ADJ;
392         final boolean wasBackground = ActivityManager.isProcStateBackground(app.setProcState);
393         app.containsCycle = false;
394         app.procStateChanged = false;
395         app.resetCachedInfo();
396         boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
397                 SystemClock.uptimeMillis());
398         if (!success || (wasCached == app.isCached() && oldAdj != ProcessList.INVALID_ADJ
399                 && wasBackground == ActivityManager.isProcStateBackground(app.setProcState))) {
400             // Okay, it's unchanged, it won't impact any service it binds to, we're done here.
401             if (DEBUG_OOM_ADJ) {
402                 Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
403             }
404             mService.mOomAdjProfiler.oomAdjEnded();
405             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
406             return success;
407         }
408 
409         // Next to find out all its reachable processes
410         ArrayList<ProcessRecord> processes = mTmpProcessList;
411         ActiveUids uids = mTmpUidRecords;
412         ArrayDeque<ProcessRecord> queue = mTmpQueue;
413 
414         processes.clear();
415         uids.clear();
416         queue.clear();
417 
418         // Track if any of them reachables could include a cycle
419         boolean containsCycle = false;
420         // Scan downstreams of the process record
421         app.mReachable = true;
422         for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
423             if (pr != app) {
424                 processes.add(pr);
425             }
426             if (pr.uidRecord != null) {
427                 uids.put(pr.uidRecord.uid, pr.uidRecord);
428             }
429             for (int i = pr.connections.size() - 1; i >= 0; i--) {
430                 ConnectionRecord cr = pr.connections.valueAt(i);
431                 ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
432                         ? cr.binding.service.isolatedProc : cr.binding.service.app;
433                 if (service == null || service == pr) {
434                     continue;
435                 }
436                 containsCycle |= service.mReachable;
437                 if (service.mReachable) {
438                     continue;
439                 }
440                 if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
441                         | Context.BIND_TREAT_LIKE_ACTIVITY
442                         | Context.BIND_ADJUST_WITH_ACTIVITY))
443                         == Context.BIND_WAIVE_PRIORITY) {
444                     continue;
445                 }
446                 queue.offer(service);
447                 service.mReachable = true;
448             }
449             for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
450                 ContentProviderConnection cpc = pr.conProviders.get(i);
451                 ProcessRecord provider = cpc.provider.proc;
452                 if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) {
453                     continue;
454                 }
455                 containsCycle |= provider.mReachable;
456                 if (provider.mReachable) {
457                     continue;
458                 }
459                 queue.offer(provider);
460                 provider.mReachable = true;
461             }
462         }
463 
464         // Reset the flag
465         app.mReachable = false;
466         int size = processes.size();
467         if (size > 0) {
468             // Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
469             for (int l = 0, r = size - 1; l < r; l++, r--) {
470                 ProcessRecord t = processes.get(l);
471                 processes.set(l, processes.get(r));
472                 processes.set(r, t);
473             }
474             mAdjSeq--;
475             // Update these reachable processes
476             updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, containsCycle, false);
477         } else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
478             // In case the app goes from non-cached to cached but it doesn't have other reachable
479             // processes, its adj could be still unknown as of now, assign one.
480             processes.add(app);
481             assignCachedAdjIfNecessary(processes);
482             applyOomAdjLocked(app, false, SystemClock.uptimeMillis(),
483                     SystemClock.elapsedRealtime());
484         }
485         mService.mOomAdjProfiler.oomAdjEnded();
486         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
487         return true;
488     }
489 
490     /**
491      * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
492      * list if the given list is null; when it's partial update, each process's client proc won't
493      * get evaluated recursively here.
494      */
495     @GuardedBy("mService")
updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp, ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles, boolean startProfiling)496     private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
497             ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
498             boolean startProfiling) {
499         if (startProfiling) {
500             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
501             mService.mOomAdjProfiler.oomAdjStarted();
502         }
503         final long now = SystemClock.uptimeMillis();
504         final long nowElapsed = SystemClock.elapsedRealtime();
505         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
506         final boolean fullUpdate = processes == null;
507         ActiveUids activeUids = uids;
508         ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.mLruProcesses
509                 : processes;
510         final int numProc = activeProcesses.size();
511 
512         if (activeUids == null) {
513             final int numUids = mActiveUids.size();
514             activeUids = mTmpUidRecords;
515             activeUids.clear();
516             for (int i = 0; i < numUids; i++) {
517                 UidRecord r = mActiveUids.valueAt(i);
518                 activeUids.put(r.uid, r);
519             }
520         }
521 
522         // Reset state in all uid records.
523         for (int  i = activeUids.size() - 1; i >= 0; i--) {
524             final UidRecord uidRec = activeUids.valueAt(i);
525             if (DEBUG_UID_OBSERVERS) {
526                 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
527             }
528             uidRec.reset();
529         }
530 
531         if (mService.mAtmInternal != null) {
532             mService.mAtmInternal.rankTaskLayersIfNeeded();
533         }
534 
535         mAdjSeq++;
536         if (fullUpdate) {
537             mNewNumServiceProcs = 0;
538             mNewNumAServiceProcs = 0;
539         }
540 
541         boolean retryCycles = false;
542         boolean computeClients = fullUpdate || potentialCycles;
543 
544         // need to reset cycle state before calling computeOomAdjLocked because of service conns
545         for (int i = numProc - 1; i >= 0; i--) {
546             ProcessRecord app = activeProcesses.get(i);
547             app.mReachable = false;
548             // No need to compute again it has been evaluated in previous iteration
549             if (app.adjSeq != mAdjSeq) {
550                 app.containsCycle = false;
551                 app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
552                 app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
553                 app.setCapability = PROCESS_CAPABILITY_NONE;
554                 app.resetCachedInfo();
555             }
556         }
557         for (int i = numProc - 1; i >= 0; i--) {
558             ProcessRecord app = activeProcesses.get(i);
559             if (!app.killedByAm && app.thread != null) {
560                 app.procStateChanged = false;
561                 computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
562                         computeClients); // It won't enter cycle if not computing clients.
563                 // if any app encountered a cycle, we need to perform an additional loop later
564                 retryCycles |= app.containsCycle;
565                 // Keep the completedAdjSeq to up to date.
566                 app.completedAdjSeq = mAdjSeq;
567             }
568         }
569 
570         assignCachedAdjIfNecessary(mProcessList.mLruProcesses);
571 
572         if (computeClients) { // There won't be cycles if we didn't compute clients above.
573             // Cycle strategy:
574             // - Retry computing any process that has encountered a cycle.
575             // - Continue retrying until no process was promoted.
576             // - Iterate from least important to most important.
577             int cycleCount = 0;
578             while (retryCycles && cycleCount < 10) {
579                 cycleCount++;
580                 retryCycles = false;
581 
582                 for (int i = 0; i < numProc; i++) {
583                     ProcessRecord app = activeProcesses.get(i);
584                     if (!app.killedByAm && app.thread != null && app.containsCycle) {
585                         app.adjSeq--;
586                         app.completedAdjSeq--;
587                     }
588                 }
589 
590                 for (int i = 0; i < numProc; i++) {
591                     ProcessRecord app = activeProcesses.get(i);
592                     if (!app.killedByAm && app.thread != null && app.containsCycle) {
593                         if (computeOomAdjLocked(app, app.getCurRawAdj(), topApp, true, now,
594                                 true, true)) {
595                             retryCycles = true;
596                         }
597                     }
598                 }
599             }
600         }
601 
602         mNumNonCachedProcs = 0;
603         mNumCachedHiddenProcs = 0;
604 
605         boolean allChanged = updateAndTrimProcessLocked(now, nowElapsed, oldTime, activeUids);
606         mNumServiceProcs = mNewNumServiceProcs;
607 
608         if (mService.mAlwaysFinishActivities) {
609             // Need to do this on its own message because the stack may not
610             // be in a consistent state at this point.
611             mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
612         }
613 
614         if (allChanged) {
615             mService.requestPssAllProcsLocked(now, false,
616                     mService.mProcessStats.isMemFactorLowered());
617         }
618 
619         updateUidsLocked(activeUids, nowElapsed);
620 
621         if (mService.mProcessStats.shouldWriteNowLocked(now)) {
622             mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
623                     mService.mProcessStats));
624         }
625 
626         // Run this after making sure all procstates are updated.
627         mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
628 
629         if (DEBUG_OOM_ADJ) {
630             final long duration = SystemClock.uptimeMillis() - now;
631             if (false) {
632                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
633                         new RuntimeException("here").fillInStackTrace());
634             } else {
635                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
636             }
637         }
638         if (startProfiling) {
639             mService.mOomAdjProfiler.oomAdjEnded();
640             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
641         }
642     }
643 
assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList)644     private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
645         final int numLru = lruList.size();
646 
647         // First update the OOM adjustment for each of the
648         // application processes based on their current state.
649         int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
650         int nextCachedAdj = curCachedAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
651         int curCachedImpAdj = 0;
652         int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
653         int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
654 
655         final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
656         final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
657                 - emptyProcessLimit;
658         // Let's determine how many processes we have running vs.
659         // how many slots we have for background processes; we may want
660         // to put multiple processes in a slot of there are enough of
661         // them.
662         int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
663         if (numEmptyProcs > cachedProcessLimit) {
664             // If there are more empty processes than our limit on cached
665             // processes, then use the cached process limit for the factor.
666             // This ensures that the really old empty processes get pushed
667             // down to the bottom, so if we are running low on memory we will
668             // have a better chance at keeping around more cached processes
669             // instead of a gazillion empty processes.
670             numEmptyProcs = cachedProcessLimit;
671         }
672         int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
673                 / mNumSlots;
674         if (cachedFactor < 1) cachedFactor = 1;
675 
676         int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
677         if (emptyFactor < 1) emptyFactor = 1;
678 
679         int stepCached = -1;
680         int stepEmpty = -1;
681         int lastCachedGroup = 0;
682         int lastCachedGroupImportance = 0;
683         int lastCachedGroupUid = 0;
684 
685         for (int i = numLru - 1; i >= 0; i--) {
686             ProcessRecord app = lruList.get(i);
687             // If we haven't yet assigned the final cached adj
688             // to the process, do that now.
689             if (!app.killedByAm && app.thread != null && app.curAdj
690                     >= ProcessList.UNKNOWN_ADJ) {
691                 switch (app.getCurProcState()) {
692                     case PROCESS_STATE_CACHED_ACTIVITY:
693                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
694                     case ActivityManager.PROCESS_STATE_CACHED_RECENT:
695                         // Figure out the next cached level, taking into account groups.
696                         boolean inGroup = false;
697                         if (app.connectionGroup != 0) {
698                             if (lastCachedGroupUid == app.uid
699                                     && lastCachedGroup == app.connectionGroup) {
700                                 // This is in the same group as the last process, just tweak
701                                 // adjustment by importance.
702                                 if (app.connectionImportance > lastCachedGroupImportance) {
703                                     lastCachedGroupImportance = app.connectionImportance;
704                                     if (curCachedAdj < nextCachedAdj
705                                             && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
706                                         curCachedImpAdj++;
707                                     }
708                                 }
709                                 inGroup = true;
710                             } else {
711                                 lastCachedGroupUid = app.uid;
712                                 lastCachedGroup = app.connectionGroup;
713                                 lastCachedGroupImportance = app.connectionImportance;
714                             }
715                         }
716                         if (!inGroup && curCachedAdj != nextCachedAdj) {
717                             stepCached++;
718                             curCachedImpAdj = 0;
719                             if (stepCached >= cachedFactor) {
720                                 stepCached = 0;
721                                 curCachedAdj = nextCachedAdj;
722                                 nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
723                                 if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
724                                     nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
725                                 }
726                             }
727                         }
728                         // This process is a cached process holding activities...
729                         // assign it the next cached value for that type, and then
730                         // step that cached level.
731                         app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
732                         app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
733                         if (DEBUG_LRU) {
734                             Slog.d(TAG_LRU, "Assigning activity LRU #" + i
735                                     + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
736                                     + " curCachedImpAdj=" + curCachedImpAdj + ")");
737                         }
738                         break;
739                     default:
740                         // Figure out the next cached level.
741                         if (curEmptyAdj != nextEmptyAdj) {
742                             stepEmpty++;
743                             if (stepEmpty >= emptyFactor) {
744                                 stepEmpty = 0;
745                                 curEmptyAdj = nextEmptyAdj;
746                                 nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
747                                 if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
748                                     nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
749                                 }
750                             }
751                         }
752                         // For everything else, assign next empty cached process
753                         // level and bump that up.  Note that this means that
754                         // long-running services that have dropped down to the
755                         // cached level will be treated as empty (since their process
756                         // state is still as a service), which is what we want.
757                         app.setCurRawAdj(curEmptyAdj);
758                         app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
759                         if (DEBUG_LRU) {
760                             Slog.d(TAG_LRU, "Assigning empty LRU #" + i
761                                     + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
762                                     + ")");
763                         }
764                         break;
765                 }
766             }
767         }
768     }
769 
updateAndTrimProcessLocked(final long now, final long nowElapsed, final long oldTime, final ActiveUids activeUids)770     private boolean updateAndTrimProcessLocked(final long now, final long nowElapsed,
771             final long oldTime, final ActiveUids activeUids) {
772         ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
773         final int numLru = lruList.size();
774 
775         final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
776         final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
777                 - emptyProcessLimit;
778         int lastCachedGroup = 0;
779         int lastCachedGroupUid = 0;
780         int numCached = 0;
781         int numCachedExtraGroup = 0;
782         int numEmpty = 0;
783         int numTrimming = 0;
784 
785         for (int i = numLru - 1; i >= 0; i--) {
786             ProcessRecord app = lruList.get(i);
787             if (!app.killedByAm && app.thread != null) {
788                 // We don't need to apply the update for the process which didn't get computed
789                 if (app.completedAdjSeq == mAdjSeq) {
790                     applyOomAdjLocked(app, true, now, nowElapsed);
791                 }
792 
793                 // Count the number of process types.
794                 switch (app.getCurProcState()) {
795                     case PROCESS_STATE_CACHED_ACTIVITY:
796                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
797                         mNumCachedHiddenProcs++;
798                         numCached++;
799                         if (app.connectionGroup != 0) {
800                             if (lastCachedGroupUid == app.info.uid
801                                     && lastCachedGroup == app.connectionGroup) {
802                                 // If this process is the next in the same group, we don't
803                                 // want it to count against our limit of the number of cached
804                                 // processes, so bump up the group count to account for it.
805                                 numCachedExtraGroup++;
806                             } else {
807                                 lastCachedGroupUid = app.info.uid;
808                                 lastCachedGroup = app.connectionGroup;
809                             }
810                         } else {
811                             lastCachedGroupUid = lastCachedGroup = 0;
812                         }
813                         if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
814                             app.kill("cached #" + numCached,
815                                     ApplicationExitInfo.REASON_OTHER,
816                                     ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
817                                     true);
818                         }
819                         break;
820                     case PROCESS_STATE_CACHED_EMPTY:
821                         if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
822                                 && app.lastActivityTime < oldTime) {
823                             app.kill("empty for "
824                                     + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
825                                     / 1000) + "s",
826                                     ApplicationExitInfo.REASON_OTHER,
827                                     ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
828                                     true);
829                         } else {
830                             numEmpty++;
831                             if (numEmpty > emptyProcessLimit) {
832                                 app.kill("empty #" + numEmpty,
833                                         ApplicationExitInfo.REASON_OTHER,
834                                         ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
835                                         true);
836                             }
837                         }
838                         break;
839                     default:
840                         mNumNonCachedProcs++;
841                         break;
842                 }
843 
844                 if (app.isolated && app.numberOfRunningServices() <= 0
845                         && app.isolatedEntryPoint == null) {
846                     // If this is an isolated process, there are no services
847                     // running in it, and it's not a special process with a
848                     // custom entry point, then the process is no longer
849                     // needed.  We agressively kill these because we can by
850                     // definition not re-use the same process again, and it is
851                     // good to avoid having whatever code was running in them
852                     // left sitting around after no longer needed.
853                     app.kill("isolated not needed", ApplicationExitInfo.REASON_OTHER,
854                             ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
855                 } else {
856                     // Keeping this process, update its uid.
857                     updateAppUidRecLocked(app);
858                 }
859 
860                 if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
861                         && !app.killedByAm) {
862                     numTrimming++;
863                 }
864             }
865         }
866 
867         mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);
868 
869         return mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
870     }
871 
updateAppUidRecLocked(ProcessRecord app)872     private void updateAppUidRecLocked(ProcessRecord app) {
873         final UidRecord uidRec = app.uidRecord;
874         if (uidRec != null) {
875             uidRec.ephemeral = app.info.isInstantApp();
876             if (uidRec.getCurProcState() > app.getCurProcState()) {
877                 uidRec.setCurProcState(app.getCurProcState());
878             }
879             if (app.hasForegroundServices()) {
880                 uidRec.foregroundServices = true;
881             }
882             uidRec.curCapability |= app.curCapability;
883         }
884     }
885 
updateUidsLocked(ActiveUids activeUids, final long nowElapsed)886     private void updateUidsLocked(ActiveUids activeUids, final long nowElapsed) {
887         ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
888         becameIdle.clear();
889 
890         // Update from any uid changes.
891         if (mLocalPowerManager != null) {
892             mLocalPowerManager.startUidChanges();
893         }
894         for (int i = activeUids.size() - 1; i >= 0; i--) {
895             final UidRecord uidRec = activeUids.valueAt(i);
896             int uidChange = UidRecord.CHANGE_PROCSTATE;
897             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
898                     && (uidRec.setProcState != uidRec.getCurProcState()
899                     || uidRec.setCapability != uidRec.curCapability
900                     || uidRec.setWhitelist != uidRec.curWhitelist)) {
901                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
902                         + ": proc state from " + uidRec.setProcState + " to "
903                         + uidRec.getCurProcState() + ", capability from "
904                         + uidRec.setCapability + " to " + uidRec.curCapability
905                         + ", whitelist from " + uidRec.setWhitelist
906                         + " to " + uidRec.curWhitelist);
907                 if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
908                         && !uidRec.curWhitelist) {
909                     // UID is now in the background (and not on the temp whitelist).  Was it
910                     // previously in the foreground (or on the temp whitelist)?
911                     if (!ActivityManager.isProcStateBackground(uidRec.setProcState)
912                             || uidRec.setWhitelist) {
913                         uidRec.lastBackgroundTime = nowElapsed;
914                         if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
915                             // Note: the background settle time is in elapsed realtime, while
916                             // the handler time base is uptime.  All this means is that we may
917                             // stop background uids later than we had intended, but that only
918                             // happens because the device was sleeping so we are okay anyway.
919                             mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
920                                     mConstants.BACKGROUND_SETTLE_TIME);
921                         }
922                     }
923                     if (uidRec.idle && !uidRec.setIdle) {
924                         uidChange = UidRecord.CHANGE_IDLE;
925                         becameIdle.add(uidRec);
926                     }
927                 } else {
928                     if (uidRec.idle) {
929                         uidChange = UidRecord.CHANGE_ACTIVE;
930                         EventLogTags.writeAmUidActive(uidRec.uid);
931                         uidRec.idle = false;
932                     }
933                     uidRec.lastBackgroundTime = 0;
934                 }
935                 final boolean wasCached = uidRec.setProcState
936                         > ActivityManager.PROCESS_STATE_RECEIVER;
937                 final boolean isCached = uidRec.getCurProcState()
938                         > ActivityManager.PROCESS_STATE_RECEIVER;
939                 if (wasCached != isCached || uidRec.setProcState == PROCESS_STATE_NONEXISTENT) {
940                     uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
941                 }
942                 uidRec.setProcState = uidRec.getCurProcState();
943                 uidRec.setCapability = uidRec.curCapability;
944                 uidRec.setWhitelist = uidRec.curWhitelist;
945                 uidRec.setIdle = uidRec.idle;
946                 mService.mAtmInternal.onUidProcStateChanged(uidRec.uid, uidRec.setProcState);
947                 mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
948                 mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(),
949                         uidRec.curCapability);
950                 if (uidRec.foregroundServices) {
951                     mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
952                 }
953             }
954             mService.mInternal.deletePendingTopUid(uidRec.uid);
955         }
956         if (mLocalPowerManager != null) {
957             mLocalPowerManager.finishUidChanges();
958         }
959 
960         int size = becameIdle.size();
961         if (size > 0) {
962             // If we have any new uids that became idle this time, we need to make sure
963             // they aren't left with running services.
964             for (int i = size - 1; i >= 0; i--) {
965                 mService.mServices.stopInBackgroundLocked(becameIdle.get(i).uid);
966             }
967         }
968     }
969 
970     private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
971             new ComputeOomAdjWindowCallback();
972 
973     /** These methods are called inline during computeOomAdjLocked(), on the same thread */
974     final class ComputeOomAdjWindowCallback
975             implements WindowProcessController.ComputeOomAdjCallback {
976 
977         ProcessRecord app;
978         int adj;
979         boolean foregroundActivities;
980         int procState;
981         int schedGroup;
982         int appUid;
983         int logUid;
984         int processStateCurTop;
985 
initialize(ProcessRecord app, int adj, boolean foregroundActivities, int procState, int schedGroup, int appUid, int logUid, int processStateCurTop)986         void initialize(ProcessRecord app, int adj, boolean foregroundActivities,
987                 int procState, int schedGroup, int appUid, int logUid, int processStateCurTop) {
988             this.app = app;
989             this.adj = adj;
990             this.foregroundActivities = foregroundActivities;
991             this.procState = procState;
992             this.schedGroup = schedGroup;
993             this.appUid = appUid;
994             this.logUid = logUid;
995             this.processStateCurTop = processStateCurTop;
996         }
997 
998         @Override
onVisibleActivity()999         public void onVisibleActivity() {
1000             // App has a visible activity; only upgrade adjustment.
1001             if (adj > ProcessList.VISIBLE_APP_ADJ) {
1002                 adj = ProcessList.VISIBLE_APP_ADJ;
1003                 app.adjType = "vis-activity";
1004                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1005                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app);
1006                 }
1007             }
1008             if (procState > processStateCurTop) {
1009                 procState = processStateCurTop;
1010                 app.adjType = "vis-activity";
1011                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1012                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1013                             "Raise procstate to vis-activity (top): " + app);
1014                 }
1015             }
1016             if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
1017                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1018             }
1019             app.setCached(false);
1020             app.empty = false;
1021             foregroundActivities = true;
1022         }
1023 
1024         @Override
onPausedActivity()1025         public void onPausedActivity() {
1026             if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1027                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1028                 app.adjType = "pause-activity";
1029                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1030                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: "  + app);
1031                 }
1032             }
1033             if (procState > processStateCurTop) {
1034                 procState = processStateCurTop;
1035                 app.adjType = "pause-activity";
1036                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1037                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1038                             "Raise procstate to pause-activity (top): "  + app);
1039                 }
1040             }
1041             if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
1042                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1043             }
1044             app.setCached(false);
1045             app.empty = false;
1046             foregroundActivities = true;
1047         }
1048 
1049         @Override
onStoppingActivity(boolean finishing)1050         public void onStoppingActivity(boolean finishing) {
1051             if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1052                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1053                 app.adjType = "stop-activity";
1054                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1055                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1056                             "Raise adj to stop-activity: "  + app);
1057                 }
1058             }
1059 
1060             // For the process state, we will at this point consider the process to be cached. It
1061             // will be cached either as an activity or empty depending on whether the activity is
1062             // finishing. We do this so that we can treat the process as cached for purposes of
1063             // memory trimming (determining current memory level, trim command to send to process)
1064             // since there can be an arbitrary number of stopping processes and they should soon all
1065             // go into the cached state.
1066             if (!finishing) {
1067                 if (procState > PROCESS_STATE_LAST_ACTIVITY) {
1068                     procState = PROCESS_STATE_LAST_ACTIVITY;
1069                     app.adjType = "stop-activity";
1070                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1071                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
1072                                 "Raise procstate to stop-activity: " + app);
1073                     }
1074                 }
1075             }
1076             app.setCached(false);
1077             app.empty = false;
1078             foregroundActivities = true;
1079         }
1080 
1081         @Override
onOtherActivity()1082         public void onOtherActivity() {
1083             if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
1084                 procState = PROCESS_STATE_CACHED_ACTIVITY;
1085                 app.adjType = "cch-act";
1086                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1087                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1088                             "Raise procstate to cached activity: " + app);
1089                 }
1090             }
1091         }
1092     }
1093 
computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval, boolean computeClients)1094     private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
1095             ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
1096             boolean computeClients) {
1097         if (mAdjSeq == app.adjSeq) {
1098             if (app.adjSeq == app.completedAdjSeq) {
1099                 // This adjustment has already been computed successfully.
1100                 return false;
1101             } else {
1102                 // The process is being computed, so there is a cycle. We cannot
1103                 // rely on this process's state.
1104                 app.containsCycle = true;
1105 
1106                 return false;
1107             }
1108         }
1109 
1110         if (app.thread == null) {
1111             app.adjSeq = mAdjSeq;
1112             app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
1113             app.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
1114             app.curAdj = ProcessList.CACHED_APP_MAX_ADJ;
1115             app.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
1116             app.completedAdjSeq = app.adjSeq;
1117             app.curCapability = PROCESS_CAPABILITY_NONE;
1118             return false;
1119         }
1120 
1121         app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
1122         app.adjSource = null;
1123         app.adjTarget = null;
1124         app.empty = false;
1125         app.setCached(false);
1126         app.shouldNotFreeze = false;
1127 
1128         final int appUid = app.info.uid;
1129         final int logUid = mService.mCurOomAdjUid;
1130 
1131         int prevAppAdj = app.curAdj;
1132         int prevProcState = app.getCurProcState();
1133         int prevCapability = app.curCapability;
1134 
1135         if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
1136             // The max adjustment doesn't allow this app to be anything
1137             // below foreground, so it is not worth doing work for it.
1138             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1139                 mService.reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app);
1140             }
1141             app.adjType = "fixed";
1142             app.adjSeq = mAdjSeq;
1143             app.setCurRawAdj(app.maxAdj);
1144             app.setHasForegroundActivities(false);
1145             app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
1146             app.curCapability = PROCESS_CAPABILITY_ALL;
1147             app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
1148             // System processes can do UI, and when they do we want to have
1149             // them trim their memory after the user leaves the UI.  To
1150             // facilitate this, here we need to determine whether or not it
1151             // is currently showing UI.
1152             app.systemNoUi = true;
1153             if (app == topApp) {
1154                 app.systemNoUi = false;
1155                 app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
1156                 app.adjType = "pers-top-activity";
1157             } else if (app.hasTopUi()) {
1158                 // sched group/proc state adjustment is below
1159                 app.systemNoUi = false;
1160                 app.adjType = "pers-top-ui";
1161             } else if (app.getCachedHasVisibleActivities()) {
1162                 app.systemNoUi = false;
1163             }
1164             if (!app.systemNoUi) {
1165                 if (mService.mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) {
1166                     // screen on, promote UI
1167                     app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
1168                     app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
1169                 } else {
1170                     // screen off, restrict UI scheduling
1171                     app.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
1172                     app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
1173                 }
1174             }
1175             app.setCurRawProcState(app.getCurProcState());
1176             app.curAdj = app.maxAdj;
1177             app.completedAdjSeq = app.adjSeq;
1178             // if curAdj is less than prevAppAdj, then this process was promoted
1179             return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
1180         }
1181 
1182         app.systemNoUi = false;
1183 
1184         final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState();
1185 
1186         // Determine the importance of the process, starting with most
1187         // important to least, and assign an appropriate OOM adjustment.
1188         int adj;
1189         int schedGroup;
1190         int procState;
1191         int cachedAdjSeq;
1192         int capability = 0;
1193 
1194         boolean foregroundActivities = false;
1195         if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
1196             // The last app on the list is the foreground app.
1197             adj = ProcessList.FOREGROUND_APP_ADJ;
1198             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
1199             app.adjType = "top-activity";
1200             foregroundActivities = true;
1201             procState = PROCESS_STATE_CUR_TOP;
1202             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1203                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
1204             }
1205         } else if (app.runningRemoteAnimation) {
1206             adj = ProcessList.VISIBLE_APP_ADJ;
1207             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
1208             app.adjType = "running-remote-anim";
1209             procState = PROCESS_STATE_CUR_TOP;
1210             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1211                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
1212             }
1213         } else if (app.getActiveInstrumentation() != null) {
1214             // Don't want to kill running instrumentation.
1215             adj = ProcessList.FOREGROUND_APP_ADJ;
1216             schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1217             app.adjType = "instrumentation";
1218             procState = PROCESS_STATE_FOREGROUND_SERVICE;
1219             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1220                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
1221             }
1222         } else if (app.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
1223             // An app that is currently receiving a broadcast also
1224             // counts as being in the foreground for OOM killer purposes.
1225             // It's placed in a sched group based on the nature of the
1226             // broadcast as reflected by which queue it's active in.
1227             adj = ProcessList.FOREGROUND_APP_ADJ;
1228             schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue))
1229                     ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
1230             app.adjType = "broadcast";
1231             procState = ActivityManager.PROCESS_STATE_RECEIVER;
1232             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1233                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
1234             }
1235         } else if (app.executingServices.size() > 0) {
1236             // An app that is currently executing a service callback also
1237             // counts as being in the foreground.
1238             adj = ProcessList.FOREGROUND_APP_ADJ;
1239             schedGroup = app.execServicesFg ?
1240                     ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
1241             app.adjType = "exec-service";
1242             procState = PROCESS_STATE_SERVICE;
1243             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1244                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
1245             }
1246             //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
1247         } else if (app == topApp) {
1248             adj = ProcessList.FOREGROUND_APP_ADJ;
1249             schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1250             app.adjType = "top-sleeping";
1251             foregroundActivities = true;
1252             procState = PROCESS_STATE_CUR_TOP;
1253             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1254                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app);
1255             }
1256         } else {
1257             // As far as we know the process is empty.  We may change our mind later.
1258             schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1259             // At this point we don't actually know the adjustment.  Use the cached adj
1260             // value that the caller wants us to.
1261             adj = cachedAdj;
1262             procState = PROCESS_STATE_CACHED_EMPTY;
1263             if (!app.containsCycle) {
1264                 app.setCached(true);
1265                 app.empty = true;
1266                 app.adjType = "cch-empty";
1267             }
1268             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1269                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
1270             }
1271         }
1272 
1273         // Examine all activities if not already foreground.
1274         if (!foregroundActivities && app.getCachedHasActivities()) {
1275             app.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
1276                     adj, foregroundActivities, procState, schedGroup, appUid, logUid,
1277                     PROCESS_STATE_CUR_TOP);
1278 
1279             adj = app.mCachedAdj;
1280             foregroundActivities = app.mCachedForegroundActivities;
1281             procState = app.mCachedProcState;
1282             schedGroup = app.mCachedSchedGroup;
1283         }
1284 
1285         if (procState > PROCESS_STATE_CACHED_RECENT && app.getCachedHasRecentTasks()) {
1286             procState = PROCESS_STATE_CACHED_RECENT;
1287             app.adjType = "cch-rec";
1288             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1289                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
1290             }
1291         }
1292 
1293         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
1294                 || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
1295             if (app.hasForegroundServices()) {
1296                 // The user is aware of this app, so make it visible.
1297                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1298                 procState = PROCESS_STATE_FOREGROUND_SERVICE;
1299                 app.adjType = "fg-service";
1300                 app.setCached(false);
1301                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1302                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1303                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + app.adjType + ": "
1304                             + app + " ");
1305                 }
1306             } else if (app.hasOverlayUi()) {
1307                 // The process is display an overlay UI.
1308                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1309                 procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
1310                 app.setCached(false);
1311                 app.adjType = "has-overlay-ui";
1312                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1313                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1314                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app);
1315                 }
1316             }
1317         }
1318 
1319         // If the app was recently in the foreground and moved to a foreground service status,
1320         // allow it to get a higher rank in memory for some time, compared to other foreground
1321         // services so that it can finish performing any persistence/processing of in-memory state.
1322         if (app.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
1323                 && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
1324                 || app.setProcState <= PROCESS_STATE_TOP)) {
1325             adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
1326             app.adjType = "fg-service-act";
1327             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1328                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
1329             }
1330         }
1331 
1332         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
1333                 || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
1334             if (app.forcingToImportant != null) {
1335                 // This is currently used for toasts...  they are not interactive, and
1336                 // we don't want them to cause the app to become fully foreground (and
1337                 // thus out of background check), so we yes the best background level we can.
1338                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1339                 procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
1340                 app.setCached(false);
1341                 app.adjType = "force-imp";
1342                 app.adjSource = app.forcingToImportant;
1343                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1344                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1345                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
1346                 }
1347             }
1348         }
1349 
1350         if (app.getCachedIsHeavyWeight()) {
1351             if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
1352                 // We don't want to kill the current heavy-weight process.
1353                 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
1354                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1355                 app.setCached(false);
1356                 app.adjType = "heavy";
1357                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1358                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
1359                 }
1360             }
1361             if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
1362                 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
1363                 app.adjType = "heavy";
1364                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1365                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
1366                 }
1367             }
1368         }
1369 
1370         if (app.getCachedIsHomeProcess()) {
1371             if (adj > ProcessList.HOME_APP_ADJ) {
1372                 // This process is hosting what we currently consider to be the
1373                 // home app, so we don't want to let it go into the background.
1374                 adj = ProcessList.HOME_APP_ADJ;
1375                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1376                 app.setCached(false);
1377                 app.adjType = "home";
1378                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1379                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
1380                 }
1381             }
1382             if (procState > ActivityManager.PROCESS_STATE_HOME) {
1383                 procState = ActivityManager.PROCESS_STATE_HOME;
1384                 app.adjType = "home";
1385                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1386                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
1387                 }
1388             }
1389         }
1390 
1391         if (app.getCachedIsPreviousProcess() && app.getCachedHasActivities()) {
1392             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
1393                 // This was the previous process that showed UI to the user.
1394                 // We want to try to keep it around more aggressively, to give
1395                 // a good experience around switching between two apps.
1396                 adj = ProcessList.PREVIOUS_APP_ADJ;
1397                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1398                 app.setCached(false);
1399                 app.adjType = "previous";
1400                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1401                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
1402                 }
1403             }
1404             if (procState > PROCESS_STATE_LAST_ACTIVITY) {
1405                 procState = PROCESS_STATE_LAST_ACTIVITY;
1406                 app.adjType = "previous";
1407                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1408                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
1409                 }
1410             }
1411         }
1412 
1413         if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
1414                 + " reason=" + app.adjType);
1415 
1416         // By default, we use the computed adjustment.  It may be changed if
1417         // there are applications dependent on our services or providers, but
1418         // this gives us a baseline and makes sure we don't get into an
1419         // infinite recursion. If we're re-evaluating due to cycles, use the previously computed
1420         // values.
1421         if (cycleReEval) {
1422             procState = Math.min(procState, app.getCurRawProcState());
1423             adj = Math.min(adj, app.getCurRawAdj());
1424             schedGroup = Math.max(schedGroup, app.getCurrentSchedulingGroup());
1425         }
1426         app.setCurRawAdj(adj);
1427         app.setCurRawProcState(procState);
1428 
1429         app.hasStartedServices = false;
1430         app.adjSeq = mAdjSeq;
1431 
1432         final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
1433         if (backupTarget != null && app == backupTarget.app) {
1434             // If possible we want to avoid killing apps while they're being backed up
1435             if (adj > ProcessList.BACKUP_APP_ADJ) {
1436                 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
1437                 adj = ProcessList.BACKUP_APP_ADJ;
1438                 if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
1439                     procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
1440                 }
1441                 app.adjType = "backup";
1442                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1443                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
1444                 }
1445                 app.setCached(false);
1446             }
1447             if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
1448                 procState = ActivityManager.PROCESS_STATE_BACKUP;
1449                 app.adjType = "backup";
1450                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1451                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
1452                 }
1453             }
1454         }
1455 
1456         int capabilityFromFGS = 0; // capability from foreground service.
1457         for (int is = app.numberOfRunningServices() - 1;
1458                 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
1459                         || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1460                         || procState > PROCESS_STATE_TOP);
1461                 is--) {
1462             ServiceRecord s = app.getRunningServiceAt(is);
1463             if (s.startRequested) {
1464                 app.hasStartedServices = true;
1465                 if (procState > PROCESS_STATE_SERVICE) {
1466                     procState = PROCESS_STATE_SERVICE;
1467                     app.adjType = "started-services";
1468                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1469                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
1470                                 "Raise procstate to started service: " + app);
1471                     }
1472                 }
1473                 if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
1474                     // If this process has shown some UI, let it immediately
1475                     // go to the LRU list because it may be pretty heavy with
1476                     // UI stuff.  We'll tag it with a label just to help
1477                     // debug and understand what is going on.
1478                     if (adj > ProcessList.SERVICE_ADJ) {
1479                         app.adjType = "cch-started-ui-services";
1480                     }
1481                 } else {
1482                     if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
1483                         // This service has seen some activity within
1484                         // recent memory, so we will keep its process ahead
1485                         // of the background processes.
1486                         if (adj > ProcessList.SERVICE_ADJ) {
1487                             adj = ProcessList.SERVICE_ADJ;
1488                             app.adjType = "started-services";
1489                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1490                                 reportOomAdjMessageLocked(TAG_OOM_ADJ,
1491                                         "Raise adj to started service: " + app);
1492                             }
1493                             app.setCached(false);
1494                         }
1495                     }
1496                     // If we have let the service slide into the background
1497                     // state, still have some text describing what it is doing
1498                     // even though the service no longer has an impact.
1499                     if (adj > ProcessList.SERVICE_ADJ) {
1500                         app.adjType = "cch-started-services";
1501                     }
1502                 }
1503             }
1504 
1505             if (s.isForeground) {
1506                 final int fgsType = s.foregroundServiceType;
1507                 if (s.mAllowWhileInUsePermissionInFgs) {
1508                     capabilityFromFGS |=
1509                             (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
1510                                     != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
1511 
1512                     boolean enabled = false;
1513                     try {
1514                         enabled = mPlatformCompat.isChangeEnabled(
1515                                 CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID, s.appInfo);
1516                     } catch (RemoteException e) {
1517                     }
1518                     if (enabled) {
1519                         capabilityFromFGS |=
1520                                 (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
1521                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
1522                         capabilityFromFGS |=
1523                                 (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
1524                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
1525                     } else {
1526                         capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
1527                                 | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
1528                     }
1529                 }
1530             }
1531 
1532             ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
1533             for (int conni = serviceConnections.size() - 1;
1534                     conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
1535                             || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1536                             || procState > PROCESS_STATE_TOP);
1537                     conni--) {
1538                 ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
1539                 for (int i = 0;
1540                         i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
1541                                 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1542                                 || procState > PROCESS_STATE_TOP);
1543                         i++) {
1544                     // XXX should compute this based on the max of
1545                     // all connected clients.
1546                     ConnectionRecord cr = clist.get(i);
1547                     if (cr.binding.client == app) {
1548                         // Binding to oneself is not interesting.
1549                         continue;
1550                     }
1551 
1552                     boolean trackedProcState = false;
1553 
1554                     ProcessRecord client = cr.binding.client;
1555                     if (computeClients) {
1556                         computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now,
1557                                 cycleReEval, true);
1558                     } else {
1559                         client.setCurRawAdj(client.setAdj);
1560                         client.setCurRawProcState(client.setProcState);
1561                     }
1562 
1563                     int clientAdj = client.getCurRawAdj();
1564                     int clientProcState = client.getCurRawProcState();
1565 
1566                     if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
1567                         if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
1568                             continue;
1569                         }
1570 
1571                         if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
1572                             capability |= client.curCapability;
1573                         }
1574 
1575                         if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
1576                             // If the other app is cached for any reason, for purposes here
1577                             // we are going to consider it empty.  The specific cached state
1578                             // doesn't propagate except under certain conditions.
1579                             clientProcState = PROCESS_STATE_CACHED_EMPTY;
1580                         }
1581                         String adjType = null;
1582                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
1583                             // Not doing bind OOM management, so treat
1584                             // this guy more like a started service.
1585                             if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
1586                                 // If this process has shown some UI, let it immediately
1587                                 // go to the LRU list because it may be pretty heavy with
1588                                 // UI stuff.  We'll tag it with a label just to help
1589                                 // debug and understand what is going on.
1590                                 if (adj > clientAdj) {
1591                                     adjType = "cch-bound-ui-services";
1592                                 }
1593                                 app.setCached(false);
1594                                 clientAdj = adj;
1595                                 clientProcState = procState;
1596                             } else {
1597                                 if (now >= (s.lastActivity
1598                                         + mConstants.MAX_SERVICE_INACTIVITY)) {
1599                                     // This service has not seen activity within
1600                                     // recent memory, so allow it to drop to the
1601                                     // LRU list if there is no other reason to keep
1602                                     // it around.  We'll also tag it with a label just
1603                                     // to help debug and undertand what is going on.
1604                                     if (adj > clientAdj) {
1605                                         adjType = "cch-bound-services";
1606                                     }
1607                                     clientAdj = adj;
1608                                 }
1609                             }
1610                         }
1611                         if (adj > clientAdj) {
1612                             // If this process has recently shown UI, and
1613                             // the process that is binding to it is less
1614                             // important than being visible, then we don't
1615                             // care about the binding as much as we care
1616                             // about letting this process get into the LRU
1617                             // list to be killed and restarted if needed for
1618                             // memory.
1619                             if (app.hasShownUi && !app.getCachedIsHomeProcess()
1620                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1621                                 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
1622                                     adjType = "cch-bound-ui-services";
1623                                 }
1624                             } else {
1625                                 int newAdj;
1626                                 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
1627                                         |Context.BIND_IMPORTANT)) != 0) {
1628                                     if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
1629                                         newAdj = clientAdj;
1630                                     } else {
1631                                         // make this service persistent
1632                                         newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
1633                                         schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1634                                         procState = ActivityManager.PROCESS_STATE_PERSISTENT;
1635                                         cr.trackProcState(procState, mAdjSeq, now);
1636                                         trackedProcState = true;
1637                                     }
1638                                 } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0
1639                                         && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
1640                                         && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
1641                                     newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
1642                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
1643                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
1644                                         && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
1645                                     newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
1646                                 } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
1647                                     newAdj = clientAdj;
1648                                 } else {
1649                                     if (adj > ProcessList.VISIBLE_APP_ADJ) {
1650                                         // TODO: Is this too limiting for apps bound from TOP?
1651                                         newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
1652                                     } else {
1653                                         newAdj = adj;
1654                                     }
1655                                 }
1656                                 if (!client.isCached()) {
1657                                     app.setCached(false);
1658                                 }
1659                                 if (adj >  newAdj) {
1660                                     adj = newAdj;
1661                                     app.setCurRawAdj(adj);
1662                                     adjType = "service";
1663                                 }
1664                             }
1665                         }
1666                         if ((cr.flags & (Context.BIND_NOT_FOREGROUND
1667                                 | Context.BIND_IMPORTANT_BACKGROUND)) == 0) {
1668                             // This will treat important bound services identically to
1669                             // the top app, which may behave differently than generic
1670                             // foreground work.
1671                             final int curSchedGroup = client.getCurrentSchedulingGroup();
1672                             if (curSchedGroup > schedGroup) {
1673                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
1674                                     schedGroup = curSchedGroup;
1675                                 } else {
1676                                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1677                                 }
1678                             }
1679                             if (clientProcState < PROCESS_STATE_TOP) {
1680                                 // Special handling for above-top states (persistent
1681                                 // processes).  These should not bring the current process
1682                                 // into the top state, since they are not on top.  Instead
1683                                 // give them the best bound state after that.
1684                                 if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
1685                                     clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;                                                                                                                       ;
1686                                 } else if (mService.mWakefulness
1687                                         == PowerManagerInternal.WAKEFULNESS_AWAKE
1688                                         && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
1689                                                 != 0) {
1690                                     clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
1691                                 } else {
1692                                     clientProcState =
1693                                             PROCESS_STATE_IMPORTANT_FOREGROUND;
1694                                 }
1695                             } else if (clientProcState == PROCESS_STATE_TOP) {
1696                                 // Go at most to BOUND_TOP, unless requested to elevate
1697                                 // to client's state.
1698                                 clientProcState = PROCESS_STATE_BOUND_TOP;
1699                                 boolean enabled = false;
1700                                 try {
1701                                     enabled = mPlatformCompat.isChangeEnabled(
1702                                             PROCESS_CAPABILITY_CHANGE_ID, client.info);
1703                                 } catch (RemoteException e) {
1704                                 }
1705                                 if (enabled) {
1706                                     if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
1707                                         // TOP process passes all capabilities to the service.
1708                                         capability |= PROCESS_CAPABILITY_ALL;
1709                                     } else {
1710                                         // TOP process passes no capability to the service.
1711                                     }
1712                                 } else {
1713                                     // TOP process passes all capabilities to the service.
1714                                     capability |= PROCESS_CAPABILITY_ALL;
1715                                 }
1716                             }
1717                         } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
1718                             if (clientProcState <
1719                                     PROCESS_STATE_TRANSIENT_BACKGROUND) {
1720                                 clientProcState =
1721                                         PROCESS_STATE_TRANSIENT_BACKGROUND;
1722                             }
1723                         } else {
1724                             if (clientProcState <
1725                                     PROCESS_STATE_IMPORTANT_BACKGROUND) {
1726                                 clientProcState =
1727                                         PROCESS_STATE_IMPORTANT_BACKGROUND;
1728                             }
1729                         }
1730 
1731                         if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP
1732                                 && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) {
1733                             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
1734                         }
1735 
1736                         if (!trackedProcState) {
1737                             cr.trackProcState(clientProcState, mAdjSeq, now);
1738                         }
1739 
1740                         if (procState > clientProcState) {
1741                             procState = clientProcState;
1742                             app.setCurRawProcState(procState);
1743                             if (adjType == null) {
1744                                 adjType = "service";
1745                             }
1746                         }
1747                         if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND
1748                                 && (cr.flags & Context.BIND_SHOWING_UI) != 0) {
1749                             app.setPendingUiClean(true);
1750                         }
1751                         if (adjType != null) {
1752                             app.adjType = adjType;
1753                             app.adjTypeCode = ActivityManager.RunningAppProcessInfo
1754                                     .REASON_SERVICE_IN_USE;
1755                             app.adjSource = cr.binding.client;
1756                             app.adjSourceProcState = clientProcState;
1757                             app.adjTarget = s.instanceName;
1758                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1759                                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
1760                                         + ": " + app + ", due to " + cr.binding.client
1761                                         + " adj=" + adj + " procState="
1762                                         + ProcessList.makeProcStateString(procState));
1763                             }
1764                         }
1765                     } else { // BIND_WAIVE_PRIORITY == true
1766                         // BIND_WAIVE_PRIORITY bindings are special when it comes to the
1767                         // freezer. Processes bound via WPRI are expected to be running,
1768                         // but they are not promoted in the LRU list to keep them out of
1769                         // cached. As a result, they can freeze based on oom_adj alone.
1770                         // Normally, bindToDeath would fire when a cached app would die
1771                         // in the background, but nothing will fire when a running process
1772                         // pings a frozen process. Accordingly, any cached app that is
1773                         // bound by an unfrozen app via a WPRI binding has to remain
1774                         // unfrozen.
1775                         if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
1776                             app.shouldNotFreeze = true;
1777                         }
1778                     }
1779                     if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
1780                         app.treatLikeActivity = true;
1781                     }
1782                     final ActivityServiceConnectionsHolder a = cr.activity;
1783                     if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
1784                         if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ
1785                                 && a.isActivityVisible()) {
1786                             adj = ProcessList.FOREGROUND_APP_ADJ;
1787                             app.setCurRawAdj(adj);
1788                             if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
1789                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
1790                                     schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
1791                                 } else {
1792                                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1793                                 }
1794                             }
1795                             app.setCached(false);
1796                             app.adjType = "service";
1797                             app.adjTypeCode = ActivityManager.RunningAppProcessInfo
1798                                     .REASON_SERVICE_IN_USE;
1799                             app.adjSource = a;
1800                             app.adjSourceProcState = procState;
1801                             app.adjTarget = s.instanceName;
1802                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1803                                 reportOomAdjMessageLocked(TAG_OOM_ADJ,
1804                                         "Raise to service w/activity: " + app);
1805                             }
1806                         }
1807                     }
1808                 }
1809             }
1810         }
1811 
1812         for (int provi = app.pubProviders.size() - 1;
1813                 provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
1814                         || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1815                         || procState > PROCESS_STATE_TOP);
1816                 provi--) {
1817             ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
1818             for (int i = cpr.connections.size() - 1;
1819                     i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
1820                             || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
1821                             || procState > PROCESS_STATE_TOP);
1822                     i--) {
1823                 ContentProviderConnection conn = cpr.connections.get(i);
1824                 ProcessRecord client = conn.client;
1825                 if (client == app) {
1826                     // Being our own client is not interesting.
1827                     continue;
1828                 }
1829                 if (computeClients) {
1830                     computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now, cycleReEval,
1831                             true);
1832                 } else {
1833                     client.setCurRawAdj(client.setAdj);
1834                     client.setCurRawProcState(client.setProcState);
1835                 }
1836 
1837                 if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
1838                     continue;
1839                 }
1840 
1841                 int clientAdj = client.getCurRawAdj();
1842                 int clientProcState = client.getCurRawProcState();
1843 
1844                 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
1845                     // If the other app is cached for any reason, for purposes here
1846                     // we are going to consider it empty.
1847                     clientProcState = PROCESS_STATE_CACHED_EMPTY;
1848                 }
1849                 String adjType = null;
1850                 if (adj > clientAdj) {
1851                     if (app.hasShownUi && !app.getCachedIsHomeProcess()
1852                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1853                         adjType = "cch-ui-provider";
1854                     } else {
1855                         adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
1856                                 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
1857                         app.setCurRawAdj(adj);
1858                         adjType = "provider";
1859                     }
1860                     app.setCached(app.isCached() & client.isCached());
1861                 }
1862 
1863                 if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
1864                     if (adjType == null) {
1865                         adjType = "provider";
1866                     }
1867                     if (clientProcState == PROCESS_STATE_TOP) {
1868                         clientProcState = PROCESS_STATE_BOUND_TOP;
1869                     } else {
1870                         clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
1871                     }
1872                 }
1873 
1874                 conn.trackProcState(clientProcState, mAdjSeq, now);
1875                 if (procState > clientProcState) {
1876                     procState = clientProcState;
1877                     app.setCurRawProcState(procState);
1878                 }
1879                 if (client.getCurrentSchedulingGroup() > schedGroup) {
1880                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1881                 }
1882                 if (adjType != null) {
1883                     app.adjType = adjType;
1884                     app.adjTypeCode = ActivityManager.RunningAppProcessInfo
1885                             .REASON_PROVIDER_IN_USE;
1886                     app.adjSource = client;
1887                     app.adjSourceProcState = clientProcState;
1888                     app.adjTarget = cpr.name;
1889                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1890                         reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
1891                                 + ": " + app + ", due to " + client
1892                                 + " adj=" + adj + " procState="
1893                                 + ProcessList.makeProcStateString(procState));
1894                     }
1895                 }
1896             }
1897             // If the provider has external (non-framework) process
1898             // dependencies, ensure that its adjustment is at least
1899             // FOREGROUND_APP_ADJ.
1900             if (cpr.hasExternalProcessHandles()) {
1901                 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
1902                     adj = ProcessList.FOREGROUND_APP_ADJ;
1903                     app.setCurRawAdj(adj);
1904                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1905                     app.setCached(false);
1906                     app.adjType = "ext-provider";
1907                     app.adjTarget = cpr.name;
1908                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1909                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
1910                                 "Raise adj to external provider: " + app);
1911                     }
1912                 }
1913                 if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
1914                     procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
1915                     app.setCurRawProcState(procState);
1916                     if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1917                         reportOomAdjMessageLocked(TAG_OOM_ADJ,
1918                                 "Raise procstate to external provider: " + app);
1919                     }
1920                 }
1921             }
1922         }
1923 
1924         if (app.lastProviderTime > 0 &&
1925                 (app.lastProviderTime + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
1926             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
1927                 adj = ProcessList.PREVIOUS_APP_ADJ;
1928                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
1929                 app.setCached(false);
1930                 app.adjType = "recent-provider";
1931                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1932                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1933                             "Raise adj to recent provider: " + app);
1934                 }
1935             }
1936             if (procState > PROCESS_STATE_LAST_ACTIVITY) {
1937                 procState = PROCESS_STATE_LAST_ACTIVITY;
1938                 app.adjType = "recent-provider";
1939                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
1940                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
1941                             "Raise procstate to recent provider: " + app);
1942                 }
1943             }
1944         }
1945 
1946         if (procState >= PROCESS_STATE_CACHED_EMPTY) {
1947             if (app.hasClientActivities()) {
1948                 // This is a cached process, but with client activities.  Mark it so.
1949                 procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
1950                 app.adjType = "cch-client-act";
1951             } else if (app.treatLikeActivity) {
1952                 // This is a cached process, but somebody wants us to treat it like it has
1953                 // an activity, okay!
1954                 procState = PROCESS_STATE_CACHED_ACTIVITY;
1955                 app.adjType = "cch-as-act";
1956             }
1957         }
1958 
1959         if (adj == ProcessList.SERVICE_ADJ) {
1960             if (doingAll && !cycleReEval) {
1961                 app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
1962                 mNewNumServiceProcs++;
1963                 //Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
1964                 if (!app.serviceb) {
1965                     // This service isn't far enough down on the LRU list to
1966                     // normally be a B service, but if we are low on RAM and it
1967                     // is large we want to force it down since we would prefer to
1968                     // keep launcher over it.
1969                     if (mService.mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
1970                             && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
1971                         app.serviceHighRam = true;
1972                         app.serviceb = true;
1973                         //Slog.i(TAG, "ADJ " + app + " high ram!");
1974                     } else {
1975                         mNewNumAServiceProcs++;
1976                         //Slog.i(TAG, "ADJ " + app + " not high ram!");
1977                     }
1978                 } else {
1979                     app.serviceHighRam = false;
1980                 }
1981             }
1982             if (app.serviceb) {
1983                 adj = ProcessList.SERVICE_B_ADJ;
1984             }
1985         }
1986 
1987         app.setCurRawAdj(adj);
1988 
1989         //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
1990         //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
1991         if (adj > app.maxAdj) {
1992             adj = app.maxAdj;
1993             if (app.maxAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
1994                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
1995             }
1996         }
1997 
1998         // Put bound foreground services in a special sched group for additional
1999         // restrictions on screen off
2000         if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
2001                 && mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) {
2002             if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) {
2003                 schedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
2004             }
2005         }
2006 
2007         // apply capability from FGS.
2008         if (app.hasForegroundServices()) {
2009             capability |= capabilityFromFGS;
2010         }
2011 
2012         capability |= getDefaultCapability(app, procState);
2013 
2014         // Do final modification to adj.  Everything we do between here and applying
2015         // the final setAdj must be done in this function, because we will also use
2016         // it when computing the final cached adj later.  Note that we don't need to
2017         // worry about this for max adj above, since max adj will always be used to
2018         // keep it out of the cached vaues.
2019         app.curAdj = app.modifyRawOomAdj(adj);
2020         app.curCapability = capability;
2021         app.setCurrentSchedulingGroup(schedGroup);
2022         app.setCurProcState(procState);
2023         app.setCurRawProcState(procState);
2024         app.setHasForegroundActivities(foregroundActivities);
2025         app.completedAdjSeq = mAdjSeq;
2026 
2027         // if curAdj or curProcState improved, then this process was promoted
2028         return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState
2029                 || app.curCapability != prevCapability ;
2030     }
2031 
getDefaultCapability(ProcessRecord app, int procState)2032     private int getDefaultCapability(ProcessRecord app, int procState) {
2033         switch (procState) {
2034             case PROCESS_STATE_PERSISTENT:
2035             case PROCESS_STATE_PERSISTENT_UI:
2036             case PROCESS_STATE_TOP:
2037                 return PROCESS_CAPABILITY_ALL;
2038             case PROCESS_STATE_BOUND_TOP:
2039                 return PROCESS_CAPABILITY_NONE;
2040             case PROCESS_STATE_FOREGROUND_SERVICE:
2041                 if (app.hasForegroundServices()) {
2042                     // Capability from FGS are conditional depending on foreground service type in
2043                     // manifest file and the mAllowWhileInUsePermissionInFgs flag.
2044                     return PROCESS_CAPABILITY_NONE;
2045                 } else {
2046                     // process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client.
2047                     // the implicit capability could be removed in the future, client should use
2048                     // BIND_INCLUDE_CAPABILITY flag.
2049                     return PROCESS_CAPABILITY_ALL_IMPLICIT;
2050                 }
2051             case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
2052                 return PROCESS_CAPABILITY_NONE;
2053             default:
2054                 return PROCESS_CAPABILITY_NONE;
2055         }
2056     }
2057 
2058     /**
2059      * Checks if for the given app and client, there's a cycle that should skip over the client
2060      * for now or use partial values to evaluate the effect of the client binding.
2061      * @param app
2062      * @param client
2063      * @param procState procstate evaluated so far for this app
2064      * @param adj oom_adj evaluated so far for this app
2065      * @param cycleReEval whether we're currently re-evaluating due to a cycle, and not the first
2066      *                    evaluation.
2067      * @return whether to skip using the client connection at this time
2068      */
shouldSkipDueToCycle(ProcessRecord app, ProcessRecord client, int procState, int adj, boolean cycleReEval)2069     private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessRecord client,
2070             int procState, int adj, boolean cycleReEval) {
2071         if (client.containsCycle) {
2072             // We've detected a cycle. We should retry computeOomAdjLocked later in
2073             // case a later-checked connection from a client  would raise its
2074             // priority legitimately.
2075             app.containsCycle = true;
2076             // If the client has not been completely evaluated, check if it's worth
2077             // using the partial values.
2078             if (client.completedAdjSeq < mAdjSeq) {
2079                 if (cycleReEval) {
2080                     // If the partial values are no better, skip until the next
2081                     // attempt
2082                     if (client.getCurRawProcState() >= procState
2083                             && client.getCurRawAdj() >= adj) {
2084                         return true;
2085                     }
2086                     // Else use the client's partial procstate and adj to adjust the
2087                     // effect of the binding
2088                 } else {
2089                     return true;
2090                 }
2091             }
2092         }
2093         return false;
2094     }
2095 
2096     /** Inform the oomadj observer of changes to oomadj. Used by tests. */
2097     @GuardedBy("mService")
reportOomAdjMessageLocked(String tag, String msg)2098     void reportOomAdjMessageLocked(String tag, String msg) {
2099         Slog.d(tag, msg);
2100         if (mService.mCurOomAdjObserver != null) {
2101             mService.mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg).sendToTarget();
2102         }
2103     }
2104 
2105     /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
2106     @GuardedBy("mService")
applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now, long nowElapsed)2107     private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
2108             long nowElapsed) {
2109         boolean success = true;
2110 
2111         if (app.getCurRawAdj() != app.setRawAdj) {
2112             app.setRawAdj = app.getCurRawAdj();
2113         }
2114 
2115         int changes = 0;
2116 
2117         // don't compact during bootup
2118         if (mCachedAppOptimizer.useCompaction() && mService.mBooted) {
2119             // Cached and prev/home compaction
2120             if (app.curAdj != app.setAdj) {
2121                 // Perform a minor compaction when a perceptible app becomes the prev/home app
2122                 // Perform a major compaction when any app enters cached
2123                 // reminder: here, setAdj is previous state, curAdj is upcoming state
2124                 if (app.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ &&
2125                         (app.curAdj == ProcessList.PREVIOUS_APP_ADJ ||
2126                                 app.curAdj == ProcessList.HOME_APP_ADJ)) {
2127                     mCachedAppOptimizer.compactAppSome(app);
2128                 } else if ((app.setAdj < ProcessList.CACHED_APP_MIN_ADJ
2129                                 || app.setAdj > ProcessList.CACHED_APP_MAX_ADJ)
2130                         && app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
2131                         && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
2132                     mCachedAppOptimizer.compactAppFull(app);
2133                 }
2134             } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE
2135                     && app.setAdj < ProcessList.FOREGROUND_APP_ADJ
2136                     // Because these can fire independent of oom_adj/procstate changes, we need
2137                     // to throttle the actual dispatch of these requests in addition to the
2138                     // processing of the requests. As a result, there is throttling both here
2139                     // and in CachedAppOptimizer.
2140                     && mCachedAppOptimizer.shouldCompactPersistent(app, now)) {
2141                 mCachedAppOptimizer.compactAppPersistent(app);
2142             } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE
2143                     && app.getCurProcState()
2144                         == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
2145                     && mCachedAppOptimizer.shouldCompactBFGS(app, now)) {
2146                 mCachedAppOptimizer.compactAppBfgs(app);
2147             }
2148         }
2149 
2150         if (app.curAdj != app.setAdj) {
2151             ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
2152             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
2153                 String msg = "Set " + app.pid + " " + app.processName + " adj "
2154                         + app.curAdj + ": " + app.adjType;
2155                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
2156             }
2157             app.setAdj = app.curAdj;
2158             app.verifiedAdj = ProcessList.INVALID_ADJ;
2159         }
2160 
2161         final int curSchedGroup = app.getCurrentSchedulingGroup();
2162         if (app.setSchedGroup != curSchedGroup) {
2163             int oldSchedGroup = app.setSchedGroup;
2164             app.setSchedGroup = curSchedGroup;
2165             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
2166                 String msg = "Setting sched group of " + app.processName
2167                         + " to " + curSchedGroup + ": " + app.adjType;
2168                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
2169             }
2170             if (app.waitingToKill != null && app.curReceivers.isEmpty()
2171                     && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
2172                 app.kill(app.waitingToKill, ApplicationExitInfo.REASON_USER_REQUESTED,
2173                         ApplicationExitInfo.SUBREASON_UNKNOWN, true);
2174                 success = false;
2175             } else {
2176                 int processGroup;
2177                 switch (curSchedGroup) {
2178                     case ProcessList.SCHED_GROUP_BACKGROUND:
2179                         processGroup = THREAD_GROUP_BACKGROUND;
2180                         break;
2181                     case ProcessList.SCHED_GROUP_TOP_APP:
2182                     case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
2183                         processGroup = THREAD_GROUP_TOP_APP;
2184                         break;
2185                     case ProcessList.SCHED_GROUP_RESTRICTED:
2186                         processGroup = THREAD_GROUP_RESTRICTED;
2187                         break;
2188                     default:
2189                         processGroup = THREAD_GROUP_DEFAULT;
2190                         break;
2191                 }
2192                 mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
2193                         0 /* unused */, app.pid, processGroup, app.processName));
2194                 try {
2195                     if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
2196                         // do nothing if we already switched to RT
2197                         if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
2198                             app.getWindowProcessController().onTopProcChanged();
2199                             if (mService.mUseFifoUiScheduling) {
2200                                 // Switch UI pipeline for app to SCHED_FIFO
2201                                 app.savedPriority = Process.getThreadPriority(app.pid);
2202                                 mService.scheduleAsFifoPriority(app.pid, /* suppressLogs */true);
2203                                 if (app.renderThreadTid != 0) {
2204                                     mService.scheduleAsFifoPriority(app.renderThreadTid,
2205                                             /* suppressLogs */true);
2206                                     if (DEBUG_OOM_ADJ) {
2207                                         Slog.d("UI_FIFO", "Set RenderThread (TID " +
2208                                                 app.renderThreadTid + ") to FIFO");
2209                                     }
2210                                 } else {
2211                                     if (DEBUG_OOM_ADJ) {
2212                                         Slog.d("UI_FIFO", "Not setting RenderThread TID");
2213                                     }
2214                                 }
2215                             } else {
2216                                 // Boost priority for top app UI and render threads
2217                                 setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
2218                                 if (app.renderThreadTid != 0) {
2219                                     try {
2220                                         setThreadPriority(app.renderThreadTid,
2221                                                 TOP_APP_PRIORITY_BOOST);
2222                                     } catch (IllegalArgumentException e) {
2223                                         // thread died, ignore
2224                                     }
2225                                 }
2226                             }
2227                         }
2228                     } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
2229                             curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
2230                         app.getWindowProcessController().onTopProcChanged();
2231                         if (mService.mUseFifoUiScheduling) {
2232                             try {
2233                                 // Reset UI pipeline to SCHED_OTHER
2234                                 setThreadScheduler(app.pid, SCHED_OTHER, 0);
2235                                 setThreadPriority(app.pid, app.savedPriority);
2236                                 if (app.renderThreadTid != 0) {
2237                                     setThreadScheduler(app.renderThreadTid,
2238                                             SCHED_OTHER, 0);
2239                                 }
2240                             } catch (IllegalArgumentException e) {
2241                                 Slog.w(TAG,
2242                                         "Failed to set scheduling policy, thread does not exist:\n"
2243                                                 + e);
2244                             } catch (SecurityException e) {
2245                                 Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
2246                             }
2247                         } else {
2248                             // Reset priority for top app UI and render threads
2249                             setThreadPriority(app.pid, 0);
2250                         }
2251 
2252                         if (app.renderThreadTid != 0) {
2253                             setThreadPriority(app.renderThreadTid, THREAD_PRIORITY_DISPLAY);
2254                         }
2255                     }
2256                 } catch (Exception e) {
2257                     if (DEBUG_ALL) {
2258                         Slog.w(TAG, "Failed setting thread priority of " + app.pid, e);
2259                     }
2260                 }
2261             }
2262         }
2263         if (app.repForegroundActivities != app.hasForegroundActivities()) {
2264             app.repForegroundActivities = app.hasForegroundActivities();
2265             changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES;
2266         }
2267 
2268         updateAppFreezeStateLocked(app);
2269 
2270         if (app.getReportedProcState() != app.getCurProcState()) {
2271             app.setReportedProcState(app.getCurProcState());
2272             if (app.thread != null) {
2273                 try {
2274                     if (false) {
2275                         //RuntimeException h = new RuntimeException("here");
2276                         Slog.i(TAG, "Sending new process state " + app.getReportedProcState()
2277                                 + " to " + app /*, h*/);
2278                     }
2279                     app.thread.setProcessState(app.getReportedProcState());
2280                 } catch (RemoteException e) {
2281                 }
2282             }
2283         }
2284         if (app.setProcState == PROCESS_STATE_NONEXISTENT
2285                 || ProcessList.procStatesDifferForMem(app.getCurProcState(), app.setProcState)) {
2286             if (false && mService.mTestPssMode
2287                     && app.setProcState >= 0 && app.lastStateTime <= (now-200)) {
2288                 // Experimental code to more aggressively collect pss while
2289                 // running test...  the problem is that this tends to collect
2290                 // the data right when a process is transitioning between process
2291                 // states, which will tend to give noisy data.
2292                 long start = SystemClock.uptimeMillis();
2293                 long startTime = SystemClock.currentThreadTimeMillis();
2294                 long pss = Debug.getPss(app.pid, mTmpLong, null);
2295                 long endTime = SystemClock.currentThreadTimeMillis();
2296                 mService.recordPssSampleLocked(app, app.getCurProcState(), pss,
2297                         mTmpLong[0], mTmpLong[1], mTmpLong[2],
2298                         ProcessStats.ADD_PSS_INTERNAL_SINGLE, endTime-startTime, now);
2299                 mService.mPendingPssProcesses.remove(app);
2300                 Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
2301                         + " to " + app.getCurProcState() + ": "
2302                         + (SystemClock.uptimeMillis()-start) + "ms");
2303             }
2304             app.lastStateTime = now;
2305             app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(),
2306                     app.procStateMemTracker, mService.mTestPssMode,
2307                     mService.mAtmInternal.isSleeping(), now);
2308             if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
2309                     + ProcessList.makeProcStateString(app.setProcState) + " to "
2310                     + ProcessList.makeProcStateString(app.getCurProcState()) + " next pss in "
2311                     + (app.nextPssTime-now) + ": " + app);
2312         } else {
2313             if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
2314                     && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
2315                     mService.mTestPssMode)))) {
2316                 if (mService.requestPssLocked(app, app.setProcState)) {
2317                     app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(),
2318                             app.procStateMemTracker, mService.mTestPssMode,
2319                             mService.mAtmInternal.isSleeping(), now);
2320                 }
2321             } else if (false && DEBUG_PSS) {
2322                 Slog.d(TAG_PSS,
2323                         "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now));
2324             }
2325         }
2326         if (app.setProcState != app.getCurProcState()) {
2327             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
2328                 String msg = "Proc state change of " + app.processName
2329                         + " to " + ProcessList.makeProcStateString(app.getCurProcState())
2330                         + " (" + app.getCurProcState() + ")" + ": " + app.adjType;
2331                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
2332             }
2333             boolean setImportant = app.setProcState < PROCESS_STATE_SERVICE;
2334             boolean curImportant = app.getCurProcState() < PROCESS_STATE_SERVICE;
2335             if (setImportant && !curImportant) {
2336                 // This app is no longer something we consider important enough to allow to use
2337                 // arbitrary amounts of battery power. Note its current CPU time to later know to
2338                 // kill it if it is not behaving well.
2339                 app.setWhenUnimportant(now);
2340                 app.lastCpuTime = 0;
2341             }
2342             // Inform UsageStats of important process state change
2343             // Must be called before updating setProcState
2344             maybeUpdateUsageStatsLocked(app, nowElapsed);
2345 
2346             maybeUpdateLastTopTime(app, now);
2347 
2348             app.setProcState = app.getCurProcState();
2349             if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
2350                 app.notCachedSinceIdle = false;
2351             }
2352             if (!doingAll) {
2353                 mService.setProcessTrackerStateLocked(app,
2354                         mService.mProcessStats.getMemFactorLocked(), now);
2355             } else {
2356                 app.procStateChanged = true;
2357             }
2358         } else if (app.reportedInteraction && (nowElapsed - app.getInteractionEventTime())
2359                 > mConstants.USAGE_STATS_INTERACTION_INTERVAL) {
2360             // For apps that sit around for a long time in the interactive state, we need
2361             // to report this at least once a day so they don't go idle.
2362             maybeUpdateUsageStatsLocked(app, nowElapsed);
2363         } else if (!app.reportedInteraction && (nowElapsed - app.getFgInteractionTime())
2364                 > mConstants.SERVICE_USAGE_INTERACTION_TIME) {
2365             // For foreground services that sit around for a long time but are not interacted with.
2366             maybeUpdateUsageStatsLocked(app, nowElapsed);
2367         }
2368 
2369         if (app.curCapability != app.setCapability) {
2370             changes |= ActivityManagerService.ProcessChangeItem.CHANGE_CAPABILITY;
2371             app.setCapability = app.curCapability;
2372         }
2373 
2374         if (changes != 0) {
2375             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
2376                     "Changes in " + app + ": " + changes);
2377             ActivityManagerService.ProcessChangeItem item =
2378                     mService.enqueueProcessChangeItemLocked(app.pid, app.info.uid);
2379             item.changes |= changes;
2380             item.foregroundActivities = app.repForegroundActivities;
2381             item.capability = app.setCapability;
2382             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
2383                     "Item " + Integer.toHexString(System.identityHashCode(item))
2384                             + " " + app.toShortString() + ": changes=" + item.changes
2385                             + " foreground=" + item.foregroundActivities
2386                             + " type=" + app.adjType + " source=" + app.adjSource
2387                             + " target=" + app.adjTarget + " capability=" + item.capability);
2388         }
2389 
2390         return success;
2391     }
2392 
2393     @GuardedBy("mService")
setAttachingSchedGroupLocked(ProcessRecord app)2394     void setAttachingSchedGroupLocked(ProcessRecord app) {
2395         int initialSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
2396         // If the process has been marked as foreground via Zygote.START_FLAG_USE_TOP_APP_PRIORITY,
2397         // then verify that the top priority is actually is applied.
2398         if (app.hasForegroundActivities()) {
2399             String fallbackReason = null;
2400             try {
2401                 // The priority must be the same as how does {@link #applyOomAdjLocked} set for
2402                 // {@link ProcessList.SCHED_GROUP_TOP_APP}. We don't check render thread because it
2403                 // is not ready when attaching.
2404                 if (Process.getProcessGroup(app.pid) == THREAD_GROUP_TOP_APP) {
2405                     app.getWindowProcessController().onTopProcChanged();
2406                     setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
2407                 } else {
2408                     fallbackReason = "not expected top priority";
2409                 }
2410             } catch (Exception e) {
2411                 fallbackReason = e.toString();
2412             }
2413             if (fallbackReason == null) {
2414                 initialSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
2415             } else {
2416                 // The real scheduling group will depend on if there is any component of the process
2417                 // did something during attaching.
2418                 Slog.w(TAG, "Fallback pre-set sched group to default: " + fallbackReason);
2419             }
2420         }
2421 
2422         app.setCurrentSchedulingGroup(app.setSchedGroup = initialSchedGroup);
2423     }
2424 
2425     // ONLY used for unit testing in OomAdjusterTests.java
2426     @VisibleForTesting
maybeUpdateUsageStats(ProcessRecord app, long nowElapsed)2427     void maybeUpdateUsageStats(ProcessRecord app, long nowElapsed) {
2428         synchronized (mService) {
2429             maybeUpdateUsageStatsLocked(app, nowElapsed);
2430         }
2431     }
2432 
2433     @GuardedBy("mService")
maybeUpdateUsageStatsLocked(ProcessRecord app, long nowElapsed)2434     private void maybeUpdateUsageStatsLocked(ProcessRecord app, long nowElapsed) {
2435         if (DEBUG_USAGE_STATS) {
2436             Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList())
2437                     + "] state changes: old = " + app.setProcState + ", new = "
2438                     + app.getCurProcState());
2439         }
2440         if (mService.mUsageStatsService == null) {
2441             return;
2442         }
2443         boolean isInteraction;
2444         // To avoid some abuse patterns, we are going to be careful about what we consider
2445         // to be an app interaction.  Being the top activity doesn't count while the display
2446         // is sleeping, nor do short foreground services.
2447         if (app.getCurProcState() <= PROCESS_STATE_TOP
2448                 || app.getCurProcState() == PROCESS_STATE_BOUND_TOP) {
2449             isInteraction = true;
2450             app.setFgInteractionTime(0);
2451         } else if (app.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) {
2452             if (app.getFgInteractionTime() == 0) {
2453                 app.setFgInteractionTime(nowElapsed);
2454                 isInteraction = false;
2455             } else {
2456                 isInteraction = nowElapsed > app.getFgInteractionTime()
2457                         + mConstants.SERVICE_USAGE_INTERACTION_TIME;
2458             }
2459         } else {
2460             isInteraction =
2461                     app.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND;
2462             app.setFgInteractionTime(0);
2463         }
2464         if (isInteraction
2465                 && (!app.reportedInteraction || (nowElapsed - app.getInteractionEventTime())
2466                 > mConstants.USAGE_STATS_INTERACTION_INTERVAL)) {
2467             app.setInteractionEventTime(nowElapsed);
2468             String[] packages = app.getPackageList();
2469             if (packages != null) {
2470                 for (int i = 0; i < packages.length; i++) {
2471                     mService.mUsageStatsService.reportEvent(packages[i], app.userId,
2472                             UsageEvents.Event.SYSTEM_INTERACTION);
2473                 }
2474             }
2475         }
2476         app.reportedInteraction = isInteraction;
2477         if (!isInteraction) {
2478             app.setInteractionEventTime(0);
2479         }
2480     }
2481 
maybeUpdateLastTopTime(ProcessRecord app, long nowUptime)2482     private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) {
2483         if (app.setProcState <= PROCESS_STATE_TOP
2484                 && app.getCurProcState() > PROCESS_STATE_TOP) {
2485             app.lastTopTime = nowUptime;
2486         }
2487     }
2488 
2489     /**
2490      * Look for recently inactive apps and mark them idle after a grace period. If idled, stop
2491      * any background services and inform listeners.
2492      */
2493     @GuardedBy("mService")
idleUidsLocked()2494     void idleUidsLocked() {
2495         final int N = mActiveUids.size();
2496         if (N <= 0) {
2497             return;
2498         }
2499         final long nowElapsed = SystemClock.elapsedRealtime();
2500         final long maxBgTime = nowElapsed - mConstants.BACKGROUND_SETTLE_TIME;
2501         long nextTime = 0;
2502         if (mLocalPowerManager != null) {
2503             mLocalPowerManager.startUidChanges();
2504         }
2505         for (int i = N - 1; i >= 0; i--) {
2506             final UidRecord uidRec = mActiveUids.valueAt(i);
2507             final long bgTime = uidRec.lastBackgroundTime;
2508             if (bgTime > 0 && !uidRec.idle) {
2509                 if (bgTime <= maxBgTime) {
2510                     EventLogTags.writeAmUidIdle(uidRec.uid);
2511                     uidRec.idle = true;
2512                     uidRec.setIdle = true;
2513                     mService.doStopUidLocked(uidRec.uid, uidRec);
2514                 } else {
2515                     if (nextTime == 0 || nextTime > bgTime) {
2516                         nextTime = bgTime;
2517                     }
2518                 }
2519             }
2520         }
2521         if (mLocalPowerManager != null) {
2522             mLocalPowerManager.finishUidChanges();
2523         }
2524         if (nextTime > 0) {
2525             mService.mHandler.removeMessages(IDLE_UIDS_MSG);
2526             mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
2527                     nextTime + mConstants.BACKGROUND_SETTLE_TIME - nowElapsed);
2528         }
2529     }
2530 
2531     @GuardedBy("mService")
setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist)2532     final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) {
2533         boolean changed = false;
2534         for (int i = mActiveUids.size() - 1; i >= 0; i--) {
2535             final UidRecord uidRec = mActiveUids.valueAt(i);
2536             if (UserHandle.getAppId(uidRec.uid) == appId && uidRec.curWhitelist != onWhitelist) {
2537                 uidRec.curWhitelist = onWhitelist;
2538                 changed = true;
2539             }
2540         }
2541         if (changed) {
2542             updateOomAdjLocked(OOM_ADJ_REASON_WHITELIST);
2543         }
2544     }
2545 
2546     @GuardedBy("mService")
setUidTempWhitelistStateLocked(int uid, boolean onWhitelist)2547     final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) {
2548         boolean changed = false;
2549         final UidRecord uidRec = mActiveUids.get(uid);
2550         if (uidRec != null && uidRec.curWhitelist != onWhitelist) {
2551             uidRec.curWhitelist = onWhitelist;
2552             updateOomAdjLocked(OOM_ADJ_REASON_WHITELIST);
2553         }
2554     }
2555 
2556     @GuardedBy("mService")
dumpProcessListVariablesLocked(ProtoOutputStream proto)2557     void dumpProcessListVariablesLocked(ProtoOutputStream proto) {
2558         proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq);
2559         proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.mLruSeq);
2560         proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS,
2561                 mNumNonCachedProcs);
2562         proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs);
2563         proto.write(ActivityManagerServiceDumpProcessesProto.NEW_NUM_SERVICE_PROCS,
2564                 mNewNumServiceProcs);
2565 
2566     }
2567 
2568     @GuardedBy("mService")
dumpSequenceNumbersLocked(PrintWriter pw)2569     void dumpSequenceNumbersLocked(PrintWriter pw) {
2570         pw.println("  mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.mLruSeq);
2571     }
2572 
2573     @GuardedBy("mService")
dumpProcCountsLocked(PrintWriter pw)2574     void dumpProcCountsLocked(PrintWriter pw) {
2575         pw.println("  mNumNonCachedProcs=" + mNumNonCachedProcs
2576                 + " (" + mProcessList.getLruSizeLocked() + " total)"
2577                 + " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
2578                 + " mNumServiceProcs=" + mNumServiceProcs
2579                 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
2580     }
2581 
2582     @GuardedBy("mService")
dumpCachedAppOptimizerSettings(PrintWriter pw)2583     void dumpCachedAppOptimizerSettings(PrintWriter pw) {
2584         mCachedAppOptimizer.dump(pw);
2585     }
2586 
2587     @GuardedBy("mService")
updateAppFreezeStateLocked(ProcessRecord app)2588     void updateAppFreezeStateLocked(ProcessRecord app) {
2589         if (!mCachedAppOptimizer.useFreezer()) {
2590             return;
2591         }
2592 
2593         // if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze
2594         if (app.frozen && app.shouldNotFreeze) {
2595             mCachedAppOptimizer.unfreezeAppLocked(app);
2596         }
2597 
2598         // Use current adjustment when freezing, set adjustment when unfreezing.
2599         if (app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ && !app.frozen && !app.shouldNotFreeze) {
2600             mCachedAppOptimizer.freezeAppAsync(app);
2601         } else if (app.setAdj < ProcessList.CACHED_APP_MIN_ADJ && app.frozen) {
2602             mCachedAppOptimizer.unfreezeAppLocked(app);
2603         }
2604     }
2605 }
2606