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