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