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