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_NETWORK; 25 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; 26 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 27 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; 28 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; 29 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; 30 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; 31 import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT; 32 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 33 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; 34 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; 35 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 36 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 37 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT; 38 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI; 39 import static android.app.ActivityManager.PROCESS_STATE_SERVICE; 40 import static android.app.ActivityManager.PROCESS_STATE_TOP; 41 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; 42 import static android.content.Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE; 43 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; 44 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; 45 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; 46 import static android.os.Process.SCHED_OTHER; 47 import static android.os.Process.THREAD_GROUP_BACKGROUND; 48 import static android.os.Process.THREAD_GROUP_DEFAULT; 49 import static android.os.Process.THREAD_GROUP_RESTRICTED; 50 import static android.os.Process.THREAD_GROUP_TOP_APP; 51 import static android.os.Process.THREAD_PRIORITY_DISPLAY; 52 import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST; 53 import static android.os.Process.setProcessGroup; 54 import static android.os.Process.setThreadPriority; 55 import static android.os.Process.setThreadScheduler; 56 57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; 58 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP; 59 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; 60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ; 61 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON; 62 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS; 63 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS; 64 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS; 65 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS; 66 import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG; 67 import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG; 68 import static com.android.server.am.ActivityManagerService.TAG_BACKUP; 69 import static com.android.server.am.ActivityManagerService.TAG_LRU; 70 import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ; 71 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS; 72 import static com.android.server.am.AppProfiler.TAG_PSS; 73 import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY; 74 import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY; 75 import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME; 76 import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS; 77 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 78 79 import android.annotation.Nullable; 80 import android.app.ActivityManager; 81 import android.app.ActivityThread; 82 import android.app.ApplicationExitInfo; 83 import android.app.usage.UsageEvents; 84 import android.compat.annotation.ChangeId; 85 import android.compat.annotation.EnabledAfter; 86 import android.compat.annotation.EnabledSince; 87 import android.content.BroadcastReceiver; 88 import android.content.ComponentName; 89 import android.content.Context; 90 import android.content.Intent; 91 import android.content.IntentFilter; 92 import android.content.pm.ApplicationInfo; 93 import android.content.pm.ServiceInfo; 94 import android.os.Handler; 95 import android.os.IBinder; 96 import android.os.PowerManagerInternal; 97 import android.os.Process; 98 import android.os.RemoteException; 99 import android.os.SystemClock; 100 import android.os.Trace; 101 import android.util.ArrayMap; 102 import android.util.ArraySet; 103 import android.util.Slog; 104 import android.util.proto.ProtoOutputStream; 105 106 import com.android.internal.annotations.CompositeRWLock; 107 import com.android.internal.annotations.GuardedBy; 108 import com.android.internal.annotations.VisibleForTesting; 109 import com.android.server.LocalServices; 110 import com.android.server.ServiceThread; 111 import com.android.server.am.PlatformCompatCache.CachedCompatChangeId; 112 import com.android.server.wm.ActivityServiceConnectionsHolder; 113 import com.android.server.wm.WindowProcessController; 114 115 import java.io.PrintWriter; 116 import java.util.ArrayDeque; 117 import java.util.ArrayList; 118 import java.util.Arrays; 119 120 /** 121 * All of the code required to compute proc states and oom_adj values. 122 */ 123 public class OomAdjuster { 124 static final String TAG = "OomAdjuster"; 125 static final String OOM_ADJ_REASON_METHOD = "updateOomAdj"; 126 static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh"; 127 static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange"; 128 static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver"; 129 static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver"; 130 static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService"; 131 static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService"; 132 static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService"; 133 static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider"; 134 static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider"; 135 static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility"; 136 static final String OOM_ADJ_REASON_ALLOWLIST = OOM_ADJ_REASON_METHOD + "_allowlistChange"; 137 static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin"; 138 static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd"; 139 140 /** 141 * Flag {@link android.content.Context#BIND_INCLUDE_CAPABILITIES} is used 142 * to pass while-in-use capabilities from client process to bound service. In targetSdkVersion 143 * R and above, if client is a TOP activity, when this flag is present, bound service gets all 144 * while-in-use capabilities; when this flag is not present, bound service gets no while-in-use 145 * capability from client. 146 */ 147 @ChangeId 148 @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q) 149 static final long PROCESS_CAPABILITY_CHANGE_ID = 136274596L; 150 151 /** 152 * In targetSdkVersion R and above, foreground service has camera and microphone while-in-use 153 * capability only when the {@link android.R.attr#foregroundServiceType} is configured as 154 * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and 155 * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the 156 * manifest file. 157 * In targetSdkVersion below R, foreground service automatically have camera and microphone 158 * capabilities. 159 */ 160 @ChangeId 161 @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q) 162 static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L; 163 164 /** 165 * For apps targeting S+, this determines whether to use a shorter timeout before elevating the 166 * standby bucket to ACTIVE when apps start a foreground service. 167 */ 168 @ChangeId 169 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) 170 static final long USE_SHORT_FGS_USAGE_INTERACTION_TIME = 183972877L; 171 172 /** 173 * For some direct access we need to power manager. 174 */ 175 PowerManagerInternal mLocalPowerManager; 176 177 /** 178 * Service for optimizing resource usage from background apps. 179 */ 180 CachedAppOptimizer mCachedAppOptimizer; 181 182 /** 183 * Re-rank apps getting a cache oom adjustment from lru to weighted order 184 * based on weighted scores for LRU, PSS and cache use count. 185 */ 186 CacheOomRanker mCacheOomRanker; 187 188 ActivityManagerConstants mConstants; 189 190 final long[] mTmpLong = new long[3]; 191 192 /** 193 * Current sequence id for oom_adj computation traversal. 194 */ 195 int mAdjSeq = 0; 196 197 /** 198 * Keep track of the number of service processes we last found, to 199 * determine on the next iteration which should be B services. 200 */ 201 int mNumServiceProcs = 0; 202 int mNewNumAServiceProcs = 0; 203 int mNewNumServiceProcs = 0; 204 205 /** 206 * Keep track of the non-cached/empty process we last found, to help 207 * determine how to distribute cached/empty processes next time. 208 */ 209 int mNumNonCachedProcs = 0; 210 211 /** 212 * Keep track of the number of cached hidden procs, to balance oom adj 213 * distribution between those and empty procs. 214 */ 215 int mNumCachedHiddenProcs = 0; 216 217 /** Track all uids that have actively running processes. */ 218 @CompositeRWLock({"mService", "mProcLock"}) 219 ActiveUids mActiveUids; 220 221 /** 222 * The handler to execute {@link #setProcessGroup} (it may be heavy if the process has many 223 * threads) for reducing the time spent in {@link #applyOomAdjLSP}. 224 */ 225 private final Handler mProcessGroupHandler; 226 227 private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet(); 228 229 private final ActivityManagerService mService; 230 private final ProcessList mProcessList; 231 private final ActivityManagerGlobalLock mProcLock; 232 233 private final int mNumSlots; 234 private final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>(); 235 private final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>(); 236 private final ActiveUids mTmpUidRecords; 237 private final ArrayDeque<ProcessRecord> mTmpQueue; 238 private final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>(); 239 private final ArraySet<ProcessRecord> mProcessesInCycle = new ArraySet<>(); 240 241 /** 242 * Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate 243 * could be called recursively because of the indirect calls during the update; 244 * however the oomAdjUpdate itself doesn't support recursion - in this case we'd 245 * have to queue up the new targets found during the update, and perform another 246 * round of oomAdjUpdate at the end of last update. 247 */ 248 @GuardedBy("mService") 249 private boolean mOomAdjUpdateOngoing = false; 250 251 /** 252 * Flag to mark if there is a pending full oomAdjUpdate. 253 */ 254 @GuardedBy("mService") 255 private boolean mPendingFullOomAdjUpdate = false; 256 257 /** Overrideable by a test */ 258 @VisibleForTesting isChangeEnabled(@achedCompatChangeId int cachedCompatChangeId, ApplicationInfo app, boolean defaultValue)259 protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, 260 ApplicationInfo app, boolean defaultValue) { 261 return PlatformCompatCache.getInstance() 262 .isChangeEnabled(cachedCompatChangeId, app, defaultValue); 263 } 264 OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids)265 OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) { 266 this(service, processList, activeUids, createAdjusterThread()); 267 } 268 createAdjusterThread()269 private static ServiceThread createAdjusterThread() { 270 // The process group is usually critical to the response time of foreground app, so the 271 // setter should apply it as soon as possible. 272 final ServiceThread adjusterThread = 273 new ServiceThread(TAG, THREAD_PRIORITY_TOP_APP_BOOST, false /* allowIo */); 274 adjusterThread.start(); 275 return adjusterThread; 276 } 277 OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, ServiceThread adjusterThread)278 OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, 279 ServiceThread adjusterThread) { 280 mService = service; 281 mProcessList = processList; 282 mProcLock = service.mProcLock; 283 mActiveUids = activeUids; 284 285 mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class); 286 mConstants = mService.mConstants; 287 mCachedAppOptimizer = new CachedAppOptimizer(mService); 288 mCacheOomRanker = new CacheOomRanker(service); 289 290 mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> { 291 final int pid = msg.arg1; 292 final int group = msg.arg2; 293 if (pid == ActivityManagerService.MY_PID) { 294 // Skip setting the process group for system_server, keep it as default. 295 return true; 296 } 297 if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 298 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup " 299 + msg.obj + " to " + group); 300 } 301 try { 302 setProcessGroup(pid, group); 303 } catch (Exception e) { 304 if (DEBUG_ALL) { 305 Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e); 306 } 307 } finally { 308 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 309 } 310 return true; 311 }); 312 mTmpUidRecords = new ActiveUids(service, false); 313 mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1); 314 mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1) 315 / ProcessList.CACHED_APP_IMPORTANCE_LEVELS; 316 } 317 initSettings()318 void initSettings() { 319 mCachedAppOptimizer.init(); 320 mCacheOomRanker.init(ActivityThread.currentApplication().getMainExecutor()); 321 if (mService.mConstants.KEEP_WARMING_SERVICES.size() > 0) { 322 final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); 323 mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() { 324 @Override 325 public void onReceive(Context context, Intent intent) { 326 synchronized (mService) { 327 handleUserSwitchedLocked(); 328 } 329 } 330 }, filter, null, mService.mHandler); 331 } 332 } 333 334 /** 335 * Update the keep-warming service flags upon user switches 336 */ 337 @VisibleForTesting 338 @GuardedBy("mService") handleUserSwitchedLocked()339 void handleUserSwitchedLocked() { 340 mProcessList.forEachLruProcessesLOSP(false, 341 this::updateKeepWarmIfNecessaryForProcessLocked); 342 } 343 344 @GuardedBy("mService") updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app)345 private void updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app) { 346 final ArraySet<ComponentName> warmServices = mService.mConstants.KEEP_WARMING_SERVICES; 347 boolean includeWarmPkg = false; 348 final PackageList pkgList = app.getPkgList(); 349 for (int j = warmServices.size() - 1; j >= 0; j--) { 350 if (pkgList.containsKey(warmServices.valueAt(j).getPackageName())) { 351 includeWarmPkg = true; 352 break; 353 } 354 } 355 if (!includeWarmPkg) { 356 return; 357 } 358 final ProcessServiceRecord psr = app.mServices; 359 for (int j = psr.numberOfRunningServices() - 1; j >= 0; j--) { 360 psr.getRunningServiceAt(j).updateKeepWarmLocked(); 361 } 362 } 363 364 /** 365 * Perform oom adj update on the given process. It does NOT do the re-computation 366 * if there is a cycle, caller should check {@link #mProcessesInCycle} and do it on its own. 367 */ 368 @GuardedBy({"mService", "mProcLock"}) performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj, ProcessRecord topApp, long now, String oomAdjReason)369 private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj, 370 ProcessRecord topApp, long now, String oomAdjReason) { 371 if (app.getThread() == null) { 372 return false; 373 } 374 375 app.mState.resetCachedInfo(); 376 app.mState.setCurBoundByNonBgRestrictedApp(false); 377 UidRecord uidRec = app.getUidRecord(); 378 if (uidRec != null) { 379 if (DEBUG_UID_OBSERVERS) { 380 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec); 381 } 382 uidRec.reset(); 383 } 384 385 // Check if this process is in the pending list too, remove from pending list if so. 386 mPendingProcessSet.remove(app); 387 388 mProcessesInCycle.clear(); 389 computeOomAdjLSP(app, cachedAdj, topApp, false, now, false, true); 390 if (!mProcessesInCycle.isEmpty()) { 391 // We can't use the score here if there is a cycle, abort. 392 for (int i = mProcessesInCycle.size() - 1; i >= 0; i--) { 393 // Reset the adj seq 394 mProcessesInCycle.valueAt(i).mState.setCompletedAdjSeq(mAdjSeq - 1); 395 } 396 return true; 397 } 398 399 if (uidRec != null) { 400 // After uidRec.reset() above, for UidRecord with multiple processes (ProcessRecord), 401 // we need to apply all ProcessRecord into UidRecord. 402 uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP); 403 if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT 404 && (uidRec.getSetProcState() != uidRec.getCurProcState() 405 || uidRec.getSetCapability() != uidRec.getCurCapability() 406 || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) { 407 ActiveUids uids = mTmpUidRecords; 408 uids.clear(); 409 uids.put(uidRec.getUid(), uidRec); 410 updateUidsLSP(uids, SystemClock.elapsedRealtime()); 411 } 412 } 413 414 return applyOomAdjLSP(app, false, now, SystemClock.elapsedRealtime(), oomAdjReason); 415 } 416 417 /** 418 * Update OomAdj for all processes in LRU list 419 */ 420 @GuardedBy("mService") updateOomAdjLocked(String oomAdjReason)421 void updateOomAdjLocked(String oomAdjReason) { 422 synchronized (mProcLock) { 423 updateOomAdjLSP(oomAdjReason); 424 } 425 } 426 427 @GuardedBy({"mService", "mProcLock"}) updateOomAdjLSP(String oomAdjReason)428 private void updateOomAdjLSP(String oomAdjReason) { 429 if (checkAndEnqueueOomAdjTargetLocked(null)) { 430 // Simply return as there is an oomAdjUpdate ongoing 431 return; 432 } 433 try { 434 mOomAdjUpdateOngoing = true; 435 performUpdateOomAdjLSP(oomAdjReason); 436 } finally { 437 // Kick off the handling of any pending targets enqueued during the above update 438 mOomAdjUpdateOngoing = false; 439 updateOomAdjPendingTargetsLocked(oomAdjReason); 440 } 441 } 442 443 @GuardedBy({"mService", "mProcLock"}) performUpdateOomAdjLSP(String oomAdjReason)444 private void performUpdateOomAdjLSP(String oomAdjReason) { 445 final ProcessRecord topApp = mService.getTopApp(); 446 // Clear any pending ones because we are doing a full update now. 447 mPendingProcessSet.clear(); 448 mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false; 449 updateOomAdjInnerLSP(oomAdjReason, topApp , null, null, true, true); 450 } 451 452 /** 453 * Update OomAdj for specific process and its reachable processes (with direction/indirect 454 * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc 455 * is hosting any service/content provider. 456 * 457 * @param app The process to update, or null to update all processes 458 * @param oomAdjReason 459 */ 460 @GuardedBy("mService") updateOomAdjLocked(ProcessRecord app, String oomAdjReason)461 boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) { 462 synchronized (mProcLock) { 463 return updateOomAdjLSP(app, oomAdjReason); 464 } 465 } 466 467 @GuardedBy({"mService", "mProcLock"}) updateOomAdjLSP(ProcessRecord app, String oomAdjReason)468 private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) { 469 if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) { 470 updateOomAdjLSP(oomAdjReason); 471 return true; 472 } 473 474 if (checkAndEnqueueOomAdjTargetLocked(app)) { 475 // Simply return true as there is an oomAdjUpdate ongoing 476 return true; 477 } 478 479 try { 480 mOomAdjUpdateOngoing = true; 481 return performUpdateOomAdjLSP(app, oomAdjReason); 482 } finally { 483 // Kick off the handling of any pending targets enqueued during the above update 484 mOomAdjUpdateOngoing = false; 485 updateOomAdjPendingTargetsLocked(oomAdjReason); 486 } 487 } 488 489 @GuardedBy({"mService", "mProcLock"}) performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason)490 private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) { 491 final ProcessRecord topApp = mService.getTopApp(); 492 493 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason); 494 mService.mOomAdjProfiler.oomAdjStarted(); 495 mAdjSeq++; 496 497 // Firstly, try to see if the importance of itself gets changed 498 final ProcessStateRecord state = app.mState; 499 final boolean wasCached = state.isCached(); 500 final int oldAdj = state.getCurRawAdj(); 501 final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ 502 ? oldAdj : ProcessList.UNKNOWN_ADJ; 503 final boolean wasBackground = ActivityManager.isProcStateBackground( 504 state.getSetProcState()); 505 final int oldCap = state.getSetCapability(); 506 state.setContainsCycle(false); 507 state.setProcStateChanged(false); 508 state.resetCachedInfo(); 509 state.setCurBoundByNonBgRestrictedApp(false); 510 // Check if this process is in the pending list too, remove from pending list if so. 511 mPendingProcessSet.remove(app); 512 boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, 513 SystemClock.uptimeMillis(), oomAdjReason); 514 // The 'app' here itself might or might not be in the cycle, for example, 515 // the case A <=> B vs. A -> B <=> C; anyway, if we spot a cycle here, re-compute them. 516 if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ 517 && mProcessesInCycle.isEmpty() /* Force re-compute if there is a cycle */ 518 && oldCap == state.getCurCapability() 519 && wasBackground == ActivityManager.isProcStateBackground( 520 state.getSetProcState()))) { 521 mProcessesInCycle.clear(); 522 // Okay, it's unchanged, it won't impact any service it binds to, we're done here. 523 if (DEBUG_OOM_ADJ) { 524 Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app); 525 } 526 mService.mOomAdjProfiler.oomAdjEnded(); 527 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 528 return success; 529 } 530 531 // Next to find out all its reachable processes 532 ArrayList<ProcessRecord> processes = mTmpProcessList; 533 ActiveUids uids = mTmpUidRecords; 534 mPendingProcessSet.add(app); 535 536 // Add all processes with cycles into the list to scan 537 for (int i = mProcessesInCycle.size() - 1; i >= 0; i--) { 538 mPendingProcessSet.add(mProcessesInCycle.valueAt(i)); 539 } 540 mProcessesInCycle.clear(); 541 542 boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet, 543 processes, uids); 544 545 // Clear the pending set as they should've been included in 'processes'. 546 mPendingProcessSet.clear(); 547 548 if (!containsCycle) { 549 // Reset the flag 550 state.setReachable(false); 551 // Remove this app from the return list because we've done the computation on it. 552 processes.remove(app); 553 } 554 555 int size = processes.size(); 556 if (size > 0) { 557 mAdjSeq--; 558 // Update these reachable processes 559 updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false); 560 } else if (state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) { 561 // In case the app goes from non-cached to cached but it doesn't have other reachable 562 // processes, its adj could be still unknown as of now, assign one. 563 processes.add(app); 564 assignCachedAdjIfNecessary(processes); 565 applyOomAdjLSP(app, false, SystemClock.uptimeMillis(), 566 SystemClock.elapsedRealtime(), oomAdjReason); 567 } 568 mTmpProcessList.clear(); 569 mService.mOomAdjProfiler.oomAdjEnded(); 570 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 571 return true; 572 } 573 574 @GuardedBy("mService") collectReachableProcessesLocked(ArraySet<ProcessRecord> apps, ArrayList<ProcessRecord> processes, ActiveUids uids)575 private boolean collectReachableProcessesLocked(ArraySet<ProcessRecord> apps, 576 ArrayList<ProcessRecord> processes, ActiveUids uids) { 577 final ArrayDeque<ProcessRecord> queue = mTmpQueue; 578 queue.clear(); 579 processes.clear(); 580 for (int i = 0, size = apps.size(); i < size; i++) { 581 final ProcessRecord app = apps.valueAt(i); 582 app.mState.setReachable(true); 583 queue.offer(app); 584 } 585 586 uids.clear(); 587 588 // Track if any of them reachables could include a cycle 589 boolean containsCycle = false; 590 // Scan downstreams of the process record 591 for (ProcessRecord pr = queue.poll(); pr != null; pr = queue.poll()) { 592 processes.add(pr); 593 final UidRecord uidRec = pr.getUidRecord(); 594 if (uidRec != null) { 595 uids.put(uidRec.getUid(), uidRec); 596 } 597 final ProcessServiceRecord psr = pr.mServices; 598 for (int i = psr.numberOfConnections() - 1; i >= 0; i--) { 599 ConnectionRecord cr = psr.getConnectionAt(i); 600 ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0 601 ? cr.binding.service.isolationHostProc : cr.binding.service.app; 602 if (service == null || service == pr) { 603 continue; 604 } 605 containsCycle |= service.mState.isReachable(); 606 if (service.mState.isReachable()) { 607 continue; 608 } 609 if ((cr.flags & (Context.BIND_WAIVE_PRIORITY 610 | Context.BIND_TREAT_LIKE_ACTIVITY 611 | Context.BIND_ADJUST_WITH_ACTIVITY)) 612 == Context.BIND_WAIVE_PRIORITY) { 613 continue; 614 } 615 queue.offer(service); 616 service.mState.setReachable(true); 617 } 618 final ProcessProviderRecord ppr = pr.mProviders; 619 for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) { 620 ContentProviderConnection cpc = ppr.getProviderConnectionAt(i); 621 ProcessRecord provider = cpc.provider.proc; 622 if (provider == null || provider == pr) { 623 continue; 624 } 625 containsCycle |= provider.mState.isReachable(); 626 if (provider.mState.isReachable()) { 627 continue; 628 } 629 queue.offer(provider); 630 provider.mState.setReachable(true); 631 } 632 } 633 634 int size = processes.size(); 635 if (size > 0) { 636 // Reverse the process list, since the updateOomAdjInnerLSP scans from the end of it. 637 for (int l = 0, r = size - 1; l < r; l++, r--) { 638 ProcessRecord t = processes.get(l); 639 processes.set(l, processes.get(r)); 640 processes.set(r, t); 641 } 642 } 643 return containsCycle; 644 } 645 646 /** 647 * Enqueue the given process for a later oom adj update 648 */ 649 @GuardedBy("mService") enqueueOomAdjTargetLocked(ProcessRecord app)650 void enqueueOomAdjTargetLocked(ProcessRecord app) { 651 if (app != null) { 652 mPendingProcessSet.add(app); 653 } 654 } 655 656 @GuardedBy("mService") removeOomAdjTargetLocked(ProcessRecord app, boolean procDied)657 void removeOomAdjTargetLocked(ProcessRecord app, boolean procDied) { 658 if (app != null) { 659 mPendingProcessSet.remove(app); 660 if (procDied) { 661 PlatformCompatCache.getInstance().invalidate(app.info); 662 } 663 } 664 } 665 666 /** 667 * Check if there is an ongoing oomAdjUpdate, enqueue the given process record 668 * to {@link #mPendingProcessSet} if there is one. 669 * 670 * @param app The target app to get an oomAdjUpdate, or a full oomAdjUpdate if it's null. 671 * @return {@code true} if there is an ongoing oomAdjUpdate. 672 */ 673 @GuardedBy("mService") checkAndEnqueueOomAdjTargetLocked(@ullable ProcessRecord app)674 private boolean checkAndEnqueueOomAdjTargetLocked(@Nullable ProcessRecord app) { 675 if (!mOomAdjUpdateOngoing) { 676 return false; 677 } 678 if (app != null) { 679 mPendingProcessSet.add(app); 680 } else { 681 mPendingFullOomAdjUpdate = true; 682 } 683 return true; 684 } 685 686 /** 687 * Kick off an oom adj update pass for the pending targets which are enqueued via 688 * {@link #enqueueOomAdjTargetLocked}. 689 */ 690 @GuardedBy("mService") updateOomAdjPendingTargetsLocked(String oomAdjReason)691 void updateOomAdjPendingTargetsLocked(String oomAdjReason) { 692 // First check if there is pending full update 693 if (mPendingFullOomAdjUpdate) { 694 mPendingFullOomAdjUpdate = false; 695 mPendingProcessSet.clear(); 696 updateOomAdjLocked(oomAdjReason); 697 return; 698 } 699 if (mPendingProcessSet.isEmpty()) { 700 return; 701 } 702 703 if (mOomAdjUpdateOngoing) { 704 // There's another oomAdjUpdate ongoing, return from here now; 705 // that ongoing update would call us again at the end of it. 706 return; 707 } 708 try { 709 mOomAdjUpdateOngoing = true; 710 performUpdateOomAdjPendingTargetsLocked(oomAdjReason); 711 } finally { 712 // Kick off the handling of any pending targets enqueued during the above update 713 mOomAdjUpdateOngoing = false; 714 updateOomAdjPendingTargetsLocked(oomAdjReason); 715 } 716 } 717 718 @GuardedBy("mService") performUpdateOomAdjPendingTargetsLocked(String oomAdjReason)719 private void performUpdateOomAdjPendingTargetsLocked(String oomAdjReason) { 720 final ProcessRecord topApp = mService.getTopApp(); 721 722 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason); 723 mService.mOomAdjProfiler.oomAdjStarted(); 724 725 final ArrayList<ProcessRecord> processes = mTmpProcessList; 726 final ActiveUids uids = mTmpUidRecords; 727 collectReachableProcessesLocked(mPendingProcessSet, processes, uids); 728 mPendingProcessSet.clear(); 729 synchronized (mProcLock) { 730 updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false); 731 } 732 processes.clear(); 733 734 mService.mOomAdjProfiler.oomAdjEnded(); 735 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 736 } 737 738 /** 739 * Update OomAdj for all processes within the given list (could be partial), or the whole LRU 740 * list if the given list is null; when it's partial update, each process's client proc won't 741 * get evaluated recursively here. 742 */ 743 @GuardedBy({"mService", "mProcLock"}) updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp, ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles, boolean startProfiling)744 private void updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp, 745 ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles, 746 boolean startProfiling) { 747 if (startProfiling) { 748 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason); 749 mService.mOomAdjProfiler.oomAdjStarted(); 750 } 751 final long now = SystemClock.uptimeMillis(); 752 final long nowElapsed = SystemClock.elapsedRealtime(); 753 final long oldTime = now - mConstants.mMaxEmptyTimeMillis; 754 final boolean fullUpdate = processes == null; 755 ActiveUids activeUids = uids; 756 ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP() 757 : processes; 758 final int numProc = activeProcesses.size(); 759 760 if (activeUids == null) { 761 final int numUids = mActiveUids.size(); 762 activeUids = mTmpUidRecords; 763 activeUids.clear(); 764 for (int i = 0; i < numUids; i++) { 765 UidRecord uidRec = mActiveUids.valueAt(i); 766 activeUids.put(uidRec.getUid(), uidRec); 767 } 768 } 769 770 // Reset state in all uid records. 771 for (int i = activeUids.size() - 1; i >= 0; i--) { 772 final UidRecord uidRec = activeUids.valueAt(i); 773 if (DEBUG_UID_OBSERVERS) { 774 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec); 775 } 776 uidRec.reset(); 777 } 778 779 mAdjSeq++; 780 if (fullUpdate) { 781 mNewNumServiceProcs = 0; 782 mNewNumAServiceProcs = 0; 783 } 784 785 boolean retryCycles = false; 786 boolean computeClients = fullUpdate || potentialCycles; 787 788 // need to reset cycle state before calling computeOomAdjLSP because of service conns 789 for (int i = numProc - 1; i >= 0; i--) { 790 ProcessRecord app = activeProcesses.get(i); 791 final ProcessStateRecord state = app.mState; 792 state.setReachable(false); 793 // No need to compute again it has been evaluated in previous iteration 794 if (state.getAdjSeq() != mAdjSeq) { 795 state.setContainsCycle(false); 796 state.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); 797 state.setCurRawAdj(ProcessList.UNKNOWN_ADJ); 798 state.setSetCapability(PROCESS_CAPABILITY_NONE); 799 state.resetCachedInfo(); 800 state.setCurBoundByNonBgRestrictedApp(false); 801 } 802 } 803 mProcessesInCycle.clear(); 804 for (int i = numProc - 1; i >= 0; i--) { 805 ProcessRecord app = activeProcesses.get(i); 806 final ProcessStateRecord state = app.mState; 807 if (!app.isKilledByAm() && app.getThread() != null) { 808 state.setProcStateChanged(false); 809 computeOomAdjLSP(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false, 810 computeClients); // It won't enter cycle if not computing clients. 811 // if any app encountered a cycle, we need to perform an additional loop later 812 retryCycles |= state.containsCycle(); 813 // Keep the completedAdjSeq to up to date. 814 state.setCompletedAdjSeq(mAdjSeq); 815 } 816 } 817 818 if (mCacheOomRanker.useOomReranking()) { 819 mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(), 820 mProcessList.getLruProcessServiceStartLOSP()); 821 } 822 assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP()); 823 824 if (computeClients) { // There won't be cycles if we didn't compute clients above. 825 // Cycle strategy: 826 // - Retry computing any process that has encountered a cycle. 827 // - Continue retrying until no process was promoted. 828 // - Iterate from least important to most important. 829 int cycleCount = 0; 830 while (retryCycles && cycleCount < 10) { 831 cycleCount++; 832 retryCycles = false; 833 834 for (int i = 0; i < numProc; i++) { 835 ProcessRecord app = activeProcesses.get(i); 836 final ProcessStateRecord state = app.mState; 837 if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) { 838 state.decAdjSeq(); 839 state.decCompletedAdjSeq(); 840 } 841 } 842 843 for (int i = 0; i < numProc; i++) { 844 ProcessRecord app = activeProcesses.get(i); 845 final ProcessStateRecord state = app.mState; 846 if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) { 847 if (computeOomAdjLSP(app, state.getCurRawAdj(), topApp, true, now, 848 true, true)) { 849 retryCycles = true; 850 } 851 } 852 } 853 } 854 } 855 mProcessesInCycle.clear(); 856 857 mNumNonCachedProcs = 0; 858 mNumCachedHiddenProcs = 0; 859 860 boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids, 861 oomAdjReason); 862 mNumServiceProcs = mNewNumServiceProcs; 863 864 if (mService.mAlwaysFinishActivities) { 865 // Need to do this on its own message because the stack may not 866 // be in a consistent state at this point. 867 mService.mAtmInternal.scheduleDestroyAllActivities("always-finish"); 868 } 869 870 if (allChanged) { 871 mService.mAppProfiler.requestPssAllProcsLPr(now, false, 872 mService.mProcessStats.isMemFactorLowered()); 873 } 874 875 updateUidsLSP(activeUids, nowElapsed); 876 877 synchronized (mService.mProcessStats.mLock) { 878 final long nowUptime = SystemClock.uptimeMillis(); 879 if (mService.mProcessStats.shouldWriteNowLocked(nowUptime)) { 880 mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService, 881 mService.mProcessStats)); 882 } 883 884 // Run this after making sure all procstates are updated. 885 mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, nowUptime); 886 } 887 888 if (DEBUG_OOM_ADJ) { 889 final long duration = SystemClock.uptimeMillis() - now; 890 if (false) { 891 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms", 892 new RuntimeException("here").fillInStackTrace()); 893 } else { 894 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms"); 895 } 896 } 897 if (startProfiling) { 898 mService.mOomAdjProfiler.oomAdjEnded(); 899 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 900 } 901 } 902 903 @GuardedBy({"mService", "mProcLock"}) assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList)904 private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) { 905 final int numLru = lruList.size(); 906 907 // First update the OOM adjustment for each of the 908 // application processes based on their current state. 909 int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ; 910 int nextCachedAdj = curCachedAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2); 911 int curCachedImpAdj = 0; 912 int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS; 913 int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2); 914 915 final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES; 916 final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES 917 - emptyProcessLimit; 918 // Let's determine how many processes we have running vs. 919 // how many slots we have for background processes; we may want 920 // to put multiple processes in a slot of there are enough of 921 // them. 922 int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs; 923 if (numEmptyProcs > cachedProcessLimit) { 924 // If there are more empty processes than our limit on cached 925 // processes, then use the cached process limit for the factor. 926 // This ensures that the really old empty processes get pushed 927 // down to the bottom, so if we are running low on memory we will 928 // have a better chance at keeping around more cached processes 929 // instead of a gazillion empty processes. 930 numEmptyProcs = cachedProcessLimit; 931 } 932 int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1) 933 / mNumSlots; 934 if (cachedFactor < 1) cachedFactor = 1; 935 936 int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots; 937 if (emptyFactor < 1) emptyFactor = 1; 938 939 int stepCached = -1; 940 int stepEmpty = -1; 941 int lastCachedGroup = 0; 942 int lastCachedGroupImportance = 0; 943 int lastCachedGroupUid = 0; 944 945 for (int i = numLru - 1; i >= 0; i--) { 946 ProcessRecord app = lruList.get(i); 947 final ProcessStateRecord state = app.mState; 948 // If we haven't yet assigned the final cached adj 949 // to the process, do that now. 950 if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj() 951 >= ProcessList.UNKNOWN_ADJ) { 952 final ProcessServiceRecord psr = app.mServices; 953 switch (state.getCurProcState()) { 954 case PROCESS_STATE_CACHED_ACTIVITY: 955 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: 956 case ActivityManager.PROCESS_STATE_CACHED_RECENT: 957 // Figure out the next cached level, taking into account groups. 958 boolean inGroup = false; 959 final int connectionGroup = psr.getConnectionGroup(); 960 if (connectionGroup != 0) { 961 final int connectionImportance = psr.getConnectionImportance(); 962 if (lastCachedGroupUid == app.uid 963 && lastCachedGroup == connectionGroup) { 964 // This is in the same group as the last process, just tweak 965 // adjustment by importance. 966 if (connectionImportance > lastCachedGroupImportance) { 967 lastCachedGroupImportance = connectionImportance; 968 if (curCachedAdj < nextCachedAdj 969 && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) { 970 curCachedImpAdj++; 971 } 972 } 973 inGroup = true; 974 } else { 975 lastCachedGroupUid = app.uid; 976 lastCachedGroup = connectionGroup; 977 lastCachedGroupImportance = connectionImportance; 978 } 979 } 980 if (!inGroup && curCachedAdj != nextCachedAdj) { 981 stepCached++; 982 curCachedImpAdj = 0; 983 if (stepCached >= cachedFactor) { 984 stepCached = 0; 985 curCachedAdj = nextCachedAdj; 986 nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2; 987 if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) { 988 nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ; 989 } 990 } 991 } 992 // This process is a cached process holding activities... 993 // assign it the next cached value for that type, and then 994 // step that cached level. 995 state.setCurRawAdj(curCachedAdj + curCachedImpAdj); 996 state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj)); 997 if (DEBUG_LRU) { 998 Slog.d(TAG_LRU, "Assigning activity LRU #" + i 999 + " adj: " + state.getCurAdj() 1000 + " (curCachedAdj=" + curCachedAdj 1001 + " curCachedImpAdj=" + curCachedImpAdj + ")"); 1002 } 1003 break; 1004 default: 1005 // Figure out the next cached level. 1006 if (curEmptyAdj != nextEmptyAdj) { 1007 stepEmpty++; 1008 if (stepEmpty >= emptyFactor) { 1009 stepEmpty = 0; 1010 curEmptyAdj = nextEmptyAdj; 1011 nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2; 1012 if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) { 1013 nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ; 1014 } 1015 } 1016 } 1017 // For everything else, assign next empty cached process 1018 // level and bump that up. Note that this means that 1019 // long-running services that have dropped down to the 1020 // cached level will be treated as empty (since their process 1021 // state is still as a service), which is what we want. 1022 state.setCurRawAdj(curEmptyAdj); 1023 state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj)); 1024 if (DEBUG_LRU) { 1025 Slog.d(TAG_LRU, "Assigning empty LRU #" + i 1026 + " adj: " + state.getCurAdj() + " (curEmptyAdj=" + curEmptyAdj 1027 + ")"); 1028 } 1029 break; 1030 } 1031 } 1032 } 1033 } 1034 1035 private long mNextNoKillDebugMessageTime; 1036 1037 private double mLastFreeSwapPercent = 1.00; 1038 getFreeSwapPercent()1039 private static double getFreeSwapPercent() { 1040 return CachedAppOptimizer.getFreeSwapPercent(); 1041 } 1042 1043 @GuardedBy({"mService", "mProcLock"}) updateAndTrimProcessLSP(final long now, final long nowElapsed, final long oldTime, final ActiveUids activeUids, String oomAdjReason)1044 private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed, 1045 final long oldTime, final ActiveUids activeUids, String oomAdjReason) { 1046 ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP(); 1047 final int numLru = lruList.size(); 1048 1049 final boolean doKillExcessiveProcesses = shouldKillExcessiveProcesses(now); 1050 if (!doKillExcessiveProcesses) { 1051 if (mNextNoKillDebugMessageTime < now) { 1052 Slog.d(TAG, "Not killing cached processes"); // STOPSHIP Remove it b/222365734 1053 mNextNoKillDebugMessageTime = now + 5000; // Every 5 seconds 1054 } 1055 } 1056 final int emptyProcessLimit = doKillExcessiveProcesses 1057 ? mConstants.CUR_MAX_EMPTY_PROCESSES : Integer.MAX_VALUE; 1058 final int cachedProcessLimit = doKillExcessiveProcesses 1059 ? (mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit) : Integer.MAX_VALUE; 1060 int lastCachedGroup = 0; 1061 int lastCachedGroupUid = 0; 1062 int numCached = 0; 1063 int numCachedExtraGroup = 0; 1064 int numEmpty = 0; 1065 int numTrimming = 0; 1066 1067 boolean proactiveKillsEnabled = mConstants.PROACTIVE_KILLS_ENABLED; 1068 double lowSwapThresholdPercent = mConstants.LOW_SWAP_THRESHOLD_PERCENT; 1069 double freeSwapPercent = proactiveKillsEnabled ? getFreeSwapPercent() : 1.00; 1070 ProcessRecord lruCachedApp = null; 1071 1072 for (int i = numLru - 1; i >= 0; i--) { 1073 ProcessRecord app = lruList.get(i); 1074 final ProcessStateRecord state = app.mState; 1075 if (!app.isKilledByAm() && app.getThread() != null) { 1076 // We don't need to apply the update for the process which didn't get computed 1077 if (state.getCompletedAdjSeq() == mAdjSeq) { 1078 applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason); 1079 } 1080 1081 final ProcessServiceRecord psr = app.mServices; 1082 // Count the number of process types. 1083 switch (state.getCurProcState()) { 1084 case PROCESS_STATE_CACHED_ACTIVITY: 1085 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: 1086 mNumCachedHiddenProcs++; 1087 numCached++; 1088 final int connectionGroup = psr.getConnectionGroup(); 1089 if (connectionGroup != 0) { 1090 if (lastCachedGroupUid == app.info.uid 1091 && lastCachedGroup == connectionGroup) { 1092 // If this process is the next in the same group, we don't 1093 // want it to count against our limit of the number of cached 1094 // processes, so bump up the group count to account for it. 1095 numCachedExtraGroup++; 1096 } else { 1097 lastCachedGroupUid = app.info.uid; 1098 lastCachedGroup = connectionGroup; 1099 } 1100 } else { 1101 lastCachedGroupUid = lastCachedGroup = 0; 1102 } 1103 if ((numCached - numCachedExtraGroup) > cachedProcessLimit) { 1104 app.killLocked("cached #" + numCached, 1105 "too many cached", 1106 ApplicationExitInfo.REASON_OTHER, 1107 ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED, 1108 true); 1109 } else if (proactiveKillsEnabled) { 1110 lruCachedApp = app; 1111 } 1112 break; 1113 case PROCESS_STATE_CACHED_EMPTY: 1114 if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES 1115 && app.getLastActivityTime() < oldTime) { 1116 app.killLocked("empty for " + ((now 1117 - app.getLastActivityTime()) / 1000) + "s", 1118 "empty for too long", 1119 ApplicationExitInfo.REASON_OTHER, 1120 ApplicationExitInfo.SUBREASON_TRIM_EMPTY, 1121 true); 1122 } else { 1123 numEmpty++; 1124 if (numEmpty > emptyProcessLimit) { 1125 app.killLocked("empty #" + numEmpty, 1126 "too many empty", 1127 ApplicationExitInfo.REASON_OTHER, 1128 ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, 1129 true); 1130 } else if (proactiveKillsEnabled) { 1131 lruCachedApp = app; 1132 } 1133 } 1134 break; 1135 default: 1136 mNumNonCachedProcs++; 1137 break; 1138 } 1139 1140 if (app.isolated && psr.numberOfRunningServices() <= 0 1141 && app.getIsolatedEntryPoint() == null) { 1142 // If this is an isolated process, there are no services 1143 // running in it, and it's not a special process with a 1144 // custom entry point, then the process is no longer 1145 // needed. We agressively kill these because we can by 1146 // definition not re-use the same process again, and it is 1147 // good to avoid having whatever code was running in them 1148 // left sitting around after no longer needed. 1149 app.killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER, 1150 ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true); 1151 } else { 1152 // Keeping this process, update its uid. 1153 updateAppUidRecLSP(app); 1154 } 1155 1156 if (state.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME 1157 && !app.isKilledByAm()) { 1158 numTrimming++; 1159 } 1160 } 1161 } 1162 1163 if (proactiveKillsEnabled // Proactive kills enabled? 1164 && doKillExcessiveProcesses // Should kill excessive processes? 1165 && freeSwapPercent < lowSwapThresholdPercent // Swap below threshold? 1166 && lruCachedApp != null // If no cached app, let LMKD decide 1167 // If swap is non-decreasing, give reclaim a chance to catch up 1168 && freeSwapPercent < mLastFreeSwapPercent) { 1169 lruCachedApp.killLocked("swap low and too many cached", 1170 ApplicationExitInfo.REASON_OTHER, 1171 ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED, 1172 true); 1173 } 1174 1175 mLastFreeSwapPercent = freeSwapPercent; 1176 1177 return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming); 1178 } 1179 1180 @GuardedBy({"mService", "mProcLock"}) updateAppUidRecIfNecessaryLSP(final ProcessRecord app)1181 private void updateAppUidRecIfNecessaryLSP(final ProcessRecord app) { 1182 if (!app.isKilledByAm() && app.getThread() != null) { 1183 if (app.isolated && app.mServices.numberOfRunningServices() <= 0 1184 && app.getIsolatedEntryPoint() == null) { 1185 // No op. 1186 } else { 1187 // Keeping this process, update its uid. 1188 updateAppUidRecLSP(app); 1189 } 1190 } 1191 } 1192 1193 @GuardedBy({"mService", "mProcLock"}) updateAppUidRecLSP(ProcessRecord app)1194 private void updateAppUidRecLSP(ProcessRecord app) { 1195 final UidRecord uidRec = app.getUidRecord(); 1196 if (uidRec != null) { 1197 final ProcessStateRecord state = app.mState; 1198 uidRec.setEphemeral(app.info.isInstantApp()); 1199 if (uidRec.getCurProcState() > state.getCurProcState()) { 1200 uidRec.setCurProcState(state.getCurProcState()); 1201 } 1202 if (app.mServices.hasForegroundServices()) { 1203 uidRec.setForegroundServices(true); 1204 } 1205 uidRec.setCurCapability(uidRec.getCurCapability() | state.getCurCapability()); 1206 } 1207 } 1208 1209 @GuardedBy({"mService", "mProcLock"}) updateUidsLSP(ActiveUids activeUids, final long nowElapsed)1210 private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) { 1211 // This compares previously set procstate to the current procstate in regards to whether 1212 // or not the app's network access will be blocked. So, this needs to be called before 1213 // we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}. 1214 mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids); 1215 1216 ArrayList<UidRecord> becameIdle = mTmpBecameIdle; 1217 becameIdle.clear(); 1218 1219 // Update from any uid changes. 1220 if (mLocalPowerManager != null) { 1221 mLocalPowerManager.startUidChanges(); 1222 } 1223 for (int i = activeUids.size() - 1; i >= 0; i--) { 1224 final UidRecord uidRec = activeUids.valueAt(i); 1225 if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT) { 1226 if (uidRec.getSetProcState() != uidRec.getCurProcState() 1227 || uidRec.getSetCapability() != uidRec.getCurCapability() 1228 || uidRec.isSetAllowListed() != uidRec.isCurAllowListed() 1229 || uidRec.getProcAdjChanged()) { 1230 int uidChange = 0; 1231 if (DEBUG_UID_OBSERVERS) { 1232 Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec 1233 + ": proc state from " + uidRec.getSetProcState() + " to " 1234 + uidRec.getCurProcState() + ", capability from " 1235 + uidRec.getSetCapability() + " to " + uidRec.getCurCapability() 1236 + ", allowlist from " + uidRec.isSetAllowListed() 1237 + " to " + uidRec.isCurAllowListed() 1238 + ", procAdjChanged: " + uidRec.getProcAdjChanged()); 1239 } 1240 if (ActivityManager.isProcStateBackground(uidRec.getCurProcState()) 1241 && !uidRec.isCurAllowListed()) { 1242 // UID is now in the background (and not on the temp allowlist). Was it 1243 // previously in the foreground (or on the temp allowlist)? 1244 if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState()) 1245 || uidRec.isSetAllowListed()) { 1246 uidRec.setLastBackgroundTime(nowElapsed); 1247 if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) { 1248 // Note: the background settle time is in elapsed realtime, while 1249 // the handler time base is uptime. All this means is that we may 1250 // stop background uids later than we had intended, but that only 1251 // happens because the device was sleeping so we are okay anyway. 1252 mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, 1253 mConstants.BACKGROUND_SETTLE_TIME); 1254 } 1255 } 1256 if (uidRec.isIdle() && !uidRec.isSetIdle()) { 1257 uidChange |= UidRecord.CHANGE_IDLE; 1258 becameIdle.add(uidRec); 1259 } 1260 } else { 1261 if (uidRec.isIdle()) { 1262 uidChange |= UidRecord.CHANGE_ACTIVE; 1263 EventLogTags.writeAmUidActive(uidRec.getUid()); 1264 uidRec.setIdle(false); 1265 } 1266 uidRec.setLastBackgroundTime(0); 1267 } 1268 final boolean wasCached = uidRec.getSetProcState() 1269 > ActivityManager.PROCESS_STATE_RECEIVER; 1270 final boolean isCached = uidRec.getCurProcState() 1271 > ActivityManager.PROCESS_STATE_RECEIVER; 1272 if (wasCached != isCached 1273 || uidRec.getSetProcState() == PROCESS_STATE_NONEXISTENT) { 1274 uidChange |= isCached ? UidRecord.CHANGE_CACHED : 1275 UidRecord.CHANGE_UNCACHED; 1276 } 1277 if (uidRec.getSetCapability() != uidRec.getCurCapability()) { 1278 uidChange |= UidRecord.CHANGE_CAPABILITY; 1279 } 1280 if (uidRec.getSetProcState() != uidRec.getCurProcState()) { 1281 uidChange |= UidRecord.CHANGE_PROCSTATE; 1282 } 1283 if (uidRec.getProcAdjChanged()) { 1284 uidChange |= UidRecord.CHANGE_PROCADJ; 1285 } 1286 uidRec.setSetProcState(uidRec.getCurProcState()); 1287 uidRec.setSetCapability(uidRec.getCurCapability()); 1288 uidRec.setSetAllowListed(uidRec.isCurAllowListed()); 1289 uidRec.setSetIdle(uidRec.isIdle()); 1290 uidRec.clearProcAdjChanged(); 1291 if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0 1292 || (uidChange & UidRecord.CHANGE_CAPABILITY) != 0) { 1293 mService.mAtmInternal.onUidProcStateChanged( 1294 uidRec.getUid(), uidRec.getSetProcState()); 1295 } 1296 if (uidChange != 0) { 1297 mService.enqueueUidChangeLocked(uidRec, -1, uidChange); 1298 } 1299 if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0 1300 || (uidChange & UidRecord.CHANGE_CAPABILITY) != 0) { 1301 mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState(), 1302 uidRec.getCurCapability()); 1303 } 1304 if (uidRec.hasForegroundServices()) { 1305 mService.mServices.foregroundServiceProcStateChangedLocked(uidRec); 1306 } 1307 } 1308 } 1309 mService.mInternal.deletePendingTopUid(uidRec.getUid(), nowElapsed); 1310 } 1311 if (mLocalPowerManager != null) { 1312 mLocalPowerManager.finishUidChanges(); 1313 } 1314 1315 int size = becameIdle.size(); 1316 if (size > 0) { 1317 // If we have any new uids that became idle this time, we need to make sure 1318 // they aren't left with running services. 1319 for (int i = size - 1; i >= 0; i--) { 1320 mService.mServices.stopInBackgroundLocked(becameIdle.get(i).getUid()); 1321 } 1322 } 1323 } 1324 1325 /** 1326 * Return true if we should kill excessive cached/empty processes. 1327 */ shouldKillExcessiveProcesses(long nowUptime)1328 private boolean shouldKillExcessiveProcesses(long nowUptime) { 1329 final long lastUserUnlockingUptime = mService.mUserController.getLastUserUnlockingUptime(); 1330 1331 if (lastUserUnlockingUptime == 0) { 1332 // No users have been unlocked. 1333 return !mConstants.mNoKillCachedProcessesUntilBootCompleted; 1334 } 1335 final long noKillCachedProcessesPostBootCompletedDurationMillis = 1336 mConstants.mNoKillCachedProcessesPostBootCompletedDurationMillis; 1337 if ((lastUserUnlockingUptime + noKillCachedProcessesPostBootCompletedDurationMillis) 1338 > nowUptime) { 1339 return false; 1340 } 1341 return true; 1342 } 1343 1344 private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback = 1345 new ComputeOomAdjWindowCallback(); 1346 1347 /** These methods are called inline during computeOomAdjLSP(), on the same thread */ 1348 final class ComputeOomAdjWindowCallback 1349 implements WindowProcessController.ComputeOomAdjCallback { 1350 1351 ProcessRecord app; 1352 int adj; 1353 boolean foregroundActivities; 1354 boolean mHasVisibleActivities; 1355 int procState; 1356 int schedGroup; 1357 int appUid; 1358 int logUid; 1359 int processStateCurTop; 1360 ProcessStateRecord mState; 1361 initialize(ProcessRecord app, int adj, boolean foregroundActivities, boolean hasVisibleActivities, int procState, int schedGroup, int appUid, int logUid, int processStateCurTop)1362 void initialize(ProcessRecord app, int adj, boolean foregroundActivities, 1363 boolean hasVisibleActivities, int procState, int schedGroup, int appUid, 1364 int logUid, int processStateCurTop) { 1365 this.app = app; 1366 this.adj = adj; 1367 this.foregroundActivities = foregroundActivities; 1368 this.mHasVisibleActivities = hasVisibleActivities; 1369 this.procState = procState; 1370 this.schedGroup = schedGroup; 1371 this.appUid = appUid; 1372 this.logUid = logUid; 1373 this.processStateCurTop = processStateCurTop; 1374 this.mState = app.mState; 1375 } 1376 1377 @Override onVisibleActivity()1378 public void onVisibleActivity() { 1379 // App has a visible activity; only upgrade adjustment. 1380 if (adj > ProcessList.VISIBLE_APP_ADJ) { 1381 adj = ProcessList.VISIBLE_APP_ADJ; 1382 mState.setAdjType("vis-activity"); 1383 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1384 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app); 1385 } 1386 } 1387 if (procState > processStateCurTop) { 1388 procState = processStateCurTop; 1389 mState.setAdjType("vis-activity"); 1390 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1391 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1392 "Raise procstate to vis-activity (top): " + app); 1393 } 1394 } 1395 if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) { 1396 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1397 } 1398 mState.setCached(false); 1399 mState.setEmpty(false); 1400 foregroundActivities = true; 1401 mHasVisibleActivities = true; 1402 } 1403 1404 @Override onPausedActivity()1405 public void onPausedActivity() { 1406 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { 1407 adj = ProcessList.PERCEPTIBLE_APP_ADJ; 1408 mState.setAdjType("pause-activity"); 1409 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1410 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: " + app); 1411 } 1412 } 1413 if (procState > processStateCurTop) { 1414 procState = processStateCurTop; 1415 mState.setAdjType("pause-activity"); 1416 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1417 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1418 "Raise procstate to pause-activity (top): " + app); 1419 } 1420 } 1421 if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) { 1422 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1423 } 1424 mState.setCached(false); 1425 mState.setEmpty(false); 1426 foregroundActivities = true; 1427 mHasVisibleActivities = false; 1428 } 1429 1430 @Override onStoppingActivity(boolean finishing)1431 public void onStoppingActivity(boolean finishing) { 1432 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { 1433 adj = ProcessList.PERCEPTIBLE_APP_ADJ; 1434 mState.setAdjType("stop-activity"); 1435 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1436 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1437 "Raise adj to stop-activity: " + app); 1438 } 1439 } 1440 1441 // For the process state, we will at this point consider the process to be cached. It 1442 // will be cached either as an activity or empty depending on whether the activity is 1443 // finishing. We do this so that we can treat the process as cached for purposes of 1444 // memory trimming (determining current memory level, trim command to send to process) 1445 // since there can be an arbitrary number of stopping processes and they should soon all 1446 // go into the cached state. 1447 if (!finishing) { 1448 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 1449 procState = PROCESS_STATE_LAST_ACTIVITY; 1450 mState.setAdjType("stop-activity"); 1451 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1452 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1453 "Raise procstate to stop-activity: " + app); 1454 } 1455 } 1456 } 1457 mState.setCached(false); 1458 mState.setEmpty(false); 1459 foregroundActivities = true; 1460 mHasVisibleActivities = false; 1461 } 1462 1463 @Override onOtherActivity()1464 public void onOtherActivity() { 1465 if (procState > PROCESS_STATE_CACHED_ACTIVITY) { 1466 procState = PROCESS_STATE_CACHED_ACTIVITY; 1467 mState.setAdjType("cch-act"); 1468 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1469 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1470 "Raise procstate to cached activity: " + app); 1471 } 1472 } 1473 mHasVisibleActivities = false; 1474 } 1475 } 1476 1477 @GuardedBy({"mService", "mProcLock"}) computeOomAdjLSP(ProcessRecord app, int cachedAdj, ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval, boolean computeClients)1478 private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj, 1479 ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval, 1480 boolean computeClients) { 1481 final ProcessStateRecord state = app.mState; 1482 if (mAdjSeq == state.getAdjSeq()) { 1483 if (state.getAdjSeq() == state.getCompletedAdjSeq()) { 1484 // This adjustment has already been computed successfully. 1485 return false; 1486 } else { 1487 // The process is being computed, so there is a cycle. We cannot 1488 // rely on this process's state. 1489 state.setContainsCycle(true); 1490 mProcessesInCycle.add(app); 1491 1492 return false; 1493 } 1494 } 1495 1496 if (app.getThread() == null) { 1497 state.setAdjSeq(mAdjSeq); 1498 state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND); 1499 state.setCurProcState(PROCESS_STATE_CACHED_EMPTY); 1500 state.setCurAdj(ProcessList.CACHED_APP_MAX_ADJ); 1501 state.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ); 1502 state.setCompletedAdjSeq(state.getAdjSeq()); 1503 state.setCurCapability(PROCESS_CAPABILITY_NONE); 1504 return false; 1505 } 1506 1507 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN); 1508 state.setAdjSource(null); 1509 state.setAdjTarget(null); 1510 state.setEmpty(false); 1511 state.setCached(false); 1512 if (!cycleReEval) { 1513 // Don't reset this flag when doing cycles re-evaluation. 1514 state.setNoKillOnBgRestrictedAndIdle(false); 1515 // If this UID is currently allowlisted, it should not be frozen. 1516 final UidRecord uidRec = app.getUidRecord(); 1517 app.mOptRecord.setShouldNotFreeze(uidRec != null && uidRec.isCurAllowListed()); 1518 } 1519 1520 final int appUid = app.info.uid; 1521 final int logUid = mService.mCurOomAdjUid; 1522 1523 int prevAppAdj = state.getCurAdj(); 1524 int prevProcState = state.getCurProcState(); 1525 int prevCapability = state.getCurCapability(); 1526 final ProcessServiceRecord psr = app.mServices; 1527 1528 if (state.getMaxAdj() <= ProcessList.FOREGROUND_APP_ADJ) { 1529 // The max adjustment doesn't allow this app to be anything 1530 // below foreground, so it is not worth doing work for it. 1531 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1532 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app); 1533 } 1534 state.setAdjType("fixed"); 1535 state.setAdjSeq(mAdjSeq); 1536 state.setCurRawAdj(state.getMaxAdj()); 1537 state.setHasForegroundActivities(false); 1538 state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT); 1539 state.setCurCapability(PROCESS_CAPABILITY_ALL); 1540 state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT); 1541 // System processes can do UI, and when they do we want to have 1542 // them trim their memory after the user leaves the UI. To 1543 // facilitate this, here we need to determine whether or not it 1544 // is currently showing UI. 1545 state.setSystemNoUi(true); 1546 if (app == topApp) { 1547 state.setSystemNoUi(false); 1548 state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); 1549 state.setAdjType("pers-top-activity"); 1550 } else if (state.hasTopUi()) { 1551 // sched group/proc state adjustment is below 1552 state.setSystemNoUi(false); 1553 state.setAdjType("pers-top-ui"); 1554 } else if (state.getCachedHasVisibleActivities()) { 1555 state.setSystemNoUi(false); 1556 } 1557 if (!state.isSystemNoUi()) { 1558 if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE 1559 || state.isRunningRemoteAnimation()) { 1560 // screen on or animating, promote UI 1561 state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI); 1562 state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); 1563 } else { 1564 // screen off, restrict UI scheduling 1565 state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 1566 state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED); 1567 } 1568 } 1569 state.setCurRawProcState(state.getCurProcState()); 1570 state.setCurAdj(state.getMaxAdj()); 1571 state.setCompletedAdjSeq(state.getAdjSeq()); 1572 // if curAdj is less than prevAppAdj, then this process was promoted 1573 return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState; 1574 } 1575 1576 state.setSystemNoUi(false); 1577 1578 final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState(); 1579 1580 // Determine the importance of the process, starting with most 1581 // important to least, and assign an appropriate OOM adjustment. 1582 int adj; 1583 int schedGroup; 1584 int procState; 1585 int capability = cycleReEval ? app.mState.getCurCapability() : 0; 1586 1587 boolean foregroundActivities = false; 1588 boolean hasVisibleActivities = false; 1589 if (app == topApp && (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP 1590 || PROCESS_STATE_CUR_TOP == PROCESS_STATE_IMPORTANT_FOREGROUND)) { 1591 // The last app on the list is the foreground app. 1592 adj = ProcessList.FOREGROUND_APP_ADJ; 1593 if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP) { 1594 schedGroup = ProcessList.SCHED_GROUP_TOP_APP; 1595 state.setAdjType("top-activity"); 1596 } else { 1597 // Demote the scheduling group to avoid CPU contention if there is another more 1598 // important process which also uses top-app, such as if SystemUI is animating. 1599 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1600 state.setAdjType("intermediate-top-activity"); 1601 } 1602 foregroundActivities = true; 1603 hasVisibleActivities = true; 1604 procState = PROCESS_STATE_TOP; 1605 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1606 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app); 1607 } 1608 } else if (state.isRunningRemoteAnimation()) { 1609 adj = ProcessList.VISIBLE_APP_ADJ; 1610 schedGroup = ProcessList.SCHED_GROUP_TOP_APP; 1611 state.setAdjType("running-remote-anim"); 1612 procState = PROCESS_STATE_CUR_TOP; 1613 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1614 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app); 1615 } 1616 } else if (app.getActiveInstrumentation() != null) { 1617 // Don't want to kill running instrumentation. 1618 adj = ProcessList.FOREGROUND_APP_ADJ; 1619 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1620 state.setAdjType("instrumentation"); 1621 procState = PROCESS_STATE_FOREGROUND_SERVICE; 1622 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1623 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app); 1624 } 1625 } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) { 1626 // An app that is currently receiving a broadcast also 1627 // counts as being in the foreground for OOM killer purposes. 1628 // It's placed in a sched group based on the nature of the 1629 // broadcast as reflected by which queue it's active in. 1630 adj = ProcessList.FOREGROUND_APP_ADJ; 1631 schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue)) 1632 ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; 1633 state.setAdjType("broadcast"); 1634 procState = ActivityManager.PROCESS_STATE_RECEIVER; 1635 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1636 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app); 1637 } 1638 } else if (psr.numberOfExecutingServices() > 0) { 1639 // An app that is currently executing a service callback also 1640 // counts as being in the foreground. 1641 adj = ProcessList.FOREGROUND_APP_ADJ; 1642 schedGroup = psr.shouldExecServicesFg() 1643 ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; 1644 state.setAdjType("exec-service"); 1645 procState = PROCESS_STATE_SERVICE; 1646 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1647 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app); 1648 } 1649 } else if (app == topApp) { 1650 adj = ProcessList.FOREGROUND_APP_ADJ; 1651 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; 1652 state.setAdjType("top-sleeping"); 1653 foregroundActivities = true; 1654 procState = PROCESS_STATE_CUR_TOP; 1655 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1656 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app); 1657 } 1658 } else { 1659 // As far as we know the process is empty. We may change our mind later. 1660 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; 1661 // At this point we don't actually know the adjustment. Use the cached adj 1662 // value that the caller wants us to. 1663 adj = cachedAdj; 1664 procState = PROCESS_STATE_CACHED_EMPTY; 1665 if (!state.containsCycle()) { 1666 state.setCached(true); 1667 state.setEmpty(true); 1668 state.setAdjType("cch-empty"); 1669 } 1670 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1671 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app); 1672 } 1673 } 1674 1675 // Examine all activities if not already foreground. 1676 if (!foregroundActivities && state.getCachedHasActivities()) { 1677 state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback, 1678 adj, foregroundActivities, hasVisibleActivities, procState, schedGroup, 1679 appUid, logUid, PROCESS_STATE_CUR_TOP); 1680 1681 adj = state.getCachedAdj(); 1682 foregroundActivities = state.getCachedForegroundActivities(); 1683 hasVisibleActivities = state.getCachedHasVisibleActivities(); 1684 procState = state.getCachedProcState(); 1685 schedGroup = state.getCachedSchedGroup(); 1686 } 1687 1688 if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) { 1689 procState = PROCESS_STATE_CACHED_RECENT; 1690 state.setAdjType("cch-rec"); 1691 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1692 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app); 1693 } 1694 } 1695 1696 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ 1697 || procState > PROCESS_STATE_FOREGROUND_SERVICE) { 1698 if (psr.hasForegroundServices()) { 1699 // The user is aware of this app, so make it visible. 1700 adj = ProcessList.PERCEPTIBLE_APP_ADJ; 1701 procState = PROCESS_STATE_FOREGROUND_SERVICE; 1702 state.setAdjType("fg-service"); 1703 state.setCached(false); 1704 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1705 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1706 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + state.getAdjType() + ": " 1707 + app + " "); 1708 } 1709 } else if (state.hasOverlayUi()) { 1710 // The process is display an overlay UI. 1711 adj = ProcessList.PERCEPTIBLE_APP_ADJ; 1712 procState = PROCESS_STATE_IMPORTANT_FOREGROUND; 1713 state.setCached(false); 1714 state.setAdjType("has-overlay-ui"); 1715 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1716 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1717 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app); 1718 } 1719 } 1720 } 1721 1722 // If the app was recently in the foreground and moved to a foreground service status, 1723 // allow it to get a higher rank in memory for some time, compared to other foreground 1724 // services so that it can finish performing any persistence/processing of in-memory state. 1725 if (psr.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 1726 && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now 1727 || state.getSetProcState() <= PROCESS_STATE_TOP)) { 1728 adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; 1729 state.setAdjType("fg-service-act"); 1730 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1731 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app); 1732 } 1733 } 1734 1735 // If the app was recently in the foreground and has expedited jobs running, 1736 // allow it to get a higher rank in memory for some time, compared to other EJS and even 1737 // foreground services so that it can finish performing any persistence/processing of 1738 // in-memory state. 1739 if (psr.hasTopStartedAlmostPerceptibleServices() 1740 && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 1741 && (state.getLastTopTime() 1742 + mConstants.TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION > now 1743 || state.getSetProcState() <= PROCESS_STATE_TOP)) { 1744 adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; 1745 // This shall henceforth be called the "EJ" exemption, despite utilizing the 1746 // ALMOST_PERCEPTIBLE flag to work. 1747 state.setAdjType("top-ej-act"); 1748 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1749 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg for EJ: " + app); 1750 } 1751 } 1752 1753 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ 1754 || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { 1755 if (state.getForcingToImportant() != null) { 1756 // This is currently used for toasts... they are not interactive, and 1757 // we don't want them to cause the app to become fully foreground (and 1758 // thus out of background check), so we yes the best background level we can. 1759 adj = ProcessList.PERCEPTIBLE_APP_ADJ; 1760 procState = PROCESS_STATE_TRANSIENT_BACKGROUND; 1761 state.setCached(false); 1762 state.setAdjType("force-imp"); 1763 state.setAdjSource(state.getForcingToImportant()); 1764 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 1765 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1766 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app); 1767 } 1768 } 1769 } 1770 1771 if (state.getCachedIsHeavyWeight()) { 1772 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) { 1773 // We don't want to kill the current heavy-weight process. 1774 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ; 1775 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; 1776 state.setCached(false); 1777 state.setAdjType("heavy"); 1778 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1779 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app); 1780 } 1781 } 1782 if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { 1783 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; 1784 state.setAdjType("heavy"); 1785 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1786 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app); 1787 } 1788 } 1789 } 1790 1791 if (state.getCachedIsHomeProcess()) { 1792 if (adj > ProcessList.HOME_APP_ADJ) { 1793 // This process is hosting what we currently consider to be the 1794 // home app, so we don't want to let it go into the background. 1795 adj = ProcessList.HOME_APP_ADJ; 1796 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; 1797 state.setCached(false); 1798 state.setAdjType("home"); 1799 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1800 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app); 1801 } 1802 } 1803 if (procState > ActivityManager.PROCESS_STATE_HOME) { 1804 procState = ActivityManager.PROCESS_STATE_HOME; 1805 state.setAdjType("home"); 1806 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1807 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app); 1808 } 1809 } 1810 } 1811 1812 if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) { 1813 if (adj > ProcessList.PREVIOUS_APP_ADJ) { 1814 // This was the previous process that showed UI to the user. 1815 // We want to try to keep it around more aggressively, to give 1816 // a good experience around switching between two apps. 1817 adj = ProcessList.PREVIOUS_APP_ADJ; 1818 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; 1819 state.setCached(false); 1820 state.setAdjType("previous"); 1821 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1822 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app); 1823 } 1824 } 1825 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 1826 procState = PROCESS_STATE_LAST_ACTIVITY; 1827 state.setAdjType("previous"); 1828 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1829 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app); 1830 } 1831 } 1832 } 1833 1834 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj 1835 + " reason=" + state.getAdjType()); 1836 1837 // By default, we use the computed adjustment. It may be changed if 1838 // there are applications dependent on our services or providers, but 1839 // this gives us a baseline and makes sure we don't get into an 1840 // infinite recursion. If we're re-evaluating due to cycles, use the previously computed 1841 // values. 1842 if (cycleReEval) { 1843 procState = Math.min(procState, state.getCurRawProcState()); 1844 adj = Math.min(adj, state.getCurRawAdj()); 1845 schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup()); 1846 } 1847 state.setCurRawAdj(adj); 1848 state.setCurRawProcState(procState); 1849 1850 state.setHasStartedServices(false); 1851 state.setAdjSeq(mAdjSeq); 1852 1853 final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId); 1854 if (backupTarget != null && app == backupTarget.app) { 1855 // If possible we want to avoid killing apps while they're being backed up 1856 if (adj > ProcessList.BACKUP_APP_ADJ) { 1857 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app); 1858 adj = ProcessList.BACKUP_APP_ADJ; 1859 if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { 1860 procState = PROCESS_STATE_TRANSIENT_BACKGROUND; 1861 } 1862 state.setAdjType("backup"); 1863 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1864 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app); 1865 } 1866 state.setCached(false); 1867 } 1868 if (procState > ActivityManager.PROCESS_STATE_BACKUP) { 1869 procState = ActivityManager.PROCESS_STATE_BACKUP; 1870 state.setAdjType("backup"); 1871 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1872 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app); 1873 } 1874 } 1875 } 1876 1877 int capabilityFromFGS = 0; // capability from foreground service. 1878 boolean boundByNonBgRestricted = state.isCurBoundByNonBgRestrictedApp(); 1879 boolean scheduleLikeTopApp = false; 1880 for (int is = psr.numberOfRunningServices() - 1; 1881 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ 1882 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND 1883 || procState > PROCESS_STATE_TOP); 1884 is--) { 1885 ServiceRecord s = psr.getRunningServiceAt(is); 1886 if (s.startRequested) { 1887 state.setHasStartedServices(true); 1888 if (procState > PROCESS_STATE_SERVICE) { 1889 procState = PROCESS_STATE_SERVICE; 1890 state.setAdjType("started-services"); 1891 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1892 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1893 "Raise procstate to started service: " + app); 1894 } 1895 } 1896 if (!s.mKeepWarming && state.hasShownUi() && !state.getCachedIsHomeProcess()) { 1897 // If this process has shown some UI, let it immediately 1898 // go to the LRU list because it may be pretty heavy with 1899 // UI stuff. We'll tag it with a label just to help 1900 // debug and understand what is going on. 1901 if (adj > ProcessList.SERVICE_ADJ) { 1902 state.setAdjType("cch-started-ui-services"); 1903 } 1904 } else { 1905 if (s.mKeepWarming 1906 || now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) { 1907 // This service has seen some activity within 1908 // recent memory, so we will keep its process ahead 1909 // of the background processes. 1910 if (adj > ProcessList.SERVICE_ADJ) { 1911 adj = ProcessList.SERVICE_ADJ; 1912 state.setAdjType("started-services"); 1913 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1914 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1915 "Raise adj to started service: " + app); 1916 } 1917 state.setCached(false); 1918 } 1919 } 1920 // If we have let the service slide into the background 1921 // state, still have some text describing what it is doing 1922 // even though the service no longer has an impact. 1923 if (adj > ProcessList.SERVICE_ADJ) { 1924 state.setAdjType("cch-started-services"); 1925 } 1926 } 1927 } 1928 1929 if (s.isForeground) { 1930 final int fgsType = s.foregroundServiceType; 1931 if (s.mAllowWhileInUsePermissionInFgs) { 1932 capabilityFromFGS |= 1933 (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) 1934 != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; 1935 1936 final boolean enabled = state.getCachedCompatChange( 1937 CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY); 1938 if (enabled) { 1939 capabilityFromFGS |= 1940 (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA) 1941 != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0; 1942 capabilityFromFGS |= 1943 (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE) 1944 != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0; 1945 } else { 1946 capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA 1947 | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; 1948 } 1949 } 1950 } 1951 1952 ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections(); 1953 for (int conni = serviceConnections.size() - 1; 1954 conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ 1955 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND 1956 || procState > PROCESS_STATE_TOP); 1957 conni--) { 1958 ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni); 1959 for (int i = 0; 1960 i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ 1961 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND 1962 || procState > PROCESS_STATE_TOP); 1963 i++) { 1964 // XXX should compute this based on the max of 1965 // all connected clients. 1966 ConnectionRecord cr = clist.get(i); 1967 if (cr.binding.client == app) { 1968 // Binding to oneself is not interesting. 1969 continue; 1970 } 1971 1972 boolean trackedProcState = false; 1973 1974 ProcessRecord client = cr.binding.client; 1975 final ProcessStateRecord cstate = client.mState; 1976 if (computeClients) { 1977 computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, 1978 cycleReEval, true); 1979 } else { 1980 cstate.setCurRawAdj(cstate.getCurAdj()); 1981 cstate.setCurRawProcState(cstate.getCurProcState()); 1982 } 1983 1984 int clientAdj = cstate.getCurRawAdj(); 1985 int clientProcState = cstate.getCurRawProcState(); 1986 1987 final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP; 1988 1989 boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp() 1990 || clientProcState <= PROCESS_STATE_BOUND_TOP 1991 || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE 1992 && !cstate.isBackgroundRestricted()); 1993 1994 if (client.mOptRecord.shouldNotFreeze()) { 1995 // Propagate the shouldNotFreeze flag down the bindings. 1996 app.mOptRecord.setShouldNotFreeze(true); 1997 } 1998 1999 if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) { 2000 if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { 2001 capability |= cstate.getCurCapability(); 2002 } 2003 2004 // If an app has network capability by default 2005 // (by having procstate <= BFGS), then the apps it binds to will get 2006 // elevated to a high enough procstate anyway to get network unless they 2007 // request otherwise, so don't propagate the network capability by default 2008 // in this case unless they explicitly request it. 2009 if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) { 2010 if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { 2011 if ((cr.flags & Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS) 2012 != 0) { 2013 capability |= PROCESS_CAPABILITY_NETWORK; 2014 } 2015 } else { 2016 capability |= PROCESS_CAPABILITY_NETWORK; 2017 } 2018 } 2019 2020 if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) { 2021 continue; 2022 } 2023 2024 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { 2025 // If the other app is cached for any reason, for purposes here 2026 // we are going to consider it empty. The specific cached state 2027 // doesn't propagate except under certain conditions. 2028 clientProcState = PROCESS_STATE_CACHED_EMPTY; 2029 } 2030 String adjType = null; 2031 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { 2032 // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen. 2033 if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) { 2034 app.mOptRecord.setShouldNotFreeze(true); 2035 } 2036 // Not doing bind OOM management, so treat 2037 // this guy more like a started service. 2038 if (state.hasShownUi() && !state.getCachedIsHomeProcess()) { 2039 // If this process has shown some UI, let it immediately 2040 // go to the LRU list because it may be pretty heavy with 2041 // UI stuff. We'll tag it with a label just to help 2042 // debug and understand what is going on. 2043 if (adj > clientAdj) { 2044 adjType = "cch-bound-ui-services"; 2045 } 2046 state.setCached(false); 2047 clientAdj = adj; 2048 clientProcState = procState; 2049 } else { 2050 if (now >= (s.lastActivity 2051 + mConstants.MAX_SERVICE_INACTIVITY)) { 2052 // This service has not seen activity within 2053 // recent memory, so allow it to drop to the 2054 // LRU list if there is no other reason to keep 2055 // it around. We'll also tag it with a label just 2056 // to help debug and undertand what is going on. 2057 if (adj > clientAdj) { 2058 adjType = "cch-bound-services"; 2059 } 2060 clientAdj = adj; 2061 } 2062 } 2063 } 2064 if (adj > clientAdj) { 2065 // If this process has recently shown UI, and 2066 // the process that is binding to it is less 2067 // important than being visible, then we don't 2068 // care about the binding as much as we care 2069 // about letting this process get into the LRU 2070 // list to be killed and restarted if needed for 2071 // memory. 2072 if (state.hasShownUi() && !state.getCachedIsHomeProcess() 2073 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { 2074 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) { 2075 adjType = "cch-bound-ui-services"; 2076 } 2077 } else { 2078 int newAdj; 2079 if ((cr.flags&(Context.BIND_ABOVE_CLIENT 2080 |Context.BIND_IMPORTANT)) != 0) { 2081 if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) { 2082 newAdj = clientAdj; 2083 } else { 2084 // make this service persistent 2085 newAdj = ProcessList.PERSISTENT_SERVICE_ADJ; 2086 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2087 procState = ActivityManager.PROCESS_STATE_PERSISTENT; 2088 cr.trackProcState(procState, mAdjSeq); 2089 trackedProcState = true; 2090 } 2091 } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0 2092 && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ 2093 && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { 2094 newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ; 2095 } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0 2096 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ 2097 && adj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) { 2098 newAdj = ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ; 2099 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0 2100 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ 2101 && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) { 2102 newAdj = ProcessList.PERCEPTIBLE_APP_ADJ; 2103 } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) { 2104 newAdj = clientAdj; 2105 } else if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE) 2106 && clientAdj <= ProcessList.VISIBLE_APP_ADJ 2107 && adj > ProcessList.VISIBLE_APP_ADJ) { 2108 newAdj = ProcessList.VISIBLE_APP_ADJ; 2109 } else { 2110 if (adj > ProcessList.VISIBLE_APP_ADJ) { 2111 // TODO: Is this too limiting for apps bound from TOP? 2112 newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ); 2113 } else { 2114 newAdj = adj; 2115 } 2116 } 2117 if (!cstate.isCached()) { 2118 state.setCached(false); 2119 } 2120 if (adj > newAdj) { 2121 adj = newAdj; 2122 state.setCurRawAdj(adj); 2123 adjType = "service"; 2124 } 2125 } 2126 } 2127 if ((cr.flags & (Context.BIND_NOT_FOREGROUND 2128 | Context.BIND_IMPORTANT_BACKGROUND)) == 0) { 2129 // This will treat important bound services identically to 2130 // the top app, which may behave differently than generic 2131 // foreground work. 2132 final int curSchedGroup = cstate.getCurrentSchedulingGroup(); 2133 if (curSchedGroup > schedGroup) { 2134 if ((cr.flags&Context.BIND_IMPORTANT) != 0) { 2135 schedGroup = curSchedGroup; 2136 } else { 2137 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2138 } 2139 } 2140 if (clientProcState < PROCESS_STATE_TOP) { 2141 // Special handling for above-top states (persistent 2142 // processes). These should not bring the current process 2143 // into the top state, since they are not on top. Instead 2144 // give them the best bound state after that. 2145 if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) { 2146 clientProcState = PROCESS_STATE_FOREGROUND_SERVICE; 2147 } else if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) { 2148 clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 2149 } else if (mService.mWakefulness.get() 2150 == PowerManagerInternal.WAKEFULNESS_AWAKE 2151 && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) 2152 != 0) { 2153 clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 2154 } else { 2155 clientProcState = 2156 PROCESS_STATE_IMPORTANT_FOREGROUND; 2157 } 2158 } else if (clientProcState == PROCESS_STATE_TOP) { 2159 // Go at most to BOUND_TOP, unless requested to elevate 2160 // to client's state. 2161 clientProcState = PROCESS_STATE_BOUND_TOP; 2162 final boolean enabled = cstate.getCachedCompatChange( 2163 CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY); 2164 if (enabled) { 2165 if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { 2166 // TOP process passes all capabilities to the service. 2167 capability |= cstate.getCurCapability(); 2168 } else { 2169 // TOP process passes no capability to the service. 2170 } 2171 } else { 2172 // TOP process passes all capabilities to the service. 2173 capability |= cstate.getCurCapability(); 2174 } 2175 } 2176 } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) { 2177 if (clientProcState < 2178 PROCESS_STATE_TRANSIENT_BACKGROUND) { 2179 clientProcState = 2180 PROCESS_STATE_TRANSIENT_BACKGROUND; 2181 } 2182 } else { 2183 if (clientProcState < 2184 PROCESS_STATE_IMPORTANT_BACKGROUND) { 2185 clientProcState = 2186 PROCESS_STATE_IMPORTANT_BACKGROUND; 2187 } 2188 } 2189 2190 if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP 2191 && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 2192 && clientIsSystem) { 2193 schedGroup = ProcessList.SCHED_GROUP_TOP_APP; 2194 scheduleLikeTopApp = true; 2195 } 2196 2197 if (!trackedProcState) { 2198 cr.trackProcState(clientProcState, mAdjSeq); 2199 } 2200 2201 if (procState > clientProcState) { 2202 procState = clientProcState; 2203 state.setCurRawProcState(procState); 2204 if (adjType == null) { 2205 adjType = "service"; 2206 } 2207 } 2208 if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND 2209 && (cr.flags & Context.BIND_SHOWING_UI) != 0) { 2210 app.setPendingUiClean(true); 2211 } 2212 if (adjType != null) { 2213 state.setAdjType(adjType); 2214 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo 2215 .REASON_SERVICE_IN_USE); 2216 state.setAdjSource(cr.binding.client); 2217 state.setAdjSourceProcState(clientProcState); 2218 state.setAdjTarget(s.instanceName); 2219 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2220 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType 2221 + ": " + app + ", due to " + cr.binding.client 2222 + " adj=" + adj + " procState=" 2223 + ProcessList.makeProcStateString(procState)); 2224 } 2225 } 2226 } else { // BIND_WAIVE_PRIORITY == true 2227 // BIND_WAIVE_PRIORITY bindings are special when it comes to the 2228 // freezer. Processes bound via WPRI are expected to be running, 2229 // but they are not promoted in the LRU list to keep them out of 2230 // cached. As a result, they can freeze based on oom_adj alone. 2231 // Normally, bindToDeath would fire when a cached app would die 2232 // in the background, but nothing will fire when a running process 2233 // pings a frozen process. Accordingly, any cached app that is 2234 // bound by an unfrozen app via a WPRI binding has to remain 2235 // unfrozen. 2236 if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) { 2237 app.mOptRecord.setShouldNotFreeze(true); 2238 } 2239 } 2240 if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { 2241 psr.setTreatLikeActivity(true); 2242 } 2243 final ActivityServiceConnectionsHolder a = cr.activity; 2244 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) { 2245 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ 2246 && a.isActivityVisible()) { 2247 adj = ProcessList.FOREGROUND_APP_ADJ; 2248 state.setCurRawAdj(adj); 2249 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { 2250 if ((cr.flags&Context.BIND_IMPORTANT) != 0) { 2251 schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND; 2252 } else { 2253 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2254 } 2255 } 2256 state.setCached(false); 2257 state.setAdjType("service"); 2258 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo 2259 .REASON_SERVICE_IN_USE); 2260 state.setAdjSource(a); 2261 state.setAdjSourceProcState(procState); 2262 state.setAdjTarget(s.instanceName); 2263 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2264 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2265 "Raise to service w/activity: " + app); 2266 } 2267 } 2268 } 2269 } 2270 } 2271 } 2272 2273 final ProcessProviderRecord ppr = app.mProviders; 2274 for (int provi = ppr.numberOfProviders() - 1; 2275 provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ 2276 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND 2277 || procState > PROCESS_STATE_TOP); 2278 provi--) { 2279 ContentProviderRecord cpr = ppr.getProviderAt(provi); 2280 for (int i = cpr.connections.size() - 1; 2281 i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ 2282 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND 2283 || procState > PROCESS_STATE_TOP); 2284 i--) { 2285 ContentProviderConnection conn = cpr.connections.get(i); 2286 ProcessRecord client = conn.client; 2287 final ProcessStateRecord cstate = client.mState; 2288 if (client == app) { 2289 // Being our own client is not interesting. 2290 continue; 2291 } 2292 if (computeClients) { 2293 computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true); 2294 } else { 2295 cstate.setCurRawAdj(cstate.getCurAdj()); 2296 cstate.setCurRawProcState(cstate.getCurProcState()); 2297 } 2298 2299 if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) { 2300 continue; 2301 } 2302 2303 int clientAdj = cstate.getCurRawAdj(); 2304 int clientProcState = cstate.getCurRawProcState(); 2305 2306 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { 2307 // If the other app is cached for any reason, for purposes here 2308 // we are going to consider it empty. 2309 clientProcState = PROCESS_STATE_CACHED_EMPTY; 2310 } 2311 if (client.mOptRecord.shouldNotFreeze()) { 2312 // Propagate the shouldNotFreeze flag down the bindings. 2313 app.mOptRecord.setShouldNotFreeze(true); 2314 } 2315 2316 boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp() 2317 || clientProcState <= PROCESS_STATE_BOUND_TOP 2318 || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE 2319 && !cstate.isBackgroundRestricted()); 2320 2321 String adjType = null; 2322 if (adj > clientAdj) { 2323 if (state.hasShownUi() && !state.getCachedIsHomeProcess() 2324 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { 2325 adjType = "cch-ui-provider"; 2326 } else { 2327 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ 2328 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ; 2329 state.setCurRawAdj(adj); 2330 adjType = "provider"; 2331 } 2332 state.setCached(state.isCached() & cstate.isCached()); 2333 } 2334 2335 if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) { 2336 if (adjType == null) { 2337 adjType = "provider"; 2338 } 2339 if (clientProcState == PROCESS_STATE_TOP) { 2340 clientProcState = PROCESS_STATE_BOUND_TOP; 2341 } else { 2342 clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 2343 } 2344 } 2345 2346 conn.trackProcState(clientProcState, mAdjSeq); 2347 if (procState > clientProcState) { 2348 procState = clientProcState; 2349 state.setCurRawProcState(procState); 2350 } 2351 if (cstate.getCurrentSchedulingGroup() > schedGroup) { 2352 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2353 } 2354 if (adjType != null) { 2355 state.setAdjType(adjType); 2356 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo 2357 .REASON_PROVIDER_IN_USE); 2358 state.setAdjSource(client); 2359 state.setAdjSourceProcState(clientProcState); 2360 state.setAdjTarget(cpr.name); 2361 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2362 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType 2363 + ": " + app + ", due to " + client 2364 + " adj=" + adj + " procState=" 2365 + ProcessList.makeProcStateString(procState)); 2366 } 2367 } 2368 } 2369 // If the provider has external (non-framework) process 2370 // dependencies, ensure that its adjustment is at least 2371 // FOREGROUND_APP_ADJ. 2372 if (cpr.hasExternalProcessHandles()) { 2373 if (adj > ProcessList.FOREGROUND_APP_ADJ) { 2374 adj = ProcessList.FOREGROUND_APP_ADJ; 2375 state.setCurRawAdj(adj); 2376 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2377 state.setCached(false); 2378 state.setAdjType("ext-provider"); 2379 state.setAdjTarget(cpr.name); 2380 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2381 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2382 "Raise adj to external provider: " + app); 2383 } 2384 } 2385 if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) { 2386 procState = PROCESS_STATE_IMPORTANT_FOREGROUND; 2387 state.setCurRawProcState(procState); 2388 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2389 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2390 "Raise procstate to external provider: " + app); 2391 } 2392 } 2393 } 2394 } 2395 2396 if (ppr.getLastProviderTime() > 0 2397 && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) { 2398 if (adj > ProcessList.PREVIOUS_APP_ADJ) { 2399 adj = ProcessList.PREVIOUS_APP_ADJ; 2400 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; 2401 state.setCached(false); 2402 state.setAdjType("recent-provider"); 2403 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2404 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2405 "Raise adj to recent provider: " + app); 2406 } 2407 } 2408 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 2409 procState = PROCESS_STATE_LAST_ACTIVITY; 2410 state.setAdjType("recent-provider"); 2411 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2412 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2413 "Raise procstate to recent provider: " + app); 2414 } 2415 } 2416 } 2417 2418 if (procState >= PROCESS_STATE_CACHED_EMPTY) { 2419 if (psr.hasClientActivities()) { 2420 // This is a cached process, but with client activities. Mark it so. 2421 procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT; 2422 state.setAdjType("cch-client-act"); 2423 } else if (psr.isTreatedLikeActivity()) { 2424 // This is a cached process, but somebody wants us to treat it like it has 2425 // an activity, okay! 2426 procState = PROCESS_STATE_CACHED_ACTIVITY; 2427 state.setAdjType("cch-as-act"); 2428 } 2429 } 2430 2431 if (adj == ProcessList.SERVICE_ADJ) { 2432 if (doingAll && !cycleReEval) { 2433 state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3)); 2434 mNewNumServiceProcs++; 2435 if (!state.isServiceB()) { 2436 // This service isn't far enough down on the LRU list to 2437 // normally be a B service, but if we are low on RAM and it 2438 // is large we want to force it down since we would prefer to 2439 // keep launcher over it. 2440 if (!mService.mAppProfiler.isLastMemoryLevelNormal() 2441 && app.mProfile.getLastPss() 2442 >= mProcessList.getCachedRestoreThresholdKb()) { 2443 state.setServiceHighRam(true); 2444 state.setServiceB(true); 2445 //Slog.i(TAG, "ADJ " + app + " high ram!"); 2446 } else { 2447 mNewNumAServiceProcs++; 2448 //Slog.i(TAG, "ADJ " + app + " not high ram!"); 2449 } 2450 } else { 2451 state.setServiceHighRam(false); 2452 } 2453 } 2454 if (state.isServiceB()) { 2455 adj = ProcessList.SERVICE_B_ADJ; 2456 } 2457 } 2458 2459 state.setCurRawAdj(adj); 2460 2461 if (adj > state.getMaxAdj()) { 2462 adj = state.getMaxAdj(); 2463 if (adj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { 2464 schedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2465 } 2466 } 2467 2468 // Put bound foreground services in a special sched group for additional 2469 // restrictions on screen off 2470 if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE 2471 && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE 2472 && !scheduleLikeTopApp) { 2473 if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) { 2474 schedGroup = ProcessList.SCHED_GROUP_RESTRICTED; 2475 } 2476 } 2477 2478 // apply capability from FGS. 2479 if (psr.hasForegroundServices()) { 2480 capability |= capabilityFromFGS; 2481 } 2482 2483 capability |= getDefaultCapability(psr, procState); 2484 2485 // Do final modification to adj. Everything we do between here and applying 2486 // the final setAdj must be done in this function, because we will also use 2487 // it when computing the final cached adj later. Note that we don't need to 2488 // worry about this for max adj above, since max adj will always be used to 2489 // keep it out of the cached vaues. 2490 state.setCurAdj(psr.modifyRawOomAdj(adj)); 2491 state.setCurCapability(capability); 2492 state.setCurrentSchedulingGroup(schedGroup); 2493 state.setCurProcState(procState); 2494 state.setCurRawProcState(procState); 2495 state.updateLastInvisibleTime(hasVisibleActivities); 2496 state.setHasForegroundActivities(foregroundActivities); 2497 state.setCompletedAdjSeq(mAdjSeq); 2498 state.setCurBoundByNonBgRestrictedApp(boundByNonBgRestricted); 2499 2500 // if curAdj or curProcState improved, then this process was promoted 2501 return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState 2502 || state.getCurCapability() != prevCapability; 2503 } 2504 2505 private int getDefaultCapability(ProcessServiceRecord psr, int procState) { 2506 switch (procState) { 2507 case PROCESS_STATE_PERSISTENT: 2508 case PROCESS_STATE_PERSISTENT_UI: 2509 case PROCESS_STATE_TOP: 2510 return PROCESS_CAPABILITY_ALL; 2511 case PROCESS_STATE_BOUND_TOP: 2512 return PROCESS_CAPABILITY_NETWORK; 2513 case PROCESS_STATE_FOREGROUND_SERVICE: 2514 if (psr.hasForegroundServices()) { 2515 // Capability from FGS are conditional depending on foreground service type in 2516 // manifest file and the mAllowWhileInUsePermissionInFgs flag. 2517 return PROCESS_CAPABILITY_NETWORK; 2518 } else { 2519 // process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client. 2520 // the implicit capability could be removed in the future, client should use 2521 // BIND_INCLUDE_CAPABILITY flag. 2522 return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK; 2523 } 2524 case PROCESS_STATE_BOUND_FOREGROUND_SERVICE: 2525 return PROCESS_CAPABILITY_NETWORK; 2526 default: 2527 return PROCESS_CAPABILITY_NONE; 2528 } 2529 } 2530 2531 /** 2532 * Checks if for the given app and client, there's a cycle that should skip over the client 2533 * for now or use partial values to evaluate the effect of the client binding. 2534 * @param app 2535 * @param client 2536 * @param procState procstate evaluated so far for this app 2537 * @param adj oom_adj evaluated so far for this app 2538 * @param cycleReEval whether we're currently re-evaluating due to a cycle, and not the first 2539 * evaluation. 2540 * @return whether to skip using the client connection at this time 2541 */ 2542 private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessStateRecord client, 2543 int procState, int adj, boolean cycleReEval) { 2544 if (client.containsCycle()) { 2545 // We've detected a cycle. We should retry computeOomAdjLSP later in 2546 // case a later-checked connection from a client would raise its 2547 // priority legitimately. 2548 app.mState.setContainsCycle(true); 2549 mProcessesInCycle.add(app); 2550 // If the client has not been completely evaluated, check if it's worth 2551 // using the partial values. 2552 if (client.getCompletedAdjSeq() < mAdjSeq) { 2553 if (cycleReEval) { 2554 // If the partial values are no better, skip until the next 2555 // attempt 2556 if (client.getCurRawProcState() >= procState 2557 && client.getCurRawAdj() >= adj) { 2558 return true; 2559 } 2560 // Else use the client's partial procstate and adj to adjust the 2561 // effect of the binding 2562 } else { 2563 return true; 2564 } 2565 } 2566 } 2567 return false; 2568 } 2569 2570 /** Inform the oomadj observer of changes to oomadj. Used by tests. */ 2571 @GuardedBy("mService") 2572 private void reportOomAdjMessageLocked(String tag, String msg) { 2573 Slog.d(tag, msg); 2574 synchronized (mService.mOomAdjObserverLock) { 2575 if (mService.mCurOomAdjObserver != null) { 2576 mService.mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg) 2577 .sendToTarget(); 2578 } 2579 } 2580 } 2581 2582 void onWakefulnessChanged(int wakefulness) { 2583 mCachedAppOptimizer.onWakefulnessChanged(wakefulness); 2584 } 2585 2586 /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */ 2587 @GuardedBy({"mService", "mProcLock"}) 2588 private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, 2589 long nowElapsed, String oomAdjReson) { 2590 boolean success = true; 2591 final ProcessStateRecord state = app.mState; 2592 final UidRecord uidRec = app.getUidRecord(); 2593 2594 if (state.getCurRawAdj() != state.getSetRawAdj()) { 2595 state.setSetRawAdj(state.getCurRawAdj()); 2596 } 2597 2598 int changes = 0; 2599 2600 // don't compact during bootup 2601 if (mCachedAppOptimizer.useCompaction() && mService.mBooted) { 2602 // Cached and prev/home compaction 2603 // reminder: here, setAdj is previous state, curAdj is upcoming state 2604 if (state.getCurAdj() != state.getSetAdj()) { 2605 mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app); 2606 } else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE) { 2607 // See if we can compact persistent and bfgs services now that screen is off 2608 if (state.getSetAdj() < ProcessList.FOREGROUND_APP_ADJ 2609 && !state.isRunningRemoteAnimation() 2610 // Because these can fire independent of oom_adj/procstate changes, we need 2611 // to throttle the actual dispatch of these requests in addition to the 2612 // processing of the requests. As a result, there is throttling both here 2613 // and in CachedAppOptimizer. 2614 && mCachedAppOptimizer.shouldCompactPersistent(app, now)) { 2615 mCachedAppOptimizer.compactAppPersistent(app); 2616 } else if (state.getCurProcState() 2617 == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE 2618 && mCachedAppOptimizer.shouldCompactBFGS(app, now)) { 2619 mCachedAppOptimizer.compactAppBfgs(app); 2620 } 2621 } 2622 } 2623 2624 if (state.getCurAdj() != state.getSetAdj()) { 2625 ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj()); 2626 if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { 2627 String msg = "Set " + app.getPid() + " " + app.processName + " adj " 2628 + state.getCurAdj() + ": " + state.getAdjType(); 2629 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); 2630 } 2631 state.setSetAdj(state.getCurAdj()); 2632 if (uidRec != null) { 2633 uidRec.noteProcAdjChanged(); 2634 } 2635 state.setVerifiedAdj(ProcessList.INVALID_ADJ); 2636 } 2637 2638 final int curSchedGroup = state.getCurrentSchedulingGroup(); 2639 if (state.getSetSchedGroup() != curSchedGroup) { 2640 int oldSchedGroup = state.getSetSchedGroup(); 2641 state.setSetSchedGroup(curSchedGroup); 2642 if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) { 2643 String msg = "Setting sched group of " + app.processName 2644 + " to " + curSchedGroup + ": " + state.getAdjType(); 2645 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); 2646 } 2647 if (app.getWaitingToKill() != null && app.mReceivers.numberOfCurReceivers() == 0 2648 && state.getSetSchedGroup() == ProcessList.SCHED_GROUP_BACKGROUND) { 2649 app.killLocked(app.getWaitingToKill(), ApplicationExitInfo.REASON_USER_REQUESTED, 2650 ApplicationExitInfo.SUBREASON_REMOVE_TASK, true); 2651 success = false; 2652 } else { 2653 int processGroup; 2654 switch (curSchedGroup) { 2655 case ProcessList.SCHED_GROUP_BACKGROUND: 2656 processGroup = THREAD_GROUP_BACKGROUND; 2657 break; 2658 case ProcessList.SCHED_GROUP_TOP_APP: 2659 case ProcessList.SCHED_GROUP_TOP_APP_BOUND: 2660 processGroup = THREAD_GROUP_TOP_APP; 2661 break; 2662 case ProcessList.SCHED_GROUP_RESTRICTED: 2663 processGroup = THREAD_GROUP_RESTRICTED; 2664 break; 2665 default: 2666 processGroup = THREAD_GROUP_DEFAULT; 2667 break; 2668 } 2669 mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage( 2670 0 /* unused */, app.getPid(), processGroup, app.processName)); 2671 try { 2672 final int renderThreadTid = app.getRenderThreadTid(); 2673 if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) { 2674 // do nothing if we already switched to RT 2675 if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) { 2676 app.getWindowProcessController().onTopProcChanged(); 2677 if (mService.mUseFifoUiScheduling) { 2678 // Switch UI pipeline for app to SCHED_FIFO 2679 state.setSavedPriority(Process.getThreadPriority(app.getPid())); 2680 mService.scheduleAsFifoPriority(app.getPid(), true); 2681 if (renderThreadTid != 0) { 2682 mService.scheduleAsFifoPriority(renderThreadTid, 2683 /* suppressLogs */true); 2684 if (DEBUG_OOM_ADJ) { 2685 Slog.d("UI_FIFO", "Set RenderThread (TID " + 2686 renderThreadTid + ") to FIFO"); 2687 } 2688 } else { 2689 if (DEBUG_OOM_ADJ) { 2690 Slog.d("UI_FIFO", "Not setting RenderThread TID"); 2691 } 2692 } 2693 } else { 2694 // Boost priority for top app UI and render threads 2695 setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST); 2696 if (renderThreadTid != 0) { 2697 try { 2698 setThreadPriority(renderThreadTid, 2699 THREAD_PRIORITY_TOP_APP_BOOST); 2700 } catch (IllegalArgumentException e) { 2701 // thread died, ignore 2702 } 2703 } 2704 } 2705 } 2706 } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP && 2707 curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) { 2708 app.getWindowProcessController().onTopProcChanged(); 2709 if (mService.mUseFifoUiScheduling) { 2710 try { 2711 // Reset UI pipeline to SCHED_OTHER 2712 setThreadScheduler(app.getPid(), SCHED_OTHER, 0); 2713 setThreadPriority(app.getPid(), state.getSavedPriority()); 2714 if (renderThreadTid != 0) { 2715 setThreadScheduler(renderThreadTid, 2716 SCHED_OTHER, 0); 2717 } 2718 } catch (IllegalArgumentException e) { 2719 Slog.w(TAG, 2720 "Failed to set scheduling policy, thread does not exist:\n" 2721 + e); 2722 } catch (SecurityException e) { 2723 Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e); 2724 } 2725 } else { 2726 // Reset priority for top app UI and render threads 2727 setThreadPriority(app.getPid(), 0); 2728 } 2729 2730 if (renderThreadTid != 0) { 2731 setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY); 2732 } 2733 } 2734 } catch (Exception e) { 2735 if (DEBUG_ALL) { 2736 Slog.w(TAG, "Failed setting thread priority of " + app.getPid(), e); 2737 } 2738 } 2739 } 2740 } 2741 if (state.hasRepForegroundActivities() != state.hasForegroundActivities()) { 2742 state.setRepForegroundActivities(state.hasForegroundActivities()); 2743 changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES; 2744 } 2745 2746 updateAppFreezeStateLSP(app, oomAdjReson); 2747 2748 if (state.getReportedProcState() != state.getCurProcState()) { 2749 state.setReportedProcState(state.getCurProcState()); 2750 if (app.getThread() != null) { 2751 try { 2752 if (false) { 2753 //RuntimeException h = new RuntimeException("here"); 2754 Slog.i(TAG, "Sending new process state " + state.getReportedProcState() 2755 + " to " + app /*, h*/); 2756 } 2757 app.getThread().setProcessState(state.getReportedProcState()); 2758 } catch (RemoteException e) { 2759 } 2760 } 2761 } 2762 boolean forceUpdatePssTime = false; 2763 if (state.getSetProcState() == PROCESS_STATE_NONEXISTENT 2764 || ProcessList.procStatesDifferForMem( 2765 state.getCurProcState(), state.getSetProcState())) { 2766 state.setLastStateTime(now); 2767 forceUpdatePssTime = true; 2768 if (DEBUG_PSS) { 2769 Slog.d(TAG_PSS, "Process state change from " 2770 + ProcessList.makeProcStateString(state.getSetProcState()) + " to " 2771 + ProcessList.makeProcStateString(state.getCurProcState()) + " next pss in " 2772 + (app.mProfile.getNextPssTime() - now) + ": " + app); 2773 } 2774 } 2775 synchronized (mService.mAppProfiler.mProfilerLock) { 2776 app.mProfile.updateProcState(app.mState); 2777 mService.mAppProfiler.updateNextPssTimeLPf( 2778 state.getCurProcState(), app.mProfile, now, forceUpdatePssTime); 2779 } 2780 if (state.getSetProcState() != state.getCurProcState()) { 2781 if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) { 2782 String msg = "Proc state change of " + app.processName 2783 + " to " + ProcessList.makeProcStateString(state.getCurProcState()) 2784 + " (" + state.getCurProcState() + ")" + ": " + state.getAdjType(); 2785 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); 2786 } 2787 boolean setImportant = state.getSetProcState() < PROCESS_STATE_SERVICE; 2788 boolean curImportant = state.getCurProcState() < PROCESS_STATE_SERVICE; 2789 if (setImportant && !curImportant) { 2790 // This app is no longer something we consider important enough to allow to use 2791 // arbitrary amounts of battery power. Note its current CPU time to later know to 2792 // kill it if it is not behaving well. 2793 state.setWhenUnimportant(now); 2794 app.mProfile.mLastCpuTime.set(0); 2795 } 2796 // Inform UsageStats of important process state change 2797 // Must be called before updating setProcState 2798 maybeUpdateUsageStatsLSP(app, nowElapsed); 2799 2800 maybeUpdateLastTopTime(state, now); 2801 2802 state.setSetProcState(state.getCurProcState()); 2803 if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) { 2804 state.setNotCachedSinceIdle(false); 2805 } 2806 if (!doingAll) { 2807 synchronized (mService.mProcessStats.mLock) { 2808 mService.setProcessTrackerStateLOSP(app, 2809 mService.mProcessStats.getMemFactorLocked()); 2810 } 2811 } else { 2812 state.setProcStateChanged(true); 2813 } 2814 } else if (state.hasReportedInteraction()) { 2815 final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( 2816 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); 2817 final long interactionThreshold = fgsInteractionChangeEnabled 2818 ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S 2819 : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S; 2820 // For apps that sit around for a long time in the interactive state, we need 2821 // to report this at least once a day so they don't go idle. 2822 if ((nowElapsed - state.getInteractionEventTime()) > interactionThreshold) { 2823 maybeUpdateUsageStatsLSP(app, nowElapsed); 2824 } 2825 } else { 2826 final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( 2827 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); 2828 final long interactionThreshold = fgsInteractionChangeEnabled 2829 ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S 2830 : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S; 2831 // For foreground services that sit around for a long time but are not interacted with. 2832 if ((nowElapsed - state.getFgInteractionTime()) > interactionThreshold) { 2833 maybeUpdateUsageStatsLSP(app, nowElapsed); 2834 } 2835 } 2836 2837 if (state.getCurCapability() != state.getSetCapability()) { 2838 changes |= ActivityManagerService.ProcessChangeItem.CHANGE_CAPABILITY; 2839 state.setSetCapability(state.getCurCapability()); 2840 } 2841 2842 final boolean curBoundByNonBgRestrictedApp = state.isCurBoundByNonBgRestrictedApp(); 2843 if (curBoundByNonBgRestrictedApp != state.isSetBoundByNonBgRestrictedApp()) { 2844 state.setSetBoundByNonBgRestrictedApp(curBoundByNonBgRestrictedApp); 2845 if (!curBoundByNonBgRestrictedApp && state.isBackgroundRestricted()) { 2846 mService.mHandler.post(() -> { 2847 synchronized (mService) { 2848 mService.mServices.stopAllForegroundServicesLocked( 2849 app.uid, app.info.packageName); 2850 } 2851 }); 2852 } 2853 } 2854 2855 if (changes != 0) { 2856 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, 2857 "Changes in " + app + ": " + changes); 2858 ActivityManagerService.ProcessChangeItem item = 2859 mProcessList.enqueueProcessChangeItemLocked(app.getPid(), app.info.uid); 2860 item.changes |= changes; 2861 item.foregroundActivities = state.hasRepForegroundActivities(); 2862 item.capability = state.getSetCapability(); 2863 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, 2864 "Item " + Integer.toHexString(System.identityHashCode(item)) 2865 + " " + app.toShortString() + ": changes=" + item.changes 2866 + " foreground=" + item.foregroundActivities 2867 + " type=" + state.getAdjType() + " source=" + state.getAdjSource() 2868 + " target=" + state.getAdjTarget() + " capability=" + item.capability); 2869 } 2870 2871 if (state.isCached() && !state.shouldNotKillOnBgRestrictedAndIdle()) { 2872 // It's eligible to get killed when in UID idle and bg restricted mode, 2873 // check if these states are just flipped. 2874 if (!state.isSetCached() || state.isSetNoKillOnBgRestrictedAndIdle()) { 2875 // Take the timestamp, we'd hold the killing for the background settle time 2876 // (for states debouncing to avoid from thrashing). 2877 state.setLastCanKillOnBgRestrictedAndIdleTime(nowElapsed); 2878 // Kick off the delayed checkup message if needed. 2879 if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) { 2880 mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, 2881 mConstants.mKillBgRestrictedAndCachedIdleSettleTimeMs); 2882 } 2883 } 2884 } 2885 state.setSetCached(state.isCached()); 2886 state.setSetNoKillOnBgRestrictedAndIdle(state.shouldNotKillOnBgRestrictedAndIdle()); 2887 2888 return success; 2889 } 2890 2891 @GuardedBy({"mService", "mProcLock"}) 2892 void setAttachingSchedGroupLSP(ProcessRecord app) { 2893 int initialSchedGroup = ProcessList.SCHED_GROUP_DEFAULT; 2894 final ProcessStateRecord state = app.mState; 2895 // If the process has been marked as foreground, it is starting as the top app (with 2896 // Zygote#START_AS_TOP_APP_ARG), so boost the thread priority of its default UI thread. 2897 if (state.hasForegroundActivities()) { 2898 try { 2899 // The priority must be the same as how does {@link #applyOomAdjLSP} set for 2900 // {@link ProcessList.SCHED_GROUP_TOP_APP}. We don't check render thread because it 2901 // is not ready when attaching. 2902 app.getWindowProcessController().onTopProcChanged(); 2903 setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST); 2904 initialSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; 2905 } catch (Exception e) { 2906 Slog.w(TAG, "Failed to pre-set top priority to " + app + " " + e); 2907 } 2908 } 2909 2910 state.setSetSchedGroup(initialSchedGroup); 2911 state.setCurrentSchedulingGroup(initialSchedGroup); 2912 } 2913 2914 // ONLY used for unit testing in OomAdjusterTests.java 2915 @VisibleForTesting 2916 void maybeUpdateUsageStats(ProcessRecord app, long nowElapsed) { 2917 synchronized (mService) { 2918 synchronized (mProcLock) { 2919 maybeUpdateUsageStatsLSP(app, nowElapsed); 2920 } 2921 } 2922 } 2923 2924 @GuardedBy({"mService", "mProcLock"}) 2925 private void maybeUpdateUsageStatsLSP(ProcessRecord app, long nowElapsed) { 2926 final ProcessStateRecord state = app.mState; 2927 if (DEBUG_USAGE_STATS) { 2928 Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList()) 2929 + "] state changes: old = " + state.getSetProcState() + ", new = " 2930 + state.getCurProcState()); 2931 } 2932 if (mService.mUsageStatsService == null) { 2933 return; 2934 } 2935 final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( 2936 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); 2937 boolean isInteraction; 2938 // To avoid some abuse patterns, we are going to be careful about what we consider 2939 // to be an app interaction. Being the top activity doesn't count while the display 2940 // is sleeping, nor do short foreground services. 2941 if (ActivityManager.isProcStateConsideredInteraction(state.getCurProcState())) { 2942 isInteraction = true; 2943 state.setFgInteractionTime(0); 2944 } else if (state.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) { 2945 if (state.getFgInteractionTime() == 0) { 2946 state.setFgInteractionTime(nowElapsed); 2947 isInteraction = false; 2948 } else { 2949 final long interactionTime = fgsInteractionChangeEnabled 2950 ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S 2951 : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S; 2952 isInteraction = nowElapsed > state.getFgInteractionTime() + interactionTime; 2953 } 2954 } else { 2955 isInteraction = 2956 state.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND; 2957 state.setFgInteractionTime(0); 2958 } 2959 final long interactionThreshold = fgsInteractionChangeEnabled 2960 ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S 2961 : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S; 2962 if (isInteraction 2963 && (!state.hasReportedInteraction() 2964 || (nowElapsed - state.getInteractionEventTime()) > interactionThreshold)) { 2965 state.setInteractionEventTime(nowElapsed); 2966 String[] packages = app.getPackageList(); 2967 if (packages != null) { 2968 for (int i = 0; i < packages.length; i++) { 2969 mService.mUsageStatsService.reportEvent(packages[i], app.userId, 2970 UsageEvents.Event.SYSTEM_INTERACTION); 2971 } 2972 } 2973 } 2974 state.setReportedInteraction(isInteraction); 2975 if (!isInteraction) { 2976 state.setInteractionEventTime(0); 2977 } 2978 } 2979 2980 private void maybeUpdateLastTopTime(ProcessStateRecord state, long nowUptime) { 2981 if (state.getSetProcState() <= PROCESS_STATE_TOP 2982 && state.getCurProcState() > PROCESS_STATE_TOP) { 2983 state.setLastTopTime(nowUptime); 2984 } 2985 } 2986 2987 /** 2988 * Look for recently inactive apps and mark them idle after a grace period. If idled, stop 2989 * any background services and inform listeners. 2990 */ 2991 @GuardedBy("mService") 2992 void idleUidsLocked() { 2993 final int N = mActiveUids.size(); 2994 if (N <= 0) { 2995 return; 2996 } 2997 final long nowElapsed = SystemClock.elapsedRealtime(); 2998 final long maxBgTime = nowElapsed - mConstants.BACKGROUND_SETTLE_TIME; 2999 long nextTime = 0; 3000 if (mLocalPowerManager != null) { 3001 mLocalPowerManager.startUidChanges(); 3002 } 3003 for (int i = N - 1; i >= 0; i--) { 3004 final UidRecord uidRec = mActiveUids.valueAt(i); 3005 final long bgTime = uidRec.getLastBackgroundTime(); 3006 if (bgTime > 0 && !uidRec.isIdle()) { 3007 if (bgTime <= maxBgTime) { 3008 EventLogTags.writeAmUidIdle(uidRec.getUid()); 3009 synchronized (mProcLock) { 3010 uidRec.setIdle(true); 3011 uidRec.setSetIdle(true); 3012 } 3013 mService.doStopUidLocked(uidRec.getUid(), uidRec); 3014 } else { 3015 if (nextTime == 0 || nextTime > bgTime) { 3016 nextTime = bgTime; 3017 } 3018 } 3019 } 3020 } 3021 if (mLocalPowerManager != null) { 3022 mLocalPowerManager.finishUidChanges(); 3023 } 3024 // Also check if there are any apps in cached and background restricted mode, 3025 // if so, kill it if it's been there long enough, or kick off a msg to check 3026 // it later. 3027 if (mService.mConstants.mKillBgRestrictedAndCachedIdle) { 3028 final ArraySet<ProcessRecord> apps = mProcessList.mAppsInBackgroundRestricted; 3029 for (int i = 0, size = apps.size(); i < size; i++) { 3030 // Check to see if needs to be killed. 3031 final long bgTime = mProcessList.killAppIfBgRestrictedAndCachedIdleLocked( 3032 apps.valueAt(i), nowElapsed) - mConstants.BACKGROUND_SETTLE_TIME; 3033 if (bgTime > 0 && (nextTime == 0 || nextTime > bgTime)) { 3034 nextTime = bgTime; 3035 } 3036 } 3037 } 3038 if (nextTime > 0) { 3039 mService.mHandler.removeMessages(IDLE_UIDS_MSG); 3040 mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, 3041 nextTime + mConstants.BACKGROUND_SETTLE_TIME - nowElapsed); 3042 } 3043 } 3044 3045 @GuardedBy({"mService", "mProcLock"}) 3046 void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) { 3047 boolean changed = false; 3048 for (int i = mActiveUids.size() - 1; i >= 0; i--) { 3049 final UidRecord uidRec = mActiveUids.valueAt(i); 3050 if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) { 3051 uidRec.setCurAllowListed(onAllowlist); 3052 changed = true; 3053 } 3054 } 3055 if (changed) { 3056 updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST); 3057 } 3058 } 3059 3060 @GuardedBy({"mService", "mProcLock"}) 3061 void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) { 3062 boolean changed = false; 3063 final UidRecord uidRec = mActiveUids.get(uid); 3064 if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) { 3065 uidRec.setCurAllowListed(onAllowlist); 3066 updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST); 3067 } 3068 } 3069 3070 @GuardedBy("mService") 3071 void dumpProcessListVariablesLocked(ProtoOutputStream proto) { 3072 proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq); 3073 proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.getLruSeqLOSP()); 3074 proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS, 3075 mNumNonCachedProcs); 3076 proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs); 3077 proto.write(ActivityManagerServiceDumpProcessesProto.NEW_NUM_SERVICE_PROCS, 3078 mNewNumServiceProcs); 3079 3080 } 3081 3082 @GuardedBy("mService") 3083 void dumpSequenceNumbersLocked(PrintWriter pw) { 3084 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.getLruSeqLOSP()); 3085 } 3086 3087 @GuardedBy("mService") 3088 void dumpProcCountsLocked(PrintWriter pw) { 3089 pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs 3090 + " (" + mProcessList.getLruSizeLOSP() + " total)" 3091 + " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs 3092 + " mNumServiceProcs=" + mNumServiceProcs 3093 + " mNewNumServiceProcs=" + mNewNumServiceProcs); 3094 } 3095 3096 @GuardedBy("mProcLock") 3097 void dumpCachedAppOptimizerSettings(PrintWriter pw) { 3098 mCachedAppOptimizer.dump(pw); 3099 } 3100 3101 @GuardedBy("mService") 3102 void dumpCacheOomRankerSettings(PrintWriter pw) { 3103 mCacheOomRanker.dump(pw); 3104 } 3105 3106 @GuardedBy({"mService", "mProcLock"}) 3107 private void updateAppFreezeStateLSP(ProcessRecord app, String oomAdjReason) { 3108 if (!mCachedAppOptimizer.useFreezer()) { 3109 return; 3110 } 3111 3112 if (app.mOptRecord.isFreezeExempt()) { 3113 return; 3114 } 3115 3116 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 3117 // if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze 3118 if (opt.isFrozen() && opt.shouldNotFreeze()) { 3119 mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason); 3120 return; 3121 } 3122 3123 final ProcessStateRecord state = app.mState; 3124 // Use current adjustment when freezing, set adjustment when unfreezing. 3125 if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen() 3126 && !opt.shouldNotFreeze()) { 3127 mCachedAppOptimizer.freezeAppAsyncLSP(app); 3128 } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) { 3129 mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason); 3130 } 3131 } 3132 } 3133