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