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