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