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