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