OSDN Git Service

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