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