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_BFSL; 22 import static android.app.ActivityManager.PROCESS_CAPABILITY_CPU_TIME; 23 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL; 24 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; 25 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; 26 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; 27 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; 28 import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK; 29 import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK; 30 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 31 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; 32 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; 33 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; 34 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; 35 import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT; 36 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 37 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; 38 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; 39 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 40 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 41 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT; 42 import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI; 43 import static android.app.ActivityManager.PROCESS_STATE_SERVICE; 44 import static android.app.ActivityManager.PROCESS_STATE_TOP; 45 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; 46 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY; 47 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST; 48 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP; 49 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BIND_SERVICE; 50 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED; 51 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE; 52 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER; 53 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FOLLOW_UP; 54 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_GET_PROVIDER; 55 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_NONE; 56 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_BEGIN; 57 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END; 58 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION; 59 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER; 60 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK; 61 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE; 62 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHELL; 63 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT; 64 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER; 65 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_SERVICE; 66 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_STOP_SERVICE; 67 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SYSTEM_INIT; 68 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UID_IDLE; 69 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UI_VISIBILITY; 70 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UNBIND_SERVICE; 71 import static android.content.Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE; 72 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; 73 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; 74 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; 75 import static android.media.audio.Flags.roForegroundAudioControl; 76 import static android.os.Process.THREAD_GROUP_BACKGROUND; 77 import static android.os.Process.THREAD_GROUP_DEFAULT; 78 import static android.os.Process.THREAD_GROUP_FOREGROUND_WINDOW; 79 import static android.os.Process.THREAD_GROUP_RESTRICTED; 80 import static android.os.Process.THREAD_GROUP_TOP_APP; 81 import static android.os.Process.THREAD_PRIORITY_DISPLAY; 82 import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST; 83 84 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; 85 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP; 86 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; 87 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ; 88 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON; 89 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS; 90 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS; 91 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS; 92 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS; 93 import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG; 94 import static com.android.server.am.ActivityManagerService.FOLLOW_UP_OOMADJUSTER_UPDATE_MSG; 95 import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG; 96 import static com.android.server.am.ActivityManagerService.TAG_BACKUP; 97 import static com.android.server.am.ActivityManagerService.TAG_LRU; 98 import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ; 99 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS; 100 import static com.android.server.am.AppProfiler.TAG_PSS; 101 import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY; 102 import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY; 103 import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME; 104 import static com.android.server.am.ProcessList.BACKUP_APP_ADJ; 105 import static com.android.server.am.ProcessList.CACHED_APP_IMPORTANCE_LEVELS; 106 import static com.android.server.am.ProcessList.CACHED_APP_MAX_ADJ; 107 import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ; 108 import static com.android.server.am.ProcessList.FOREGROUND_APP_ADJ; 109 import static com.android.server.am.ProcessList.HEAVY_WEIGHT_APP_ADJ; 110 import static com.android.server.am.ProcessList.HOME_APP_ADJ; 111 import static com.android.server.am.ProcessList.INVALID_ADJ; 112 import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ; 113 import static com.android.server.am.ProcessList.PERCEPTIBLE_LOW_APP_ADJ; 114 import static com.android.server.am.ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ; 115 import static com.android.server.am.ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; 116 import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ; 117 import static com.android.server.am.ProcessList.PREVIOUS_APP_ADJ; 118 import static com.android.server.am.ProcessList.PREVIOUS_APP_MAX_ADJ; 119 import static com.android.server.am.ProcessList.SCHED_GROUP_BACKGROUND; 120 import static com.android.server.am.ProcessList.SCHED_GROUP_DEFAULT; 121 import static com.android.server.am.ProcessList.SCHED_GROUP_FOREGROUND_WINDOW; 122 import static com.android.server.am.ProcessList.SCHED_GROUP_RESTRICTED; 123 import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP; 124 import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP_BOUND; 125 import static com.android.server.am.ProcessList.SERVICE_ADJ; 126 import static com.android.server.am.ProcessList.SERVICE_B_ADJ; 127 import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS; 128 import static com.android.server.am.ProcessList.UNKNOWN_ADJ; 129 import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ; 130 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 131 132 import android.annotation.NonNull; 133 import android.annotation.Nullable; 134 import android.annotation.UserIdInt; 135 import android.app.ActivityManager; 136 import android.app.ActivityManagerInternal.OomAdjReason; 137 import android.app.ActivityThread; 138 import android.app.AppProtoEnums; 139 import android.app.ApplicationExitInfo; 140 import android.app.usage.UsageEvents; 141 import android.compat.annotation.ChangeId; 142 import android.compat.annotation.EnabledAfter; 143 import android.compat.annotation.EnabledSince; 144 import android.content.BroadcastReceiver; 145 import android.content.ComponentName; 146 import android.content.Context; 147 import android.content.Intent; 148 import android.content.IntentFilter; 149 import android.content.pm.ApplicationInfo; 150 import android.content.pm.ServiceInfo; 151 import android.net.NetworkPolicyManager; 152 import android.os.Handler; 153 import android.os.IBinder; 154 import android.os.PowerManagerInternal; 155 import android.os.Process; 156 import android.os.RemoteException; 157 import android.os.SystemClock; 158 import android.os.Trace; 159 import android.util.ArrayMap; 160 import android.util.ArraySet; 161 import android.util.Slog; 162 import android.util.proto.ProtoOutputStream; 163 164 import com.android.internal.annotations.CompositeRWLock; 165 import com.android.internal.annotations.GuardedBy; 166 import com.android.internal.annotations.VisibleForTesting; 167 import com.android.server.ServiceThread; 168 import com.android.server.am.PlatformCompatCache.CachedCompatChangeId; 169 import com.android.server.wm.ActivityServiceConnectionsHolder; 170 import com.android.server.wm.WindowProcessController; 171 172 import java.io.PrintWriter; 173 import java.util.ArrayDeque; 174 import java.util.ArrayList; 175 import java.util.Arrays; 176 import java.util.List; 177 178 /** 179 * All of the code required to compute proc states and oom_adj values. 180 */ 181 public class OomAdjuster { 182 static final String TAG = "OomAdjuster"; 183 oomAdjReasonToProto(@omAdjReason int oomReason)184 public static final int oomAdjReasonToProto(@OomAdjReason int oomReason) { 185 switch (oomReason) { 186 case OOM_ADJ_REASON_NONE: 187 return AppProtoEnums.OOM_ADJ_REASON_NONE; 188 case OOM_ADJ_REASON_ACTIVITY: 189 return AppProtoEnums.OOM_ADJ_REASON_ACTIVITY; 190 case OOM_ADJ_REASON_FINISH_RECEIVER: 191 return AppProtoEnums.OOM_ADJ_REASON_FINISH_RECEIVER; 192 case OOM_ADJ_REASON_START_RECEIVER: 193 return AppProtoEnums.OOM_ADJ_REASON_START_RECEIVER; 194 case OOM_ADJ_REASON_BIND_SERVICE: 195 return AppProtoEnums.OOM_ADJ_REASON_BIND_SERVICE; 196 case OOM_ADJ_REASON_UNBIND_SERVICE: 197 return AppProtoEnums.OOM_ADJ_REASON_UNBIND_SERVICE; 198 case OOM_ADJ_REASON_START_SERVICE: 199 return AppProtoEnums.OOM_ADJ_REASON_START_SERVICE; 200 case OOM_ADJ_REASON_GET_PROVIDER: 201 return AppProtoEnums.OOM_ADJ_REASON_GET_PROVIDER; 202 case OOM_ADJ_REASON_REMOVE_PROVIDER: 203 return AppProtoEnums.OOM_ADJ_REASON_REMOVE_PROVIDER; 204 case OOM_ADJ_REASON_UI_VISIBILITY: 205 return AppProtoEnums.OOM_ADJ_REASON_UI_VISIBILITY; 206 case OOM_ADJ_REASON_ALLOWLIST: 207 return AppProtoEnums.OOM_ADJ_REASON_ALLOWLIST; 208 case OOM_ADJ_REASON_PROCESS_BEGIN: 209 return AppProtoEnums.OOM_ADJ_REASON_PROCESS_BEGIN; 210 case OOM_ADJ_REASON_PROCESS_END: 211 return AppProtoEnums.OOM_ADJ_REASON_PROCESS_END; 212 case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT: 213 return AppProtoEnums.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT; 214 case OOM_ADJ_REASON_SYSTEM_INIT: 215 return AppProtoEnums.OOM_ADJ_REASON_SYSTEM_INIT; 216 case OOM_ADJ_REASON_BACKUP: 217 return AppProtoEnums.OOM_ADJ_REASON_BACKUP; 218 case OOM_ADJ_REASON_SHELL: 219 return AppProtoEnums.OOM_ADJ_REASON_SHELL; 220 case OOM_ADJ_REASON_REMOVE_TASK: 221 return AppProtoEnums.OOM_ADJ_REASON_REMOVE_TASK; 222 case OOM_ADJ_REASON_UID_IDLE: 223 return AppProtoEnums.OOM_ADJ_REASON_UID_IDLE; 224 case OOM_ADJ_REASON_STOP_SERVICE: 225 return AppProtoEnums.OOM_ADJ_REASON_STOP_SERVICE; 226 case OOM_ADJ_REASON_EXECUTING_SERVICE: 227 return AppProtoEnums.OOM_ADJ_REASON_EXECUTING_SERVICE; 228 case OOM_ADJ_REASON_RESTRICTION_CHANGE: 229 return AppProtoEnums.OOM_ADJ_REASON_RESTRICTION_CHANGE; 230 case OOM_ADJ_REASON_COMPONENT_DISABLED: 231 return AppProtoEnums.OOM_ADJ_REASON_COMPONENT_DISABLED; 232 case OOM_ADJ_REASON_FOLLOW_UP: 233 return AppProtoEnums.OOM_ADJ_REASON_FOLLOW_UP; 234 case OOM_ADJ_REASON_RECONFIGURATION: 235 return AppProtoEnums.OOM_ADJ_REASON_RECONFIGURATION; 236 default: 237 return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO; 238 } 239 } 240 oomAdjReasonToString(@omAdjReason int oomReason)241 public static final String oomAdjReasonToString(@OomAdjReason int oomReason) { 242 final String OOM_ADJ_REASON_METHOD = "updateOomAdj"; 243 switch (oomReason) { 244 case OOM_ADJ_REASON_NONE: 245 return OOM_ADJ_REASON_METHOD + "_meh"; 246 case OOM_ADJ_REASON_ACTIVITY: 247 return OOM_ADJ_REASON_METHOD + "_activityChange"; 248 case OOM_ADJ_REASON_FINISH_RECEIVER: 249 return OOM_ADJ_REASON_METHOD + "_finishReceiver"; 250 case OOM_ADJ_REASON_START_RECEIVER: 251 return OOM_ADJ_REASON_METHOD + "_startReceiver"; 252 case OOM_ADJ_REASON_BIND_SERVICE: 253 return OOM_ADJ_REASON_METHOD + "_bindService"; 254 case OOM_ADJ_REASON_UNBIND_SERVICE: 255 return OOM_ADJ_REASON_METHOD + "_unbindService"; 256 case OOM_ADJ_REASON_START_SERVICE: 257 return OOM_ADJ_REASON_METHOD + "_startService"; 258 case OOM_ADJ_REASON_GET_PROVIDER: 259 return OOM_ADJ_REASON_METHOD + "_getProvider"; 260 case OOM_ADJ_REASON_REMOVE_PROVIDER: 261 return OOM_ADJ_REASON_METHOD + "_removeProvider"; 262 case OOM_ADJ_REASON_UI_VISIBILITY: 263 return OOM_ADJ_REASON_METHOD + "_uiVisibility"; 264 case OOM_ADJ_REASON_ALLOWLIST: 265 return OOM_ADJ_REASON_METHOD + "_allowlistChange"; 266 case OOM_ADJ_REASON_PROCESS_BEGIN: 267 return OOM_ADJ_REASON_METHOD + "_processBegin"; 268 case OOM_ADJ_REASON_PROCESS_END: 269 return OOM_ADJ_REASON_METHOD + "_processEnd"; 270 case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT: 271 return OOM_ADJ_REASON_METHOD + "_shortFgs"; 272 case OOM_ADJ_REASON_SYSTEM_INIT: 273 return OOM_ADJ_REASON_METHOD + "_systemInit"; 274 case OOM_ADJ_REASON_BACKUP: 275 return OOM_ADJ_REASON_METHOD + "_backup"; 276 case OOM_ADJ_REASON_SHELL: 277 return OOM_ADJ_REASON_METHOD + "_shell"; 278 case OOM_ADJ_REASON_REMOVE_TASK: 279 return OOM_ADJ_REASON_METHOD + "_removeTask"; 280 case OOM_ADJ_REASON_UID_IDLE: 281 return OOM_ADJ_REASON_METHOD + "_uidIdle"; 282 case OOM_ADJ_REASON_STOP_SERVICE: 283 return OOM_ADJ_REASON_METHOD + "_stopService"; 284 case OOM_ADJ_REASON_EXECUTING_SERVICE: 285 return OOM_ADJ_REASON_METHOD + "_executingService"; 286 case OOM_ADJ_REASON_RESTRICTION_CHANGE: 287 return OOM_ADJ_REASON_METHOD + "_restrictionChange"; 288 case OOM_ADJ_REASON_COMPONENT_DISABLED: 289 return OOM_ADJ_REASON_METHOD + "_componentDisabled"; 290 case OOM_ADJ_REASON_FOLLOW_UP: 291 return OOM_ADJ_REASON_METHOD + "_followUp"; 292 case OOM_ADJ_REASON_RECONFIGURATION: 293 return OOM_ADJ_REASON_METHOD + "_reconfiguration"; 294 default: 295 return "_unknown"; 296 } 297 } 298 299 /** 300 * Flag {@link android.content.Context#BIND_INCLUDE_CAPABILITIES} is used 301 * to pass while-in-use capabilities from client process to bound service. In targetSdkVersion 302 * R and above, if client is a TOP activity, when this flag is present, bound service gets all 303 * while-in-use capabilities; when this flag is not present, bound service gets no while-in-use 304 * capability from client. 305 */ 306 @ChangeId 307 @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q) 308 static final long PROCESS_CAPABILITY_CHANGE_ID = 136274596L; 309 310 /** 311 * In targetSdkVersion R and above, foreground service has camera and microphone while-in-use 312 * capability only when the {@link android.R.attr#foregroundServiceType} is configured as 313 * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and 314 * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the 315 * manifest file. 316 * In targetSdkVersion below R, foreground service automatically have camera and microphone 317 * capabilities. 318 */ 319 @ChangeId 320 @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q) 321 static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L; 322 323 /** 324 * For apps targeting S+, this determines whether to use a shorter timeout before elevating the 325 * standby bucket to ACTIVE when apps start a foreground service. 326 */ 327 @ChangeId 328 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) 329 static final long USE_SHORT_FGS_USAGE_INTERACTION_TIME = 183972877L; 330 331 /** 332 * Service for optimizing resource usage from background apps. 333 */ 334 CachedAppOptimizer mCachedAppOptimizer; 335 336 /** 337 * Re-rank apps getting a cache oom adjustment from lru to weighted order 338 * based on weighted scores for LRU, PSS and cache use count. 339 */ 340 CacheOomRanker mCacheOomRanker; 341 342 ActivityManagerConstants mConstants; 343 344 final long[] mTmpLong = new long[3]; 345 346 /** 347 * Current sequence id for oom_adj computation traversal. 348 */ 349 int mAdjSeq = 0; 350 351 /** 352 * Keep track of the number of service processes we last found, to 353 * determine on the next iteration which should be B services. 354 */ 355 int mNumServiceProcs = 0; 356 int mNewNumAServiceProcs = 0; 357 int mNewNumServiceProcs = 0; 358 359 /** 360 * Keep track of the non-cached/empty process we last found, to help 361 * determine how to distribute cached/empty processes next time. 362 */ 363 int mNumNonCachedProcs = 0; 364 365 /** 366 * Keep track of the number of cached hidden procs, to balance oom adj 367 * distribution between those and empty procs. 368 */ 369 int mNumCachedHiddenProcs = 0; 370 371 /** Track all uids that have actively running processes. */ 372 @CompositeRWLock({"mService", "mProcLock"}) 373 ActiveUids mActiveUids; 374 375 /** 376 * The handler to execute {@link #setProcessGroup} (it may be heavy if the process has many 377 * threads) for reducing the time spent in {@link #applyOomAdjLSP}. 378 */ 379 private final Handler mProcessGroupHandler; 380 381 protected final int[] mTmpSchedGroup = new int[1]; 382 383 final ActivityManagerService mService; 384 final Injector mInjector; 385 final GlobalState mGlobalState; 386 final ProcessList mProcessList; 387 final ActivityManagerGlobalLock mProcLock; 388 389 private final int mNumSlots; 390 protected final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>(); 391 protected final ArrayList<ProcessRecord> mTmpProcessList2 = new ArrayList<ProcessRecord>(); 392 protected final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>(); 393 protected final ActiveUids mTmpUidRecords; 394 protected final ArrayDeque<ProcessRecord> mTmpQueue; 395 protected final ArraySet<ProcessRecord> mTmpProcessSet = new ArraySet<>(); 396 protected final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>(); 397 protected final ArraySet<ProcessRecord> mProcessesInCycle = new ArraySet<>(); 398 399 /** 400 * List of processes that we want to batch for LMKD to adjust their respective 401 * OOM scores. 402 */ 403 @GuardedBy("mService") 404 protected final ArrayList<ProcessRecord> mProcsToOomAdj = new ArrayList<ProcessRecord>(); 405 406 /** 407 * Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate 408 * could be called recursively because of the indirect calls during the update; 409 * however the oomAdjUpdate itself doesn't support recursion - in this case we'd 410 * have to queue up the new targets found during the update, and perform another 411 * round of oomAdjUpdate at the end of last update. 412 */ 413 @GuardedBy("mService") 414 private boolean mOomAdjUpdateOngoing = false; 415 416 /** 417 * Flag to mark if there is a pending full oomAdjUpdate. 418 */ 419 @GuardedBy("mService") 420 private boolean mPendingFullOomAdjUpdate = false; 421 422 /** 423 * Most recent reason string. We update it in sync with the trace. 424 */ 425 @OomAdjReason 426 protected int mLastReason; 427 428 private final OomAdjusterDebugLogger mLogger; 429 430 /** 431 * The process state of the current TOP app. 432 */ 433 @GuardedBy("mService") 434 protected int mProcessStateCurTop = PROCESS_STATE_TOP; 435 436 @GuardedBy("mService") 437 private final ArraySet<ProcessRecord> mFollowUpUpdateSet = new ArraySet<>(); 438 439 private static final long NO_FOLLOW_UP_TIME = Long.MAX_VALUE; 440 @GuardedBy("mService") 441 private long mNextFollowUpUpdateUptimeMs = NO_FOLLOW_UP_TIME; 442 443 /** 444 * The oom score a client needs to be to raise a service with UI out of cache. 445 */ 446 private static final int CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD = 447 Flags.raiseBoundUiServiceThreshold() ? SERVICE_ADJ : PERCEPTIBLE_APP_ADJ; 448 449 static final long PERCEPTIBLE_TASK_TIMEOUT_MILLIS = 5 * 60 * 1000; 450 451 @VisibleForTesting 452 public static class Injector { isChangeEnabled(@achedCompatChangeId int cachedCompatChangeId, ApplicationInfo app, boolean defaultValue)453 boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, 454 ApplicationInfo app, boolean defaultValue) { 455 return PlatformCompatCache.getInstance() 456 .isChangeEnabled(cachedCompatChangeId, app, defaultValue); 457 } 458 getUptimeMillis()459 long getUptimeMillis() { 460 return SystemClock.uptimeMillis(); 461 } 462 getElapsedRealtimeMillis()463 long getElapsedRealtimeMillis() { 464 return SystemClock.elapsedRealtime(); 465 } 466 batchSetOomAdj(ArrayList<ProcessRecord> procsToOomAdj)467 void batchSetOomAdj(ArrayList<ProcessRecord> procsToOomAdj) { 468 ProcessList.batchSetOomAdj(procsToOomAdj); 469 } 470 setOomAdj(int pid, int uid, int adj)471 void setOomAdj(int pid, int uid, int adj) { 472 ProcessList.setOomAdj(pid, uid, adj); 473 } 474 setThreadPriority(int tid, int priority)475 void setThreadPriority(int tid, int priority) { 476 Process.setThreadPriority(tid, priority); 477 } 478 } 479 480 // TODO(b/346822474): hook up global state usage. 481 interface GlobalState { 482 /** Is device's screen on. */ isAwake()483 boolean isAwake(); 484 485 /** What process is running a backup for a given userId. */ getBackupTarget(@serIdInt int userId)486 ProcessRecord getBackupTarget(@UserIdInt int userId); 487 488 /** Is memory level normal since last evaluation. */ isLastMemoryLevelNormal()489 boolean isLastMemoryLevelNormal(); 490 } 491 isChangeEnabled(@achedCompatChangeId int cachedCompatChangeId, ApplicationInfo app, boolean defaultValue)492 boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, 493 ApplicationInfo app, boolean defaultValue) { 494 return mInjector.isChangeEnabled(cachedCompatChangeId, app, defaultValue); 495 } 496 createAdjusterThread()497 static ServiceThread createAdjusterThread() { 498 // The process group is usually critical to the response time of foreground app, so the 499 // setter should apply it as soon as possible. 500 final ServiceThread adjusterThread = 501 new ServiceThread(TAG, THREAD_PRIORITY_TOP_APP_BOOST, false /* allowIo */); 502 adjusterThread.start(); 503 return adjusterThread; 504 } 505 OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, ServiceThread adjusterThread, GlobalState globalState, CachedAppOptimizer cachedAppOptimizer, Injector injector)506 OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, 507 ServiceThread adjusterThread, GlobalState globalState, 508 CachedAppOptimizer cachedAppOptimizer, Injector injector) { 509 mService = service; 510 mGlobalState = globalState; 511 mInjector = injector; 512 mProcessList = processList; 513 mProcLock = service.mProcLock; 514 mActiveUids = activeUids; 515 516 mConstants = mService.mConstants; 517 mCachedAppOptimizer = cachedAppOptimizer; 518 mCacheOomRanker = new CacheOomRanker(service); 519 520 mLogger = new OomAdjusterDebugLogger(this, mService.mConstants); 521 522 mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> { 523 final int group = msg.what; 524 final ProcessRecord app = (ProcessRecord) msg.obj; 525 setProcessGroup(app.getPid(), group, app.processName); 526 if (Flags.phantomProcessesFix()) { 527 mService.mPhantomProcessList.setProcessGroupForPhantomProcessOfApp(app, group); 528 } 529 return true; 530 }); 531 mTmpUidRecords = new ActiveUids(service, false); 532 mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1); 533 mNumSlots = ((CACHED_APP_MAX_ADJ - CACHED_APP_MIN_ADJ + 1) >> 1) 534 / CACHED_APP_IMPORTANCE_LEVELS; 535 } 536 setProcessGroup(int pid, int group, String processName)537 void setProcessGroup(int pid, int group, String processName) { 538 if (pid == ActivityManagerService.MY_PID) { 539 // Skip setting the process group for system_server, keep it as default. 540 return; 541 } 542 final boolean traceEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER); 543 if (traceEnabled) { 544 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup " 545 + processName + " to " + group); 546 } 547 try { 548 android.os.Process.setProcessGroup(pid, group); 549 } catch (Exception e) { 550 if (DEBUG_ALL) { 551 Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e); 552 } 553 } finally { 554 if (traceEnabled) { 555 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 556 } 557 } 558 } 559 setAppAndChildProcessGroup(ProcessRecord app, int group)560 void setAppAndChildProcessGroup(ProcessRecord app, int group) { 561 mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage( 562 group, app)); 563 } 564 initSettings()565 void initSettings() { 566 mCachedAppOptimizer.init(); 567 mCacheOomRanker.init(ActivityThread.currentApplication().getMainExecutor()); 568 if (mService.mConstants.KEEP_WARMING_SERVICES.size() > 0) { 569 final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); 570 mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() { 571 @Override 572 public void onReceive(Context context, Intent intent) { 573 synchronized (mService) { 574 handleUserSwitchedLocked(); 575 } 576 } 577 }, filter, null, mService.mHandler); 578 } 579 } 580 581 /** 582 * Update the keep-warming service flags upon user switches 583 */ 584 @VisibleForTesting 585 @GuardedBy("mService") handleUserSwitchedLocked()586 void handleUserSwitchedLocked() { 587 mProcessList.forEachLruProcessesLOSP(false, 588 this::updateKeepWarmIfNecessaryForProcessLocked); 589 } 590 591 @GuardedBy("mService") updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app)592 private void updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app) { 593 final ArraySet<ComponentName> warmServices = mService.mConstants.KEEP_WARMING_SERVICES; 594 boolean includeWarmPkg = false; 595 final PackageList pkgList = app.getPkgList(); 596 for (int j = warmServices.size() - 1; j >= 0; j--) { 597 if (pkgList.containsKey(warmServices.valueAt(j).getPackageName())) { 598 includeWarmPkg = true; 599 break; 600 } 601 } 602 if (!includeWarmPkg) { 603 return; 604 } 605 final ProcessServiceRecord psr = app.mServices; 606 for (int j = psr.numberOfRunningServices() - 1; j >= 0; j--) { 607 psr.getRunningServiceAt(j).updateKeepWarmLocked(); 608 } 609 } 610 611 /** 612 * Update OomAdj for all processes in LRU list 613 */ 614 @GuardedBy("mService") updateOomAdjLocked(@omAdjReason int oomAdjReason)615 void updateOomAdjLocked(@OomAdjReason int oomAdjReason) { 616 synchronized (mProcLock) { 617 updateOomAdjLSP(oomAdjReason); 618 } 619 } 620 621 @GuardedBy({"mService", "mProcLock"}) updateOomAdjLSP(@omAdjReason int oomAdjReason)622 private void updateOomAdjLSP(@OomAdjReason int oomAdjReason) { 623 if (checkAndEnqueueOomAdjTargetLocked(null)) { 624 // Simply return as there is an oomAdjUpdate ongoing 625 return; 626 } 627 try { 628 mOomAdjUpdateOngoing = true; 629 performUpdateOomAdjLSP(oomAdjReason); 630 } finally { 631 // Kick off the handling of any pending targets enqueued during the above update 632 mOomAdjUpdateOngoing = false; 633 updateOomAdjPendingTargetsLocked(oomAdjReason); 634 } 635 } 636 637 @GuardedBy({"mService", "mProcLock"}) performUpdateOomAdjLSP(@omAdjReason int oomAdjReason)638 protected void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) { 639 final ProcessRecord topApp = mService.getTopApp(); 640 mProcessStateCurTop = mService.mAtmInternal.getTopProcessState(); 641 // Clear any pending ones because we are doing a full update now. 642 mPendingProcessSet.clear(); 643 mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false; 644 updateOomAdjInnerLSP(oomAdjReason, topApp , null, null, true, true); 645 } 646 647 /** 648 * Update OomAdj for specific process and its reachable processes (with direction/indirect 649 * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc 650 * is hosting any service/content provider. 651 * 652 * @param app The process to update, or null to update all processes 653 * @param oomAdjReason 654 */ 655 @GuardedBy("mService") updateOomAdjLocked(ProcessRecord app, @OomAdjReason int oomAdjReason)656 boolean updateOomAdjLocked(ProcessRecord app, @OomAdjReason int oomAdjReason) { 657 synchronized (mProcLock) { 658 return updateOomAdjLSP(app, oomAdjReason); 659 } 660 } 661 662 @GuardedBy({"mService", "mProcLock"}) updateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason)663 private boolean updateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) { 664 if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) { 665 updateOomAdjLSP(oomAdjReason); 666 return true; 667 } 668 669 if (checkAndEnqueueOomAdjTargetLocked(app)) { 670 // Simply return true as there is an oomAdjUpdate ongoing 671 return true; 672 } 673 674 try { 675 mOomAdjUpdateOngoing = true; 676 return performUpdateOomAdjLSP(app, oomAdjReason); 677 } finally { 678 // Kick off the handling of any pending targets enqueued during the above update 679 mOomAdjUpdateOngoing = false; 680 updateOomAdjPendingTargetsLocked(oomAdjReason); 681 } 682 } 683 684 @GuardedBy({"mService", "mProcLock"}) performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason)685 protected boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) { 686 final ProcessRecord topApp = mService.getTopApp(); 687 688 mLastReason = oomAdjReason; 689 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason)); 690 691 final ProcessStateRecord state = app.mState; 692 693 // Next to find out all its reachable processes 694 ArrayList<ProcessRecord> processes = mTmpProcessList; 695 ActiveUids uids = mTmpUidRecords; 696 mPendingProcessSet.add(app); 697 mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP(); 698 699 boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet, 700 processes, uids); 701 702 // Clear the pending set as they should've been included in 'processes'. 703 mPendingProcessSet.clear(); 704 705 int size = processes.size(); 706 if (size > 0) { 707 // Update these reachable processes 708 updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false); 709 } else if (state.getCurRawAdj() == UNKNOWN_ADJ) { 710 // In case the app goes from non-cached to cached but it doesn't have other reachable 711 // processes, its adj could be still unknown as of now, assign one. 712 processes.add(app); 713 applyLruAdjust(processes); 714 applyOomAdjLSP(app, false, mInjector.getUptimeMillis(), 715 mInjector.getElapsedRealtimeMillis(), oomAdjReason); 716 } 717 mTmpProcessList.clear(); 718 mService.clearPendingTopAppLocked(); 719 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 720 return true; 721 } 722 723 @GuardedBy({"mService", "mProcLock"}) enqueuePendingTopAppIfNecessaryLSP()724 protected int enqueuePendingTopAppIfNecessaryLSP() { 725 final int prevTopProcessState = mService.mAtmInternal.getTopProcessState(); 726 mService.enqueuePendingTopAppIfNecessaryLocked(); 727 final int topProcessState = mService.mAtmInternal.getTopProcessState(); 728 if (prevTopProcessState != topProcessState) { 729 // Unlikely but possible: WM just updated the top process state, it may have 730 // enqueued the new top app to the pending top UID list. Enqueue that one here too. 731 mService.enqueuePendingTopAppIfNecessaryLocked(); 732 } 733 return topProcessState; 734 } 735 736 /** 737 * Collect the reachable processes from the given {@code apps}, the result will be 738 * returned in the given {@code processes}, which will include the processes from 739 * the given {@code apps}. 740 */ 741 @GuardedBy("mService") collectReachableProcessesLocked(ArraySet<ProcessRecord> apps, ArrayList<ProcessRecord> processes, ActiveUids uids)742 protected boolean collectReachableProcessesLocked(ArraySet<ProcessRecord> apps, 743 ArrayList<ProcessRecord> processes, ActiveUids uids) { 744 final ArrayDeque<ProcessRecord> queue = mTmpQueue; 745 queue.clear(); 746 processes.clear(); 747 for (int i = 0, size = apps.size(); i < size; i++) { 748 final ProcessRecord app = apps.valueAt(i); 749 app.mState.setReachable(true); 750 queue.offer(app); 751 } 752 753 uids.clear(); 754 755 // Track if any of them reachables could include a cycle 756 boolean containsCycle = false; 757 // Scan downstreams of the process record 758 for (ProcessRecord pr = queue.poll(); pr != null; pr = queue.poll()) { 759 processes.add(pr); 760 final UidRecord uidRec = pr.getUidRecord(); 761 if (uidRec != null) { 762 uids.put(uidRec.getUid(), uidRec); 763 } 764 final ProcessServiceRecord psr = pr.mServices; 765 for (int i = psr.numberOfConnections() - 1; i >= 0; i--) { 766 ConnectionRecord cr = psr.getConnectionAt(i); 767 ProcessRecord service = cr.hasFlag(ServiceInfo.FLAG_ISOLATED_PROCESS) 768 ? cr.binding.service.isolationHostProc : cr.binding.service.app; 769 if (service == null || service == pr 770 || ((service.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ) 771 && (service.mState.getMaxAdj() < FOREGROUND_APP_ADJ))) { 772 continue; 773 } 774 containsCycle |= service.mState.isReachable(); 775 if (service.mState.isReachable()) { 776 continue; 777 } 778 if (cr.hasFlag(Context.BIND_WAIVE_PRIORITY) 779 && cr.notHasFlag(Context.BIND_TREAT_LIKE_ACTIVITY 780 | Context.BIND_ADJUST_WITH_ACTIVITY)) { 781 continue; 782 } 783 queue.offer(service); 784 service.mState.setReachable(true); 785 } 786 final ProcessProviderRecord ppr = pr.mProviders; 787 for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) { 788 ContentProviderConnection cpc = ppr.getProviderConnectionAt(i); 789 ProcessRecord provider = cpc.provider.proc; 790 if (provider == null || provider == pr 791 || ((provider.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ) 792 && (provider.mState.getMaxAdj() < FOREGROUND_APP_ADJ))) { 793 continue; 794 } 795 containsCycle |= provider.mState.isReachable(); 796 if (provider.mState.isReachable()) { 797 continue; 798 } 799 queue.offer(provider); 800 provider.mState.setReachable(true); 801 } 802 // See if this process has any corresponding SDK sandbox processes running, and if so 803 // scan them as well. 804 final List<ProcessRecord> sdkSandboxes = 805 mProcessList.getSdkSandboxProcessesForAppLocked(pr.uid); 806 final int numSdkSandboxes = sdkSandboxes != null ? sdkSandboxes.size() : 0; 807 for (int i = numSdkSandboxes - 1; i >= 0; i--) { 808 ProcessRecord sdkSandbox = sdkSandboxes.get(i); 809 containsCycle |= sdkSandbox.mState.isReachable(); 810 if (sdkSandbox.mState.isReachable()) { 811 continue; 812 } 813 queue.offer(sdkSandbox); 814 sdkSandbox.mState.setReachable(true); 815 } 816 // If this process is a sandbox itself, also scan the app on whose behalf its running 817 if (pr.isSdkSandbox) { 818 for (int is = psr.numberOfRunningServices() - 1; is >= 0; is--) { 819 ServiceRecord s = psr.getRunningServiceAt(is); 820 ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = 821 s.getConnections(); 822 for (int conni = serviceConnections.size() - 1; conni >= 0; conni--) { 823 ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni); 824 for (int i = clist.size() - 1; i >= 0; i--) { 825 ConnectionRecord cr = clist.get(i); 826 ProcessRecord attributedApp = cr.binding.attributedClient; 827 if (attributedApp == null || attributedApp == pr 828 || ((attributedApp.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ) 829 && (attributedApp.mState.getMaxAdj() < FOREGROUND_APP_ADJ))) { 830 continue; 831 } 832 if (attributedApp.mState.isReachable()) { 833 continue; 834 } 835 queue.offer(attributedApp); 836 attributedApp.mState.setReachable(true); 837 } 838 } 839 } 840 } 841 } 842 843 int size = processes.size(); 844 if (size > 0) { 845 // Reverse the process list, since the updateOomAdjInnerLSP scans from the end of it. 846 for (int l = 0, r = size - 1; l < r; l++, r--) { 847 final ProcessRecord t = processes.get(l); 848 final ProcessRecord u = processes.get(r); 849 t.mState.setReachable(false); 850 u.mState.setReachable(false); 851 processes.set(l, u); 852 processes.set(r, t); 853 } 854 } 855 856 return containsCycle; 857 } 858 859 /** 860 * Enqueue the given process for a later oom adj update 861 */ 862 @GuardedBy("mService") enqueueOomAdjTargetLocked(ProcessRecord app)863 void enqueueOomAdjTargetLocked(ProcessRecord app) { 864 if (app != null && app.mState.getMaxAdj() > FOREGROUND_APP_ADJ) { 865 mPendingProcessSet.add(app); 866 } 867 } 868 869 @GuardedBy("mService") removeOomAdjTargetLocked(ProcessRecord app, boolean procDied)870 void removeOomAdjTargetLocked(ProcessRecord app, boolean procDied) { 871 if (app != null) { 872 mPendingProcessSet.remove(app); 873 if (procDied) { 874 PlatformCompatCache.getInstance().invalidate(app.info); 875 } 876 } 877 } 878 879 /** 880 * Check if there is an ongoing oomAdjUpdate, enqueue the given process record 881 * to {@link #mPendingProcessSet} if there is one. 882 * 883 * @param app The target app to get an oomAdjUpdate, or a full oomAdjUpdate if it's null. 884 * @return {@code true} if there is an ongoing oomAdjUpdate. 885 */ 886 @GuardedBy("mService") checkAndEnqueueOomAdjTargetLocked(@ullable ProcessRecord app)887 private boolean checkAndEnqueueOomAdjTargetLocked(@Nullable ProcessRecord app) { 888 if (!mOomAdjUpdateOngoing) { 889 return false; 890 } 891 if (app != null) { 892 mPendingProcessSet.add(app); 893 } else { 894 mPendingFullOomAdjUpdate = true; 895 } 896 return true; 897 } 898 899 /** 900 * Kick off an oom adj update pass for the pending targets which are enqueued via 901 * {@link #enqueueOomAdjTargetLocked}. 902 */ 903 @GuardedBy("mService") updateOomAdjPendingTargetsLocked(@omAdjReason int oomAdjReason)904 void updateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) { 905 // First check if there is pending full update 906 if (mPendingFullOomAdjUpdate) { 907 mPendingFullOomAdjUpdate = false; 908 mPendingProcessSet.clear(); 909 updateOomAdjLocked(oomAdjReason); 910 return; 911 } 912 if (mPendingProcessSet.isEmpty()) { 913 return; 914 } 915 916 if (mOomAdjUpdateOngoing) { 917 // There's another oomAdjUpdate ongoing, return from here now; 918 // that ongoing update would call us again at the end of it. 919 return; 920 } 921 try { 922 mOomAdjUpdateOngoing = true; 923 performUpdateOomAdjPendingTargetsLocked(oomAdjReason); 924 } finally { 925 // Kick off the handling of any pending targets enqueued during the above update 926 mOomAdjUpdateOngoing = false; 927 updateOomAdjPendingTargetsLocked(oomAdjReason); 928 } 929 } 930 931 @GuardedBy("mService") updateOomAdjFollowUpTargetsLocked()932 void updateOomAdjFollowUpTargetsLocked() { 933 final long now = mInjector.getUptimeMillis(); 934 long nextFollowUpUptimeMs = Long.MAX_VALUE; 935 mNextFollowUpUpdateUptimeMs = NO_FOLLOW_UP_TIME; 936 for (int i = mFollowUpUpdateSet.size() - 1; i >= 0; i--) { 937 final ProcessRecord proc = mFollowUpUpdateSet.valueAtUnchecked(i); 938 final long followUpUptimeMs = proc.mState.getFollowupUpdateUptimeMs(); 939 940 if (proc.isKilled()) { 941 // Process is dead, just remove from follow up set. 942 mFollowUpUpdateSet.removeAt(i); 943 } else if (followUpUptimeMs <= now) { 944 // Add processes that need a follow up update. 945 mPendingProcessSet.add(proc); 946 proc.mState.setFollowupUpdateUptimeMs(NO_FOLLOW_UP_TIME); 947 mFollowUpUpdateSet.removeAt(i); 948 } else if (followUpUptimeMs < nextFollowUpUptimeMs) { 949 // Figure out when to schedule the next follow up update. 950 nextFollowUpUptimeMs = followUpUptimeMs; 951 } else if (followUpUptimeMs == NO_FOLLOW_UP_TIME) { 952 // The follow up is no longer needed for this process. 953 mFollowUpUpdateSet.removeAt(i); 954 } 955 } 956 957 if (nextFollowUpUptimeMs != Long.MAX_VALUE) { 958 // There is still at least one process that needs a follow up. 959 scheduleFollowUpOomAdjusterUpdateLocked(nextFollowUpUptimeMs, now); 960 } 961 962 updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_FOLLOW_UP); 963 } 964 965 @GuardedBy("mService") performUpdateOomAdjPendingTargetsLocked(@omAdjReason int oomAdjReason)966 protected void performUpdateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) { 967 final ProcessRecord topApp = mService.getTopApp(); 968 969 mLastReason = oomAdjReason; 970 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason)); 971 mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP(); 972 973 final ArrayList<ProcessRecord> processes = mTmpProcessList; 974 final ActiveUids uids = mTmpUidRecords; 975 collectReachableProcessesLocked(mPendingProcessSet, processes, uids); 976 mPendingProcessSet.clear(); 977 synchronized (mProcLock) { 978 updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false); 979 } 980 processes.clear(); 981 mService.clearPendingTopAppLocked(); 982 983 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 984 } 985 986 /** 987 * Update OomAdj for all processes within the given list (could be partial), or the whole LRU 988 * list if the given list is null; when it's partial update, each process's client proc won't 989 * get evaluated recursively here. 990 * 991 * <p>Note: If the given {@code processes} is not null, the expectation to it is, the caller 992 * must have called {@link collectReachableProcessesLocked} on it. 993 */ 994 @GuardedBy({"mService", "mProcLock"}) updateOomAdjInnerLSP(@omAdjReason int oomAdjReason, final ProcessRecord topApp, ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles, boolean startProfiling)995 private void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp, 996 ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles, 997 boolean startProfiling) { 998 final boolean fullUpdate = processes == null; 999 final ArrayList<ProcessRecord> activeProcesses = fullUpdate 1000 ? mProcessList.getLruProcessesLOSP() : processes; 1001 ActiveUids activeUids = uids; 1002 if (activeUids == null) { 1003 final int numUids = mActiveUids.size(); 1004 activeUids = mTmpUidRecords; 1005 activeUids.clear(); 1006 for (int i = 0; i < numUids; i++) { 1007 UidRecord uidRec = mActiveUids.valueAt(i); 1008 activeUids.put(uidRec.getUid(), uidRec); 1009 } 1010 } 1011 1012 mLastReason = oomAdjReason; 1013 if (startProfiling) { 1014 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason)); 1015 } 1016 final long now = mInjector.getUptimeMillis(); 1017 final long nowElapsed = mInjector.getElapsedRealtimeMillis(); 1018 final long oldTime = now - mConstants.mMaxEmptyTimeMillis; 1019 final int numProc = activeProcesses.size(); 1020 1021 mAdjSeq++; 1022 if (fullUpdate) { 1023 mNewNumServiceProcs = 0; 1024 mNewNumAServiceProcs = 0; 1025 } 1026 1027 // Reset state in all uid records. 1028 resetUidRecordsLsp(activeUids); 1029 1030 boolean retryCycles = false; 1031 boolean computeClients = fullUpdate || potentialCycles; 1032 1033 // need to reset cycle state before calling computeOomAdjLSP because of service conns 1034 for (int i = numProc - 1; i >= 0; i--) { 1035 ProcessRecord app = activeProcesses.get(i); 1036 final ProcessStateRecord state = app.mState; 1037 state.setReachable(false); 1038 // No need to compute again it has been evaluated in previous iteration 1039 if (state.getAdjSeq() != mAdjSeq) { 1040 state.setContainsCycle(false); 1041 state.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); 1042 state.setCurRawAdj(UNKNOWN_ADJ); 1043 state.setSetCapability(PROCESS_CAPABILITY_NONE); 1044 state.resetCachedInfo(); 1045 state.setCurBoundByNonBgRestrictedApp(false); 1046 } 1047 } 1048 mProcessesInCycle.clear(); 1049 for (int i = numProc - 1; i >= 0; i--) { 1050 ProcessRecord app = activeProcesses.get(i); 1051 final ProcessStateRecord state = app.mState; 1052 if (!app.isKilledByAm() && app.getThread() != null) { 1053 state.setProcStateChanged(false); 1054 app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason); 1055 // It won't enter cycle if not computing clients. 1056 computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, fullUpdate, now, false, 1057 computeClients, oomAdjReason, true); 1058 // if any app encountered a cycle, we need to perform an additional loop later 1059 retryCycles |= state.containsCycle(); 1060 // Keep the completedAdjSeq to up to date. 1061 state.setCompletedAdjSeq(mAdjSeq); 1062 } 1063 } 1064 1065 if (mCacheOomRanker.useOomReranking()) { 1066 mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(), 1067 mProcessList.getLruProcessServiceStartLOSP()); 1068 } 1069 1070 if (computeClients) { // There won't be cycles if we didn't compute clients above. 1071 // Cycle strategy: 1072 // - Retry computing any process that has encountered a cycle. 1073 // - Continue retrying until no process was promoted. 1074 // - Iterate from least important to most important. 1075 int cycleCount = 0; 1076 while (retryCycles && cycleCount < 10) { 1077 cycleCount++; 1078 retryCycles = false; 1079 1080 for (int i = 0; i < numProc; i++) { 1081 ProcessRecord app = activeProcesses.get(i); 1082 final ProcessStateRecord state = app.mState; 1083 if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) { 1084 state.decAdjSeq(); 1085 state.decCompletedAdjSeq(); 1086 } 1087 } 1088 1089 for (int i = 0; i < numProc; i++) { 1090 ProcessRecord app = activeProcesses.get(i); 1091 final ProcessStateRecord state = app.mState; 1092 if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) { 1093 if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now, 1094 true, true, oomAdjReason, true)) { 1095 retryCycles = true; 1096 } 1097 } 1098 } 1099 } 1100 } 1101 mProcessesInCycle.clear(); 1102 1103 applyLruAdjust(mProcessList.getLruProcessesLOSP()); 1104 1105 postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime, true); 1106 1107 if (startProfiling) { 1108 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1109 } 1110 } 1111 1112 @GuardedBy({"mService", "mProcLock"}) resetUidRecordsLsp(@onNull ActiveUids activeUids)1113 private void resetUidRecordsLsp(@NonNull ActiveUids activeUids) { 1114 // Reset state in all uid records. 1115 for (int i = activeUids.size() - 1; i >= 0; i--) { 1116 final UidRecord uidRec = activeUids.valueAt(i); 1117 if (DEBUG_UID_OBSERVERS) { 1118 Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec); 1119 } 1120 uidRec.reset(); 1121 } 1122 } 1123 1124 @GuardedBy({"mService", "mProcLock"}) postUpdateOomAdjInnerLSP(@omAdjReason int oomAdjReason, ActiveUids activeUids, long now, long nowElapsed, long oldTime, boolean doingAll)1125 protected void postUpdateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, ActiveUids activeUids, 1126 long now, long nowElapsed, long oldTime, boolean doingAll) { 1127 mNumNonCachedProcs = 0; 1128 mNumCachedHiddenProcs = 0; 1129 1130 updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids, 1131 oomAdjReason, doingAll); 1132 mNumServiceProcs = mNewNumServiceProcs; 1133 1134 if (mService.mAlwaysFinishActivities) { 1135 // Need to do this on its own message because the stack may not 1136 // be in a consistent state at this point. 1137 mService.mAtmInternal.scheduleDestroyAllActivities("always-finish"); 1138 } 1139 1140 updateUidsLSP(activeUids, nowElapsed); 1141 1142 synchronized (mService.mProcessStats.mLock) { 1143 final long nowUptime = mInjector.getUptimeMillis(); 1144 if (mService.mProcessStats.shouldWriteNowLocked(nowUptime)) { 1145 mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService, 1146 mService.mProcessStats)); 1147 } 1148 1149 // Run this after making sure all procstates are updated. 1150 mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, nowUptime); 1151 } 1152 1153 if (DEBUG_OOM_ADJ) { 1154 final long duration = mInjector.getUptimeMillis() - now; 1155 if (false) { 1156 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms", 1157 new RuntimeException("here").fillInStackTrace()); 1158 } else { 1159 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms"); 1160 } 1161 } 1162 } 1163 1164 @GuardedBy({"mService", "mProcLock"}) applyLruAdjust(ArrayList<ProcessRecord> lruList)1165 protected void applyLruAdjust(ArrayList<ProcessRecord> lruList) { 1166 final int numLru = lruList.size(); 1167 int nextPreviousAppAdj = PREVIOUS_APP_ADJ; 1168 if (mConstants.USE_TIERED_CACHED_ADJ) { 1169 final long now = mInjector.getUptimeMillis(); 1170 int uiTargetAdj = 10; 1171 // mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE is 10 by default, but is configurable. 1172 final int uiTierMaxAdj = 10 + mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE; 1173 for (int i = numLru - 1; i >= 0; i--) { 1174 ProcessRecord app = lruList.get(i); 1175 final ProcessStateRecord state = app.mState; 1176 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 1177 final int curAdj = state.getCurAdj(); 1178 if (PREVIOUS_APP_ADJ <= curAdj && curAdj <= PREVIOUS_APP_MAX_ADJ) { 1179 state.setCurAdj(nextPreviousAppAdj); 1180 nextPreviousAppAdj = Math.min(nextPreviousAppAdj + 1, PREVIOUS_APP_MAX_ADJ); 1181 } else if (!app.isKilledByAm() && app.getThread() != null && (curAdj >= UNKNOWN_ADJ 1182 || (state.hasShownUi() && curAdj >= CACHED_APP_MIN_ADJ))) { 1183 final ProcessServiceRecord psr = app.mServices; 1184 int targetAdj = CACHED_APP_MIN_ADJ; 1185 1186 if (opt != null && opt.isFreezeExempt()) { 1187 // BIND_WAIVE_PRIORITY and the like get oom_adj 900 1188 targetAdj += 0; 1189 } else if (state.hasShownUi() && uiTargetAdj < uiTierMaxAdj) { 1190 // The most recent UI-showing apps get [910, 910 + ui tier size). 1191 targetAdj += uiTargetAdj++; 1192 } else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ) 1193 && (state.getLastStateTime() 1194 + mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) { 1195 // Older cached apps get 940 + ui tier size (950 by default). 1196 targetAdj += 40 + mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE; 1197 } else { 1198 // Newer cached apps get 910 + ui tier size (920 by default). 1199 targetAdj += 10 + mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE; 1200 } 1201 state.setCurRawAdj(targetAdj); 1202 state.setCurAdj(psr.modifyRawOomAdj(targetAdj)); 1203 } 1204 } 1205 } else { 1206 // First update the OOM adjustment for each of the 1207 // application processes based on their current state. 1208 int curCachedAdj = CACHED_APP_MIN_ADJ; 1209 int nextCachedAdj = curCachedAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2); 1210 int curCachedImpAdj = 0; 1211 int curEmptyAdj = CACHED_APP_MIN_ADJ + CACHED_APP_IMPORTANCE_LEVELS; 1212 int nextEmptyAdj = curEmptyAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2); 1213 1214 final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES; 1215 final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES 1216 - emptyProcessLimit; 1217 // Let's determine how many processes we have running vs. 1218 // how many slots we have for background processes; we may want 1219 // to put multiple processes in a slot of there are enough of 1220 // them. 1221 int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs; 1222 if (numEmptyProcs > cachedProcessLimit) { 1223 // If there are more empty processes than our limit on cached 1224 // processes, then use the cached process limit for the factor. 1225 // This ensures that the really old empty processes get pushed 1226 // down to the bottom, so if we are running low on memory we will 1227 // have a better chance at keeping around more cached processes 1228 // instead of a gazillion empty processes. 1229 numEmptyProcs = cachedProcessLimit; 1230 } 1231 int cachedFactor = (mNumCachedHiddenProcs > 0 1232 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1) 1233 / mNumSlots; 1234 if (cachedFactor < 1) cachedFactor = 1; 1235 1236 int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots; 1237 if (emptyFactor < 1) emptyFactor = 1; 1238 1239 int stepCached = -1; 1240 int stepEmpty = -1; 1241 int lastCachedGroup = 0; 1242 int lastCachedGroupImportance = 0; 1243 int lastCachedGroupUid = 0; 1244 1245 1246 for (int i = numLru - 1; i >= 0; i--) { 1247 ProcessRecord app = lruList.get(i); 1248 final ProcessStateRecord state = app.mState; 1249 final int curAdj = state.getCurAdj(); 1250 if (PREVIOUS_APP_ADJ <= curAdj && curAdj <= PREVIOUS_APP_MAX_ADJ) { 1251 state.setCurAdj(nextPreviousAppAdj); 1252 nextPreviousAppAdj = Math.min(nextPreviousAppAdj + 1, PREVIOUS_APP_MAX_ADJ); 1253 } else if (!app.isKilledByAm() && app.getThread() != null 1254 && curAdj >= UNKNOWN_ADJ) { 1255 // If we haven't yet assigned the final cached adj to the process, do that now. 1256 final ProcessServiceRecord psr = app.mServices; 1257 switch (state.getCurProcState()) { 1258 case PROCESS_STATE_LAST_ACTIVITY: 1259 case PROCESS_STATE_CACHED_ACTIVITY: 1260 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: 1261 case ActivityManager.PROCESS_STATE_CACHED_RECENT: 1262 // Figure out the next cached level, taking into account groups. 1263 boolean inGroup = false; 1264 final int connectionGroup = psr.getConnectionGroup(); 1265 if (connectionGroup != 0) { 1266 final int connectionImportance = psr.getConnectionImportance(); 1267 if (lastCachedGroupUid == app.uid 1268 && lastCachedGroup == connectionGroup) { 1269 // This is in the same group as the last process, just tweak 1270 // adjustment by importance. 1271 if (connectionImportance > lastCachedGroupImportance) { 1272 lastCachedGroupImportance = connectionImportance; 1273 if (curCachedAdj < nextCachedAdj 1274 && curCachedAdj < CACHED_APP_MAX_ADJ) { 1275 curCachedImpAdj++; 1276 } 1277 } 1278 inGroup = true; 1279 } else { 1280 lastCachedGroupUid = app.uid; 1281 lastCachedGroup = connectionGroup; 1282 lastCachedGroupImportance = connectionImportance; 1283 } 1284 } 1285 if (!inGroup && curCachedAdj != nextCachedAdj) { 1286 stepCached++; 1287 curCachedImpAdj = 0; 1288 if (stepCached >= cachedFactor) { 1289 stepCached = 0; 1290 curCachedAdj = nextCachedAdj; 1291 nextCachedAdj += CACHED_APP_IMPORTANCE_LEVELS * 2; 1292 if (nextCachedAdj > CACHED_APP_MAX_ADJ) { 1293 nextCachedAdj = CACHED_APP_MAX_ADJ; 1294 } 1295 } 1296 } 1297 // This process is a cached process holding activities... 1298 // assign it the next cached value for that type, and then 1299 // step that cached level. 1300 state.setCurRawAdj(curCachedAdj + curCachedImpAdj); 1301 state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj)); 1302 if (DEBUG_LRU) { 1303 Slog.d(TAG_LRU, "Assigning activity LRU #" + i 1304 + " adj: " + state.getCurAdj() 1305 + " (curCachedAdj=" + curCachedAdj 1306 + " curCachedImpAdj=" + curCachedImpAdj + ")"); 1307 } 1308 break; 1309 default: 1310 // Figure out the next cached level. 1311 if (curEmptyAdj != nextEmptyAdj) { 1312 stepEmpty++; 1313 if (stepEmpty >= emptyFactor) { 1314 stepEmpty = 0; 1315 curEmptyAdj = nextEmptyAdj; 1316 nextEmptyAdj += CACHED_APP_IMPORTANCE_LEVELS * 2; 1317 if (nextEmptyAdj > CACHED_APP_MAX_ADJ) { 1318 nextEmptyAdj = CACHED_APP_MAX_ADJ; 1319 } 1320 } 1321 } 1322 // For everything else, assign next empty cached process 1323 // level and bump that up. Note that this means that 1324 // long-running services that have dropped down to the 1325 // cached level will be treated as empty (since their process 1326 // state is still as a service), which is what we want. 1327 state.setCurRawAdj(curEmptyAdj); 1328 state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj)); 1329 if (DEBUG_LRU) { 1330 Slog.d(TAG_LRU, "Assigning empty LRU #" + i 1331 + " adj: " + state.getCurAdj() 1332 + " (curEmptyAdj=" + curEmptyAdj 1333 + ")"); 1334 } 1335 break; 1336 } 1337 } 1338 } 1339 } 1340 } 1341 private long mNextNoKillDebugMessageTime; 1342 1343 private double mLastFreeSwapPercent = 1.00; 1344 getFreeSwapPercent()1345 private static double getFreeSwapPercent() { 1346 return CachedAppOptimizer.getFreeSwapPercent(); 1347 } 1348 1349 @GuardedBy({"mService", "mProcLock"}) updateAndTrimProcessLSP(final long now, final long nowElapsed, final long oldTime, final ActiveUids activeUids, @OomAdjReason int oomAdjReason, boolean doingAll)1350 private void updateAndTrimProcessLSP(final long now, final long nowElapsed, 1351 final long oldTime, final ActiveUids activeUids, @OomAdjReason int oomAdjReason, 1352 boolean doingAll) { 1353 ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP(); 1354 final int numLru = lruList.size(); 1355 1356 final boolean doKillExcessiveProcesses = shouldKillExcessiveProcesses(now); 1357 if (!doKillExcessiveProcesses) { 1358 if (mNextNoKillDebugMessageTime < now) { 1359 Slog.d(TAG, "Not killing cached processes"); // STOPSHIP Remove it b/222365734 1360 mNextNoKillDebugMessageTime = now + 5000; // Every 5 seconds 1361 } 1362 } 1363 final int emptyProcessLimit = doKillExcessiveProcesses 1364 ? mConstants.CUR_MAX_EMPTY_PROCESSES : Integer.MAX_VALUE; 1365 final int cachedProcessLimit = doKillExcessiveProcesses 1366 ? (mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit) : Integer.MAX_VALUE; 1367 int lastCachedGroup = 0; 1368 int lastCachedGroupUid = 0; 1369 int numCached = 0; 1370 int numCachedExtraGroup = 0; 1371 int numEmpty = 0; 1372 int numTrimming = 0; 1373 1374 boolean proactiveKillsEnabled = mConstants.PROACTIVE_KILLS_ENABLED; 1375 double lowSwapThresholdPercent = mConstants.LOW_SWAP_THRESHOLD_PERCENT; 1376 double freeSwapPercent = proactiveKillsEnabled ? getFreeSwapPercent() : 1.00; 1377 ProcessRecord lruCachedApp = null; 1378 1379 for (int i = numLru - 1; i >= 0; i--) { 1380 ProcessRecord app = lruList.get(i); 1381 final ProcessStateRecord state = app.mState; 1382 if (!app.isKilledByAm() && app.getThread() != null) { 1383 if (!Flags.fixApplyOomadjOrder()) { 1384 // We don't need to apply the update for the process which didn't get computed 1385 if (state.getCompletedAdjSeq() == mAdjSeq) { 1386 applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, true); 1387 } 1388 } 1389 1390 if (app.isPendingFinishAttach()) { 1391 // Avoid trimming processes that are still initializing. If they aren't 1392 // hosting any components yet because they may be unfairly killed. 1393 // We however apply the oom scores set at #setAttachingProcessStatesLSP. 1394 updateAppUidRecLSP(app); 1395 continue; 1396 } 1397 1398 final ProcessServiceRecord psr = app.mServices; 1399 // Count the number of process types. 1400 switch (state.getCurProcState()) { 1401 case PROCESS_STATE_CACHED_ACTIVITY: 1402 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: 1403 mNumCachedHiddenProcs++; 1404 numCached++; 1405 final int connectionGroup = psr.getConnectionGroup(); 1406 if (connectionGroup != 0) { 1407 if (lastCachedGroupUid == app.info.uid 1408 && lastCachedGroup == connectionGroup) { 1409 // If this process is the next in the same group, we don't 1410 // want it to count against our limit of the number of cached 1411 // processes, so bump up the group count to account for it. 1412 numCachedExtraGroup++; 1413 } else { 1414 lastCachedGroupUid = app.info.uid; 1415 lastCachedGroup = connectionGroup; 1416 } 1417 } else { 1418 lastCachedGroupUid = lastCachedGroup = 0; 1419 } 1420 if ((numCached - numCachedExtraGroup) > cachedProcessLimit) { 1421 app.killLocked("cached #" + numCached, 1422 "too many cached", 1423 ApplicationExitInfo.REASON_OTHER, 1424 ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED, 1425 true); 1426 } else if (proactiveKillsEnabled) { 1427 lruCachedApp = app; 1428 } 1429 break; 1430 case PROCESS_STATE_CACHED_EMPTY: 1431 if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES 1432 && app.getLastActivityTime() < oldTime) { 1433 app.killLocked("empty for " + ((now 1434 - app.getLastActivityTime()) / 1000) + "s", 1435 "empty for too long", 1436 ApplicationExitInfo.REASON_OTHER, 1437 ApplicationExitInfo.SUBREASON_TRIM_EMPTY, 1438 true); 1439 } else { 1440 numEmpty++; 1441 if (numEmpty > emptyProcessLimit) { 1442 app.killLocked("empty #" + numEmpty, 1443 "too many empty", 1444 ApplicationExitInfo.REASON_OTHER, 1445 ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, 1446 true); 1447 } else if (proactiveKillsEnabled) { 1448 lruCachedApp = app; 1449 } 1450 } 1451 break; 1452 default: 1453 mNumNonCachedProcs++; 1454 break; 1455 } 1456 1457 // TODO: b/319163103 - limit isolated/sandbox trimming to just the processes 1458 // evaluated in the current update. 1459 if (app.isolated && psr.numberOfRunningServices() <= 0 1460 && app.getIsolatedEntryPoint() == null) { 1461 // If this is an isolated process, there are no services 1462 // running in it, and it's not a special process with a 1463 // custom entry point, then the process is no longer 1464 // needed. We agressively kill these because we can by 1465 // definition not re-use the same process again, and it is 1466 // good to avoid having whatever code was running in them 1467 // left sitting around after no longer needed. 1468 app.killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER, 1469 ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true); 1470 } else if (app.isSdkSandbox && psr.numberOfRunningServices() <= 0 1471 && app.getActiveInstrumentation() == null) { 1472 // If this is an SDK sandbox process and there are no services running it, we 1473 // aggressively kill the sandbox as we usually don't want to re-use the same 1474 // sandbox again. 1475 app.killLocked("sandbox not needed", ApplicationExitInfo.REASON_OTHER, 1476 ApplicationExitInfo.SUBREASON_SDK_SANDBOX_NOT_NEEDED, true); 1477 } else { 1478 // Keeping this process, update its uid. 1479 updateAppUidRecLSP(app); 1480 } 1481 1482 if (state.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME 1483 && !app.isKilledByAm()) { 1484 numTrimming++; 1485 } 1486 } 1487 } 1488 1489 if (Flags.fixApplyOomadjOrder()) { 1490 // We need to apply the update starting from the least recently used. 1491 // Otherwise, they won't be in the correct LRU order in LMKD. 1492 for (int i = 0; i < numLru; i++) { 1493 ProcessRecord app = lruList.get(i); 1494 // We don't need to apply the update for the process which didn't get computed 1495 if (!app.isKilledByAm() && app.getThread() != null 1496 && app.mState.getCompletedAdjSeq() == mAdjSeq) { 1497 applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, true); 1498 } 1499 } 1500 } 1501 1502 if (!mProcsToOomAdj.isEmpty()) { 1503 mInjector.batchSetOomAdj(mProcsToOomAdj); 1504 mProcsToOomAdj.clear(); 1505 } 1506 1507 if (proactiveKillsEnabled // Proactive kills enabled? 1508 && doKillExcessiveProcesses // Should kill excessive processes? 1509 && freeSwapPercent < lowSwapThresholdPercent // Swap below threshold? 1510 && lruCachedApp != null // If no cached app, let LMKD decide 1511 // If swap is non-decreasing, give reclaim a chance to catch up 1512 && freeSwapPercent < mLastFreeSwapPercent) { 1513 lruCachedApp.killLocked("swap low and too many cached", 1514 ApplicationExitInfo.REASON_OTHER, 1515 ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED, 1516 true); 1517 } 1518 1519 mLastFreeSwapPercent = freeSwapPercent; 1520 1521 mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming, now); 1522 } 1523 1524 @GuardedBy({"mService", "mProcLock"}) updateAppUidRecIfNecessaryLSP(final ProcessRecord app)1525 protected void updateAppUidRecIfNecessaryLSP(final ProcessRecord app) { 1526 if (!app.isKilledByAm() && app.getThread() != null) { 1527 if (app.isolated && app.mServices.numberOfRunningServices() <= 0 1528 && app.getIsolatedEntryPoint() == null) { 1529 // No op. 1530 } else { 1531 // Keeping this process, update its uid. 1532 updateAppUidRecLSP(app); 1533 } 1534 } 1535 } 1536 1537 @GuardedBy({"mService", "mProcLock"}) updateAppUidRecLSP(ProcessRecord app)1538 private void updateAppUidRecLSP(ProcessRecord app) { 1539 final UidRecord uidRec = app.getUidRecord(); 1540 if (uidRec != null) { 1541 final ProcessStateRecord state = app.mState; 1542 uidRec.setEphemeral(app.info.isInstantApp()); 1543 if (uidRec.getCurProcState() > state.getCurProcState()) { 1544 uidRec.setCurProcState(state.getCurProcState()); 1545 } 1546 if (app.mServices.hasForegroundServices()) { 1547 uidRec.setForegroundServices(true); 1548 } 1549 uidRec.setCurCapability(uidRec.getCurCapability() | state.getCurCapability()); 1550 } 1551 } 1552 1553 @GuardedBy({"mService", "mProcLock"}) updateUidsLSP(ActiveUids activeUids, final long nowElapsed)1554 protected void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) { 1555 // This compares previously set procstate to the current procstate in regards to whether 1556 // or not the app's network access will be blocked. So, this needs to be called before 1557 // we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}. 1558 mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids); 1559 1560 ArrayList<UidRecord> becameIdle = mTmpBecameIdle; 1561 becameIdle.clear(); 1562 1563 // Update from any uid changes. 1564 if (mService.mLocalPowerManager != null) { 1565 mService.mLocalPowerManager.startUidChanges(); 1566 } 1567 for (int i = activeUids.size() - 1; i >= 0; i--) { 1568 final UidRecord uidRec = activeUids.valueAt(i); 1569 if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT) { 1570 if (uidRec.getSetProcState() != uidRec.getCurProcState() 1571 || uidRec.getSetCapability() != uidRec.getCurCapability() 1572 || uidRec.isSetAllowListed() != uidRec.isCurAllowListed() 1573 || uidRec.getProcAdjChanged()) { 1574 int uidChange = 0; 1575 final boolean shouldLog = mLogger.shouldLog(uidRec.getUid()); 1576 if (DEBUG_UID_OBSERVERS) { 1577 Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec 1578 + ": proc state from " + uidRec.getSetProcState() + " to " 1579 + uidRec.getCurProcState() + ", capability from " 1580 + uidRec.getSetCapability() + " to " + uidRec.getCurCapability() 1581 + ", allowlist from " + uidRec.isSetAllowListed() 1582 + " to " + uidRec.isCurAllowListed() 1583 + ", procAdjChanged: " + uidRec.getProcAdjChanged()); 1584 } 1585 if (ActivityManager.isProcStateBackground(uidRec.getCurProcState()) 1586 && !uidRec.isCurAllowListed()) { 1587 // UID is now in the background (and not on the temp allowlist). Was it 1588 // previously in the foreground (or on the temp allowlist)? 1589 // Or, it wasn't in the foreground / allowlist, but its last background 1590 // timestamp is also 0, this means it's never been in the 1591 // foreground / allowlist since it's born at all. 1592 if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState()) 1593 || uidRec.isSetAllowListed() 1594 || uidRec.getLastBackgroundTime() == 0) { 1595 uidRec.setLastBackgroundTime(nowElapsed); 1596 if (shouldLog) { 1597 mLogger.logSetLastBackgroundTime(uidRec.getUid(), nowElapsed); 1598 } 1599 if (mService.mDeterministicUidIdle 1600 || !mService.mHandler.hasMessages(IDLE_UIDS_MSG)) { 1601 // Note: the background settle time is in elapsed realtime, while 1602 // the handler time base is uptime. All this means is that we may 1603 // stop background uids later than we had intended, but that only 1604 // happens because the device was sleeping so we are okay anyway. 1605 if (shouldLog) { 1606 mLogger.logScheduleUidIdle1(uidRec.getUid(), 1607 mConstants.BACKGROUND_SETTLE_TIME); 1608 } 1609 mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, 1610 mConstants.BACKGROUND_SETTLE_TIME); // XXX 1611 } 1612 } 1613 if (uidRec.isIdle() && !uidRec.isSetIdle()) { 1614 uidChange |= UidRecord.CHANGE_IDLE; 1615 if (uidRec.getSetProcState() != PROCESS_STATE_NONEXISTENT) { 1616 // don't stop the bg services if it's just started. 1617 becameIdle.add(uidRec); 1618 } 1619 } 1620 } else { 1621 if (uidRec.isIdle()) { 1622 uidChange |= UidRecord.CHANGE_ACTIVE; 1623 EventLogTags.writeAmUidActive(uidRec.getUid()); 1624 uidRec.setIdle(false); 1625 } 1626 uidRec.setLastBackgroundTime(0); 1627 uidRec.setLastIdleTime(0); 1628 if (shouldLog) { 1629 mLogger.logClearLastBackgroundTime(uidRec.getUid()); 1630 } 1631 } 1632 final boolean wasCached = uidRec.getSetProcState() 1633 > ActivityManager.PROCESS_STATE_RECEIVER; 1634 final boolean isCached = uidRec.getCurProcState() 1635 > ActivityManager.PROCESS_STATE_RECEIVER; 1636 if (wasCached != isCached 1637 || uidRec.getSetProcState() == PROCESS_STATE_NONEXISTENT) { 1638 uidChange |= isCached ? UidRecord.CHANGE_CACHED : 1639 UidRecord.CHANGE_UNCACHED; 1640 } 1641 if (uidRec.getSetCapability() != uidRec.getCurCapability()) { 1642 uidChange |= UidRecord.CHANGE_CAPABILITY; 1643 } 1644 if (uidRec.getSetProcState() != uidRec.getCurProcState()) { 1645 uidChange |= UidRecord.CHANGE_PROCSTATE; 1646 } 1647 if (uidRec.getProcAdjChanged()) { 1648 uidChange |= UidRecord.CHANGE_PROCADJ; 1649 } 1650 int oldProcState = uidRec.getSetProcState(); 1651 int oldCapability = uidRec.getSetCapability(); 1652 uidRec.setSetProcState(uidRec.getCurProcState()); 1653 uidRec.setSetCapability(uidRec.getCurCapability()); 1654 uidRec.setSetAllowListed(uidRec.isCurAllowListed()); 1655 uidRec.setSetIdle(uidRec.isIdle()); 1656 uidRec.clearProcAdjChanged(); 1657 if (shouldLog 1658 && ((uidRec.getSetProcState() != oldProcState) 1659 || (uidRec.getSetCapability() != oldCapability))) { 1660 int flags = 0; 1661 if (uidRec.isSetAllowListed()) { 1662 flags |= 1; 1663 } 1664 mLogger.logUidStateChanged(uidRec.getUid(), 1665 uidRec.getSetProcState(), oldProcState, 1666 uidRec.getSetCapability(), oldCapability, 1667 flags); 1668 } 1669 if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0 1670 || (uidChange & UidRecord.CHANGE_CAPABILITY) != 0) { 1671 mService.mAtmInternal.onUidProcStateChanged( 1672 uidRec.getUid(), uidRec.getSetProcState()); 1673 } 1674 if (uidChange != 0) { 1675 mService.enqueueUidChangeLocked(uidRec, -1, uidChange); 1676 } 1677 if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0 1678 || (uidChange & UidRecord.CHANGE_CAPABILITY) != 0) { 1679 mService.noteUidProcessStateAndCapability(uidRec.getUid(), 1680 uidRec.getCurProcState(), uidRec.getCurCapability()); 1681 } 1682 if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0) { 1683 mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState()); 1684 } 1685 if (uidRec.hasForegroundServices()) { 1686 mService.mServices.foregroundServiceProcStateChangedLocked(uidRec); 1687 } 1688 } 1689 } 1690 mService.mInternal.deletePendingTopUid(uidRec.getUid(), nowElapsed); 1691 } 1692 if (mService.mLocalPowerManager != null) { 1693 mService.mLocalPowerManager.finishUidChanges(); 1694 } 1695 1696 int size = becameIdle.size(); 1697 if (size > 0) { 1698 // If we have any new uids that became idle this time, we need to make sure 1699 // they aren't left with running services. 1700 for (int i = size - 1; i >= 0; i--) { 1701 mService.mServices.stopInBackgroundLocked(becameIdle.get(i).getUid()); 1702 } 1703 } 1704 } 1705 1706 /** 1707 * Return true if we should kill excessive cached/empty processes. 1708 */ shouldKillExcessiveProcesses(long nowUptime)1709 private boolean shouldKillExcessiveProcesses(long nowUptime) { 1710 final long lastUserUnlockingUptime = mService.mUserController.getLastUserUnlockingUptime(); 1711 1712 if (lastUserUnlockingUptime == 0) { 1713 // No users have been unlocked. 1714 return !mConstants.mNoKillCachedProcessesUntilBootCompleted; 1715 } 1716 final long noKillCachedProcessesPostBootCompletedDurationMillis = 1717 mConstants.mNoKillCachedProcessesPostBootCompletedDurationMillis; 1718 if ((lastUserUnlockingUptime + noKillCachedProcessesPostBootCompletedDurationMillis) 1719 > nowUptime) { 1720 return false; 1721 } 1722 return true; 1723 } 1724 1725 protected final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback = 1726 new ComputeOomAdjWindowCallback(); 1727 1728 /** These methods are called inline during computeOomAdjLSP(), on the same thread */ 1729 final class ComputeOomAdjWindowCallback { 1730 1731 ProcessRecord app; 1732 int adj; 1733 boolean foregroundActivities; 1734 boolean mHasVisibleActivities; 1735 int procState; 1736 int schedGroup; 1737 int appUid; 1738 int logUid; 1739 int processStateCurTop; 1740 String mAdjType; 1741 ProcessStateRecord mState; 1742 initialize(ProcessRecord app, int adj, boolean foregroundActivities, boolean hasVisibleActivities, int procState, int schedGroup, int appUid, int logUid, int processStateCurTop)1743 void initialize(ProcessRecord app, int adj, boolean foregroundActivities, 1744 boolean hasVisibleActivities, int procState, int schedGroup, int appUid, 1745 int logUid, int processStateCurTop) { 1746 this.app = app; 1747 this.adj = adj; 1748 this.foregroundActivities = foregroundActivities; 1749 this.mHasVisibleActivities = hasVisibleActivities; 1750 this.procState = procState; 1751 this.schedGroup = schedGroup; 1752 this.appUid = appUid; 1753 this.logUid = logUid; 1754 this.processStateCurTop = processStateCurTop; 1755 mAdjType = app.mState.getAdjType(); 1756 this.mState = app.mState; 1757 } 1758 onVisibleActivity(int flags)1759 void onVisibleActivity(int flags) { 1760 // App has a visible activity; only upgrade adjustment. 1761 if (adj > VISIBLE_APP_ADJ) { 1762 adj = VISIBLE_APP_ADJ; 1763 mAdjType = "vis-activity"; 1764 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1765 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app); 1766 } 1767 } 1768 if (procState > processStateCurTop) { 1769 procState = processStateCurTop; 1770 mAdjType = "vis-activity"; 1771 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1772 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1773 "Raise procstate to vis-activity (top): " + app); 1774 } 1775 } 1776 if (schedGroup < SCHED_GROUP_DEFAULT) { 1777 schedGroup = SCHED_GROUP_DEFAULT; 1778 } 1779 if ((flags & WindowProcessController.ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN) != 0) { 1780 // Another side of split should be the current global top. Use the same top 1781 // priority for this non-top split. 1782 schedGroup = SCHED_GROUP_TOP_APP; 1783 mAdjType = "resumed-split-screen-activity"; 1784 } else if ((flags 1785 & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0) { 1786 // The recently used non-top visible freeform app. 1787 schedGroup = SCHED_GROUP_TOP_APP; 1788 mAdjType = "perceptible-freeform-activity"; 1789 } else if ((flags 1790 & WindowProcessController.ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE) != 0) { 1791 // Currently the only case is from freeform apps which are not close to top. 1792 schedGroup = SCHED_GROUP_FOREGROUND_WINDOW; 1793 mAdjType = "vis-multi-window-activity"; 1794 } 1795 foregroundActivities = true; 1796 mHasVisibleActivities = true; 1797 } 1798 onPausedActivity()1799 void onPausedActivity() { 1800 if (adj > PERCEPTIBLE_APP_ADJ) { 1801 adj = PERCEPTIBLE_APP_ADJ; 1802 mAdjType = "pause-activity"; 1803 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1804 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: " + app); 1805 } 1806 } 1807 if (procState > processStateCurTop) { 1808 procState = processStateCurTop; 1809 mAdjType = "pause-activity"; 1810 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1811 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1812 "Raise procstate to pause-activity (top): " + app); 1813 } 1814 } 1815 if (schedGroup < SCHED_GROUP_DEFAULT) { 1816 schedGroup = SCHED_GROUP_DEFAULT; 1817 } 1818 foregroundActivities = true; 1819 mHasVisibleActivities = false; 1820 } 1821 onStoppingActivity(boolean finishing)1822 void onStoppingActivity(boolean finishing) { 1823 if (adj > PERCEPTIBLE_APP_ADJ) { 1824 adj = PERCEPTIBLE_APP_ADJ; 1825 mAdjType = "stop-activity"; 1826 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1827 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1828 "Raise adj to stop-activity: " + app); 1829 } 1830 } 1831 1832 // For the process state, we will at this point consider the process to be cached. It 1833 // will be cached either as an activity or empty depending on whether the activity is 1834 // finishing. We do this so that we can treat the process as cached for purposes of 1835 // memory trimming (determining current memory level, trim command to send to process) 1836 // since there can be an arbitrary number of stopping processes and they should soon all 1837 // go into the cached state. 1838 if (!finishing) { 1839 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 1840 procState = PROCESS_STATE_LAST_ACTIVITY; 1841 mAdjType = "stop-activity"; 1842 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1843 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1844 "Raise procstate to stop-activity: " + app); 1845 } 1846 } 1847 } 1848 foregroundActivities = true; 1849 mHasVisibleActivities = false; 1850 } 1851 onOtherActivity(long perceptibleTaskStoppedTimeMillis)1852 void onOtherActivity(long perceptibleTaskStoppedTimeMillis) { 1853 if (procState > PROCESS_STATE_CACHED_ACTIVITY) { 1854 procState = PROCESS_STATE_CACHED_ACTIVITY; 1855 mAdjType = "cch-act"; 1856 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1857 reportOomAdjMessageLocked(TAG_OOM_ADJ, 1858 "Raise procstate to cached activity: " + app); 1859 } 1860 } 1861 if (Flags.perceptibleTasks() && adj > PERCEPTIBLE_MEDIUM_APP_ADJ) { 1862 if (perceptibleTaskStoppedTimeMillis >= 0) { 1863 final long now = mInjector.getUptimeMillis(); 1864 if (now - perceptibleTaskStoppedTimeMillis < PERCEPTIBLE_TASK_TIMEOUT_MILLIS) { 1865 adj = PERCEPTIBLE_MEDIUM_APP_ADJ; 1866 mAdjType = "perceptible-act"; 1867 if (procState > PROCESS_STATE_IMPORTANT_BACKGROUND) { 1868 procState = PROCESS_STATE_IMPORTANT_BACKGROUND; 1869 } 1870 1871 maybeSetProcessFollowUpUpdateLocked(app, 1872 perceptibleTaskStoppedTimeMillis + PERCEPTIBLE_TASK_TIMEOUT_MILLIS, 1873 now); 1874 } else if (adj > PREVIOUS_APP_ADJ) { 1875 adj = PREVIOUS_APP_ADJ; 1876 mAdjType = "stale-perceptible-act"; 1877 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 1878 procState = PROCESS_STATE_LAST_ACTIVITY; 1879 } 1880 } 1881 } 1882 } 1883 mHasVisibleActivities = false; 1884 } 1885 } 1886 isDeviceFullyAwake()1887 private boolean isDeviceFullyAwake() { 1888 if (Flags.pushGlobalStateToOomadjuster()) { 1889 return mGlobalState.isAwake(); 1890 } else { 1891 return mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE; 1892 } 1893 } 1894 isScreenOnOrAnimatingLocked(ProcessStateRecord state)1895 private boolean isScreenOnOrAnimatingLocked(ProcessStateRecord state) { 1896 return isDeviceFullyAwake() || state.isRunningRemoteAnimation(); 1897 } 1898 isBackupProcess(ProcessRecord app)1899 private boolean isBackupProcess(ProcessRecord app) { 1900 if (Flags.pushGlobalStateToOomadjuster()) { 1901 return app == mGlobalState.getBackupTarget(app.userId); 1902 } else { 1903 final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId); 1904 if (backupTarget == null) { 1905 return false; 1906 } 1907 return app == backupTarget.app; 1908 } 1909 } 1910 isLastMemoryLevelNormal()1911 private boolean isLastMemoryLevelNormal() { 1912 if (Flags.pushGlobalStateToOomadjuster()) { 1913 return mGlobalState.isLastMemoryLevelNormal(); 1914 } else { 1915 return mService.mAppProfiler.isLastMemoryLevelNormal(); 1916 } 1917 } 1918 1919 @GuardedBy({"mService", "mProcLock"}) computeOomAdjLSP(ProcessRecord app, int cachedAdj, ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval, boolean computeClients, int oomAdjReason, boolean couldRecurse)1920 protected boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj, 1921 ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval, 1922 boolean computeClients, int oomAdjReason, boolean couldRecurse) { 1923 final ProcessStateRecord state = app.mState; 1924 if (couldRecurse) { 1925 if (mAdjSeq == state.getAdjSeq()) { 1926 if (state.getAdjSeq() == state.getCompletedAdjSeq()) { 1927 // This adjustment has already been computed successfully. 1928 return false; 1929 } else { 1930 // The process is being computed, so there is a cycle. We cannot 1931 // rely on this process's state. 1932 state.setContainsCycle(true); 1933 mProcessesInCycle.add(app); 1934 1935 return false; 1936 } 1937 } 1938 } 1939 1940 int prevAppAdj = getInitialAdj(app); 1941 int prevProcState = getInitialProcState(app); 1942 int prevCapability = getInitialCapability(app); 1943 1944 // Remove any follow up update this process might have. It will be rescheduled if still 1945 // needed. 1946 app.mState.setFollowupUpdateUptimeMs(NO_FOLLOW_UP_TIME); 1947 1948 if (app.getThread() == null) { 1949 state.setAdjSeq(mAdjSeq); 1950 state.setCurrentSchedulingGroup(SCHED_GROUP_BACKGROUND); 1951 state.setCurProcState(PROCESS_STATE_CACHED_EMPTY); 1952 state.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); 1953 state.setCurAdj(CACHED_APP_MAX_ADJ); 1954 state.setCurRawAdj(CACHED_APP_MAX_ADJ); 1955 state.setCompletedAdjSeq(state.getAdjSeq()); 1956 state.setCurCapability(PROCESS_CAPABILITY_NONE); 1957 return false; 1958 } 1959 1960 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN); 1961 state.setAdjSource(null); 1962 state.setAdjTarget(null); 1963 if (!couldRecurse || !cycleReEval) { 1964 // Don't reset this flag when doing cycles re-evaluation. 1965 state.setNoKillOnBgRestrictedAndIdle(false); 1966 // If this UID is currently allowlisted, it should not be frozen. 1967 final UidRecord uidRec = app.getUidRecord(); 1968 app.mOptRecord.setShouldNotFreeze(uidRec != null && uidRec.isCurAllowListed(), 1969 ProcessCachedOptimizerRecord.SHOULD_NOT_FREEZE_REASON_UID_ALLOWLISTED, mAdjSeq); 1970 } 1971 1972 final int appUid = app.info.uid; 1973 final int logUid = mService.mCurOomAdjUid; 1974 1975 final ProcessServiceRecord psr = app.mServices; 1976 1977 if (state.getMaxAdj() <= FOREGROUND_APP_ADJ) { 1978 // The max adjustment doesn't allow this app to be anything 1979 // below foreground, so it is not worth doing work for it. 1980 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 1981 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app); 1982 } 1983 state.setAdjType("fixed"); 1984 state.setAdjSeq(mAdjSeq); 1985 state.setCurRawAdj(state.getMaxAdj()); 1986 state.setHasForegroundActivities(false); 1987 state.setCurrentSchedulingGroup(SCHED_GROUP_DEFAULT); 1988 state.setCurCapability(PROCESS_CAPABILITY_ALL); // BFSL allowed 1989 state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT); 1990 // System processes can do UI, and when they do we want to have 1991 // them trim their memory after the user leaves the UI. To 1992 // facilitate this, here we need to determine whether or not it 1993 // is currently showing UI. 1994 state.setSystemNoUi(true); 1995 if (app == topApp) { 1996 state.setSystemNoUi(false); 1997 state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP); 1998 state.setAdjType("pers-top-activity"); 1999 } else if (state.hasTopUi()) { 2000 // sched group/proc state adjustment is below 2001 state.setSystemNoUi(false); 2002 state.setAdjType("pers-top-ui"); 2003 } else if (state.getCachedHasVisibleActivities()) { 2004 state.setSystemNoUi(false); 2005 } 2006 if (!state.isSystemNoUi()) { 2007 if (isScreenOnOrAnimatingLocked(state)) { 2008 // screen on or animating, promote UI 2009 state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI); 2010 state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP); 2011 } else if (!app.getWindowProcessController().isShowingUiWhileDozing()) { 2012 // screen off, restrict UI scheduling 2013 state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 2014 state.setCurrentSchedulingGroup(SCHED_GROUP_RESTRICTED); 2015 } 2016 } 2017 state.setCurRawProcState(state.getCurProcState()); 2018 state.setCurAdj(state.getMaxAdj()); 2019 state.setCompletedAdjSeq(state.getAdjSeq()); 2020 // if curAdj is less than prevAppAdj, then this process was promoted 2021 return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState; 2022 } 2023 2024 state.setSystemNoUi(false); 2025 2026 final int PROCESS_STATE_CUR_TOP = mProcessStateCurTop; 2027 2028 // Determine the importance of the process, starting with most 2029 // important to least, and assign an appropriate OOM adjustment. 2030 int adj; 2031 int schedGroup; 2032 int procState; 2033 int capability = cycleReEval ? getInitialCapability(app) : 0; 2034 2035 boolean hasVisibleActivities = false; 2036 if (app == topApp && PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP) { 2037 // The last app on the list is the foreground app. 2038 adj = FOREGROUND_APP_ADJ; 2039 if (mService.mAtmInternal.useTopSchedGroupForTopProcess()) { 2040 schedGroup = SCHED_GROUP_TOP_APP; 2041 state.setAdjType("top-activity"); 2042 } else { 2043 // Demote the scheduling group to avoid CPU contention if there is another more 2044 // important process which also uses top-app, such as if SystemUI is animating. 2045 schedGroup = SCHED_GROUP_DEFAULT; 2046 state.setAdjType("intermediate-top-activity"); 2047 } 2048 hasVisibleActivities = true; 2049 procState = PROCESS_STATE_TOP; 2050 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2051 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app); 2052 } 2053 } else if (state.isRunningRemoteAnimation()) { 2054 adj = VISIBLE_APP_ADJ; 2055 schedGroup = SCHED_GROUP_TOP_APP; 2056 state.setAdjType("running-remote-anim"); 2057 procState = PROCESS_STATE_CUR_TOP; 2058 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2059 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app); 2060 } 2061 } else if (app.getActiveInstrumentation() != null) { 2062 // Don't want to kill running instrumentation. 2063 adj = FOREGROUND_APP_ADJ; 2064 schedGroup = SCHED_GROUP_DEFAULT; 2065 state.setAdjType("instrumentation"); 2066 procState = PROCESS_STATE_FOREGROUND_SERVICE; 2067 capability |= PROCESS_CAPABILITY_BFSL; 2068 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2069 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app); 2070 } 2071 } else if (state.getCachedIsReceivingBroadcast(mTmpSchedGroup)) { 2072 // An app that is currently receiving a broadcast also 2073 // counts as being in the foreground for OOM killer purposes. 2074 // It's placed in a sched group based on the nature of the 2075 // broadcast as reflected by which queue it's active in. 2076 adj = FOREGROUND_APP_ADJ; 2077 schedGroup = mTmpSchedGroup[0]; 2078 state.setAdjType("broadcast"); 2079 procState = ActivityManager.PROCESS_STATE_RECEIVER; 2080 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2081 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app); 2082 } 2083 } else if (psr.numberOfExecutingServices() > 0) { 2084 // An app that is currently executing a service callback also 2085 // counts as being in the foreground. 2086 adj = FOREGROUND_APP_ADJ; 2087 schedGroup = psr.shouldExecServicesFg() 2088 ? SCHED_GROUP_DEFAULT : SCHED_GROUP_BACKGROUND; 2089 state.setAdjType("exec-service"); 2090 procState = PROCESS_STATE_SERVICE; 2091 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2092 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app); 2093 } 2094 } else if (app == topApp) { 2095 adj = FOREGROUND_APP_ADJ; 2096 schedGroup = SCHED_GROUP_BACKGROUND; 2097 state.setAdjType("top-sleeping"); 2098 procState = PROCESS_STATE_CUR_TOP; 2099 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2100 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app); 2101 } 2102 } else { 2103 // As far as we know the process is empty. We may change our mind later. 2104 schedGroup = SCHED_GROUP_BACKGROUND; 2105 // At this point we don't actually know the adjustment. Use the cached adj 2106 // value that the caller wants us to. 2107 adj = cachedAdj; 2108 procState = PROCESS_STATE_CACHED_EMPTY; 2109 if (!couldRecurse || !state.containsCycle()) { 2110 state.setAdjType("cch-empty"); 2111 } 2112 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2113 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app); 2114 } 2115 } 2116 2117 // Examine all non-top activities. 2118 boolean foregroundActivities = app == topApp; 2119 if (!foregroundActivities && state.getCachedHasActivities()) { 2120 state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback, 2121 adj, foregroundActivities, hasVisibleActivities, procState, schedGroup, 2122 appUid, logUid, PROCESS_STATE_CUR_TOP); 2123 2124 adj = state.getCachedAdj(); 2125 foregroundActivities = state.getCachedForegroundActivities(); 2126 hasVisibleActivities = state.getCachedHasVisibleActivities(); 2127 procState = state.getCachedProcState(); 2128 schedGroup = state.getCachedSchedGroup(); 2129 state.setAdjType(state.getCachedAdjType()); 2130 } 2131 2132 if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) { 2133 procState = PROCESS_STATE_CACHED_RECENT; 2134 state.setAdjType("cch-rec"); 2135 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2136 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app); 2137 } 2138 } 2139 2140 int capabilityFromFGS = 0; // capability from foreground service. 2141 2142 final boolean hasForegroundServices = psr.hasForegroundServices(); 2143 final boolean hasNonShortForegroundServices = psr.hasNonShortForegroundServices(); 2144 final boolean hasShortForegroundServices = hasForegroundServices 2145 && !psr.areAllShortForegroundServicesProcstateTimedOut(now); 2146 2147 // Adjust for FGS or "has-overlay-ui". 2148 if (adj > PERCEPTIBLE_APP_ADJ 2149 || procState > PROCESS_STATE_FOREGROUND_SERVICE) { 2150 String adjType = null; 2151 int newAdj = 0; 2152 int newProcState = 0; 2153 2154 if (hasForegroundServices && hasNonShortForegroundServices) { 2155 // For regular (non-short) FGS. 2156 adjType = "fg-service"; 2157 newAdj = PERCEPTIBLE_APP_ADJ; 2158 newProcState = PROCESS_STATE_FOREGROUND_SERVICE; 2159 capabilityFromFGS |= PROCESS_CAPABILITY_BFSL; 2160 2161 } else if (hasShortForegroundServices) { 2162 2163 // For short FGS. 2164 adjType = "fg-service-short"; 2165 2166 // We use MEDIUM_APP_ADJ + 1 so we can tell apart EJ 2167 // (which uses MEDIUM_APP_ADJ + 1) 2168 // from short-FGS. 2169 // (We use +1 and +2, not +0 and +1, to be consistent with the following 2170 // RECENT_FOREGROUND_APP_ADJ tweak) 2171 newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 1; 2172 2173 // We give the FGS procstate, but not PROCESS_CAPABILITY_BFSL, so 2174 // short-fgs can't start FGS from the background. 2175 newProcState = PROCESS_STATE_FOREGROUND_SERVICE; 2176 2177 } else if (state.hasOverlayUi()) { 2178 adjType = "has-overlay-ui"; 2179 newAdj = PERCEPTIBLE_APP_ADJ; 2180 newProcState = PROCESS_STATE_IMPORTANT_FOREGROUND; 2181 } 2182 2183 if (adjType != null) { 2184 adj = newAdj; 2185 procState = newProcState; 2186 state.setAdjType(adjType); 2187 schedGroup = SCHED_GROUP_DEFAULT; 2188 2189 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2190 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType + ": " 2191 + app + " "); 2192 } 2193 } 2194 } 2195 2196 // If the app was recently in the foreground and moved to a foreground service status, 2197 // allow it to get a higher rank in memory for some time, compared to other foreground 2198 // services so that it can finish performing any persistence/processing of in-memory state. 2199 if (psr.hasForegroundServices() && adj > PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 2200 && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now 2201 || state.getSetProcState() <= PROCESS_STATE_TOP)) { 2202 if (psr.hasNonShortForegroundServices()) { 2203 adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; 2204 state.setAdjType("fg-service-act"); 2205 } else { 2206 // For short-service FGS, we +1 the value, so we'll be able to detect it in 2207 // various dashboards. 2208 adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 1; 2209 state.setAdjType("fg-service-short-act"); 2210 } 2211 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2212 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app); 2213 } 2214 maybeSetProcessFollowUpUpdateLocked(app, 2215 state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION, now); 2216 } 2217 2218 // If the app was recently in the foreground and has expedited jobs running, 2219 // allow it to get a higher rank in memory for some time, compared to other EJS and even 2220 // foreground services so that it can finish performing any persistence/processing of 2221 // in-memory state. 2222 if (psr.hasTopStartedAlmostPerceptibleServices() 2223 && (adj > PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2) 2224 && (state.getLastTopTime() 2225 + mConstants.TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION > now 2226 || state.getSetProcState() <= PROCESS_STATE_TOP)) { 2227 // For EJ, we +2 the value, so we'll be able to detect it in 2228 // various dashboards. 2229 adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2; 2230 // This shall henceforth be called the "EJ" exemption, despite utilizing the 2231 // ALMOST_PERCEPTIBLE flag to work. 2232 state.setAdjType("top-ej-act"); 2233 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2234 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg for EJ: " + app); 2235 } 2236 maybeSetProcessFollowUpUpdateLocked(app, 2237 state.getLastTopTime() + mConstants.TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION, 2238 now); 2239 } 2240 2241 if (adj > PERCEPTIBLE_APP_ADJ 2242 || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { 2243 if (state.getForcingToImportant() != null) { 2244 // This is currently used for toasts... they are not interactive, and 2245 // we don't want them to cause the app to become fully foreground (and 2246 // thus out of background check), so we yes the best background level we can. 2247 adj = PERCEPTIBLE_APP_ADJ; 2248 procState = PROCESS_STATE_TRANSIENT_BACKGROUND; 2249 state.setAdjType("force-imp"); 2250 state.setAdjSource(state.getForcingToImportant()); 2251 schedGroup = SCHED_GROUP_DEFAULT; 2252 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2253 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app); 2254 } 2255 } 2256 } 2257 2258 if (state.getCachedIsHeavyWeight()) { 2259 if (adj > HEAVY_WEIGHT_APP_ADJ) { 2260 // We don't want to kill the current heavy-weight process. 2261 adj = HEAVY_WEIGHT_APP_ADJ; 2262 schedGroup = SCHED_GROUP_BACKGROUND; 2263 state.setAdjType("heavy"); 2264 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2265 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app); 2266 } 2267 } 2268 if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { 2269 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; 2270 state.setAdjType("heavy"); 2271 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2272 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app); 2273 } 2274 } 2275 } 2276 2277 if (state.getCachedIsHomeProcess()) { 2278 if (adj > HOME_APP_ADJ) { 2279 // This process is hosting what we currently consider to be the 2280 // home app, so we don't want to let it go into the background. 2281 adj = HOME_APP_ADJ; 2282 schedGroup = SCHED_GROUP_BACKGROUND; 2283 state.setAdjType("home"); 2284 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2285 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app); 2286 } 2287 } 2288 if (procState > ActivityManager.PROCESS_STATE_HOME) { 2289 procState = ActivityManager.PROCESS_STATE_HOME; 2290 state.setAdjType("home"); 2291 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2292 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app); 2293 } 2294 } 2295 } 2296 if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) { 2297 // This was the previous process that showed UI to the user. We want to 2298 // try to keep it around more aggressively, to give a good experience 2299 // around switching between two apps. However, we don't want to keep the 2300 // process in this privileged state indefinitely. Eventually, allow the 2301 // app to be demoted to cached. 2302 if (procState >= PROCESS_STATE_LAST_ACTIVITY 2303 && state.getSetProcState() == PROCESS_STATE_LAST_ACTIVITY 2304 && (state.getLastStateTime() + mConstants.MAX_PREVIOUS_TIME) <= now) { 2305 procState = PROCESS_STATE_LAST_ACTIVITY; 2306 schedGroup = SCHED_GROUP_BACKGROUND; 2307 state.setAdjType("previous-expired"); 2308 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2309 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Expire prev adj: " + app); 2310 } 2311 } else { 2312 if (adj > PREVIOUS_APP_ADJ) { 2313 adj = PREVIOUS_APP_ADJ; 2314 schedGroup = SCHED_GROUP_BACKGROUND; 2315 state.setAdjType("previous"); 2316 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2317 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app); 2318 } 2319 } 2320 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 2321 procState = PROCESS_STATE_LAST_ACTIVITY; 2322 state.setAdjType("previous"); 2323 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2324 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app); 2325 } 2326 } 2327 final long lastStateTime; 2328 if (state.getSetProcState() == PROCESS_STATE_LAST_ACTIVITY) { 2329 lastStateTime = state.getLastStateTime(); 2330 } else { 2331 lastStateTime = now; 2332 } 2333 maybeSetProcessFollowUpUpdateLocked(app, 2334 lastStateTime + mConstants.MAX_PREVIOUS_TIME, now); 2335 } 2336 } 2337 2338 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj 2339 + " reason=" + state.getAdjType()); 2340 2341 // By default, we use the computed adjustment. It may be changed if 2342 // there are applications dependent on our services or providers, but 2343 // this gives us a baseline and makes sure we don't get into an 2344 // infinite recursion. If we're re-evaluating due to cycles, use the previously computed 2345 // values. 2346 if (cycleReEval) { 2347 procState = Math.min(procState, state.getCurRawProcState()); 2348 adj = Math.min(adj, state.getCurRawAdj()); 2349 schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup()); 2350 } 2351 state.setCurRawAdj(adj); 2352 state.setCurRawProcState(procState); 2353 2354 state.setHasStartedServices(false); 2355 state.setAdjSeq(mAdjSeq); 2356 2357 if (isBackupProcess(app)) { 2358 // If possible we want to avoid killing apps while they're being backed up 2359 if (adj > BACKUP_APP_ADJ) { 2360 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app); 2361 adj = BACKUP_APP_ADJ; 2362 if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { 2363 procState = PROCESS_STATE_TRANSIENT_BACKGROUND; 2364 } 2365 state.setAdjType("backup"); 2366 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2367 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app); 2368 } 2369 } 2370 if (procState > ActivityManager.PROCESS_STATE_BACKUP) { 2371 procState = ActivityManager.PROCESS_STATE_BACKUP; 2372 state.setAdjType("backup"); 2373 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2374 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app); 2375 } 2376 } 2377 } 2378 2379 state.setCurBoundByNonBgRestrictedApp(getInitialIsCurBoundByNonBgRestrictedApp(app)); 2380 2381 state.setScheduleLikeTopApp(false); 2382 2383 for (int is = psr.numberOfRunningServices() - 1; 2384 is >= 0 && (adj > FOREGROUND_APP_ADJ 2385 || schedGroup == SCHED_GROUP_BACKGROUND 2386 || procState > PROCESS_STATE_TOP); 2387 is--) { 2388 ServiceRecord s = psr.getRunningServiceAt(is); 2389 if (s.startRequested) { 2390 state.setHasStartedServices(true); 2391 if (procState > PROCESS_STATE_SERVICE) { 2392 procState = PROCESS_STATE_SERVICE; 2393 state.setAdjType("started-services"); 2394 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2395 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2396 "Raise procstate to started service: " + app); 2397 } 2398 } 2399 if (!s.mKeepWarming && state.hasShownUi() && !state.getCachedIsHomeProcess()) { 2400 // If this process has shown some UI, let it immediately 2401 // go to the LRU list because it may be pretty heavy with 2402 // UI stuff. We'll tag it with a label just to help 2403 // debug and understand what is going on. 2404 if (adj > SERVICE_ADJ) { 2405 state.setAdjType("cch-started-ui-services"); 2406 } 2407 } else { 2408 if (s.mKeepWarming 2409 || now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) { 2410 // This service has seen some activity within 2411 // recent memory, so we will keep its process ahead 2412 // of the background processes. This does not apply 2413 // to the SDK sandbox process since it should never 2414 // be more important than its corresponding app. 2415 if (!app.isSdkSandbox && adj > SERVICE_ADJ) { 2416 adj = SERVICE_ADJ; 2417 state.setAdjType("started-services"); 2418 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2419 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2420 "Raise adj to started service: " + app); 2421 } 2422 maybeSetProcessFollowUpUpdateLocked(app, 2423 s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY, now); 2424 } 2425 } 2426 // If we have let the service slide into the background 2427 // state, still have some text describing what it is doing 2428 // even though the service no longer has an impact. 2429 if (adj > SERVICE_ADJ) { 2430 state.setAdjType("cch-started-services"); 2431 } 2432 } 2433 } 2434 2435 if (s.isForeground) { 2436 final int fgsType = s.foregroundServiceType; 2437 if (s.isFgsAllowedWiu_forCapabilities()) { 2438 capabilityFromFGS |= 2439 (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) 2440 != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; 2441 2442 if (roForegroundAudioControl()) { // flag check 2443 // TODO(b/335373208) - revisit restriction of FOREGROUND_AUDIO_CONTROL 2444 // when it can be limited to specific FGS types 2445 capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL; 2446 } 2447 2448 final boolean enabled = state.getCachedCompatChange( 2449 CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY); 2450 if (enabled) { 2451 capabilityFromFGS |= 2452 (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA) 2453 != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0; 2454 capabilityFromFGS |= 2455 (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE) 2456 != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0; 2457 } else { 2458 capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA 2459 | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; 2460 } 2461 } 2462 } 2463 2464 if (!couldRecurse) { 2465 // We're entering recursive functions below, if we're told it's not a recursive 2466 // loop, abort here. 2467 continue; 2468 } 2469 2470 2471 state.setCurRawAdj(adj); 2472 state.setCurRawProcState(procState); 2473 state.setCurrentSchedulingGroup(schedGroup); 2474 state.setCurCapability(capability); 2475 2476 ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections(); 2477 for (int conni = serviceConnections.size() - 1; 2478 conni >= 0 && (adj > FOREGROUND_APP_ADJ 2479 || schedGroup == SCHED_GROUP_BACKGROUND 2480 || procState > PROCESS_STATE_TOP); 2481 conni--) { 2482 ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni); 2483 for (int i = 0; 2484 i < clist.size() && (adj > FOREGROUND_APP_ADJ 2485 || schedGroup == SCHED_GROUP_BACKGROUND 2486 || procState > PROCESS_STATE_TOP); 2487 i++) { 2488 // XXX should compute this based on the max of 2489 // all connected clients. 2490 ConnectionRecord cr = clist.get(i); 2491 if (cr.binding.client == app) { 2492 // Binding to oneself is not interesting. 2493 continue; 2494 } 2495 2496 computeServiceHostOomAdjLSP(cr, app, cr.binding.client, now, topApp, doingAll, 2497 cycleReEval, computeClients, oomAdjReason, cachedAdj, true, false); 2498 2499 adj = state.getCurRawAdj(); 2500 procState = state.getCurRawProcState(); 2501 schedGroup = state.getCurrentSchedulingGroup(); 2502 capability = state.getCurCapability(); 2503 } 2504 } 2505 } 2506 2507 final ProcessProviderRecord ppr = app.mProviders; 2508 for (int provi = ppr.numberOfProviders() - 1; 2509 provi >= 0 && (adj > FOREGROUND_APP_ADJ 2510 || schedGroup == SCHED_GROUP_BACKGROUND 2511 || procState > PROCESS_STATE_TOP); 2512 provi--) { 2513 ContentProviderRecord cpr = ppr.getProviderAt(provi); 2514 if (couldRecurse) { 2515 // We're entering recursive functions below. 2516 state.setCurRawAdj(adj); 2517 state.setCurRawProcState(procState); 2518 state.setCurrentSchedulingGroup(schedGroup); 2519 state.setCurCapability(capability); 2520 2521 for (int i = cpr.connections.size() - 1; 2522 i >= 0 && (adj > FOREGROUND_APP_ADJ 2523 || schedGroup == SCHED_GROUP_BACKGROUND 2524 || procState > PROCESS_STATE_TOP); 2525 i--) { 2526 ContentProviderConnection conn = cpr.connections.get(i); 2527 ProcessRecord client = conn.client; 2528 computeProviderHostOomAdjLSP(conn, app, client, now, topApp, doingAll, 2529 cycleReEval, computeClients, oomAdjReason, cachedAdj, true, false); 2530 2531 adj = state.getCurRawAdj(); 2532 procState = state.getCurRawProcState(); 2533 schedGroup = state.getCurrentSchedulingGroup(); 2534 capability = state.getCurCapability(); 2535 } 2536 } 2537 // If the provider has external (non-framework) process 2538 // dependencies, ensure that its adjustment is at least 2539 // FOREGROUND_APP_ADJ. 2540 if (cpr.hasExternalProcessHandles()) { 2541 if (adj > FOREGROUND_APP_ADJ) { 2542 adj = FOREGROUND_APP_ADJ; 2543 state.setCurRawAdj(adj); 2544 schedGroup = SCHED_GROUP_DEFAULT; 2545 state.setAdjType("ext-provider"); 2546 state.setAdjTarget(cpr.name); 2547 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2548 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2549 "Raise adj to external provider: " + app); 2550 } 2551 } 2552 if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) { 2553 procState = PROCESS_STATE_IMPORTANT_FOREGROUND; 2554 state.setCurRawProcState(procState); 2555 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2556 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2557 "Raise procstate to external provider: " + app); 2558 } 2559 } 2560 } 2561 } 2562 2563 if ((ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) { 2564 if (adj > PREVIOUS_APP_ADJ) { 2565 adj = PREVIOUS_APP_ADJ; 2566 schedGroup = SCHED_GROUP_BACKGROUND; 2567 state.setAdjType("recent-provider"); 2568 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2569 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2570 "Raise adj to recent provider: " + app); 2571 } 2572 maybeSetProcessFollowUpUpdateLocked(app, 2573 ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME, now); 2574 } 2575 if (procState > PROCESS_STATE_LAST_ACTIVITY) { 2576 procState = PROCESS_STATE_LAST_ACTIVITY; 2577 state.setAdjType("recent-provider"); 2578 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 2579 reportOomAdjMessageLocked(TAG_OOM_ADJ, 2580 "Raise procstate to recent provider: " + app); 2581 } 2582 maybeSetProcessFollowUpUpdateLocked(app, 2583 ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME, now); 2584 } 2585 } 2586 2587 if (procState >= PROCESS_STATE_CACHED_EMPTY) { 2588 if (psr.hasClientActivities()) { 2589 // This is a cached process, but with client activities. Mark it so. 2590 procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT; 2591 state.setAdjType("cch-client-act"); 2592 } else if (psr.isTreatedLikeActivity()) { 2593 // This is a cached process, but somebody wants us to treat it like it has 2594 // an activity, okay! 2595 procState = PROCESS_STATE_CACHED_ACTIVITY; 2596 state.setAdjType("cch-as-act"); 2597 } 2598 } 2599 2600 if (adj == SERVICE_ADJ) { 2601 if (doingAll && !cycleReEval) { 2602 state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3)); 2603 mNewNumServiceProcs++; 2604 if (!state.isServiceB()) { 2605 // This service isn't far enough down on the LRU list to 2606 // normally be a B service, but if we are low on RAM and it 2607 // is large we want to force it down since we would prefer to 2608 // keep launcher over it. 2609 long lastPssOrRss = mService.mAppProfiler.isProfilingPss() 2610 ? app.mProfile.getLastPss() : app.mProfile.getLastRss(); 2611 2612 // RSS is larger than PSS, but the RSS/PSS ratio varies per-process based on how 2613 // many shared pages a process uses. The threshold is increased if the flag for 2614 // reading RSS instead of PSS is enabled. 2615 // 2616 // TODO(b/296454553): Tune the second value so that the relative number of 2617 // service B is similar before/after this flag is enabled. 2618 double thresholdModifier = mService.mAppProfiler.isProfilingPss() 2619 ? 1 : mConstants.PSS_TO_RSS_THRESHOLD_MODIFIER; 2620 double cachedRestoreThreshold = 2621 mProcessList.getCachedRestoreThresholdKb() * thresholdModifier; 2622 2623 if (!isLastMemoryLevelNormal() && lastPssOrRss >= cachedRestoreThreshold) { 2624 state.setServiceHighRam(true); 2625 state.setServiceB(true); 2626 //Slog.i(TAG, "ADJ " + app + " high ram!"); 2627 } else { 2628 mNewNumAServiceProcs++; 2629 //Slog.i(TAG, "ADJ " + app + " not high ram!"); 2630 } 2631 } else { 2632 state.setServiceHighRam(false); 2633 } 2634 } 2635 if (state.isServiceB()) { 2636 adj = SERVICE_B_ADJ; 2637 } 2638 } 2639 2640 // apply capability from FGS. 2641 if (psr.hasForegroundServices()) { 2642 capability |= capabilityFromFGS; 2643 } 2644 2645 capability |= getDefaultCapability(app, procState); 2646 capability |= getCpuCapability(app, now, foregroundActivities); 2647 2648 // Procstates below BFGS should never have this capability. 2649 if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { 2650 capability &= ~PROCESS_CAPABILITY_BFSL; 2651 } 2652 2653 if (app.isPendingFinishAttach()) { 2654 // If the app is still starting up. We reset the computations to the 2655 // hardcoded values in setAttachingProcessStatesLSP. This ensures that the app keeps 2656 // hard-coded default 'startup' oom scores while starting up. When it finishes startup, 2657 // we'll recompute oom scores based on it's actual hosted compoenents. 2658 setAttachingProcessStatesLSP(app); 2659 state.setAdjSeq(mAdjSeq); 2660 state.setCompletedAdjSeq(state.getAdjSeq()); 2661 return false; 2662 } 2663 2664 // Do final modification to adj. Everything we do between here and applying 2665 // the final setAdj must be done in this function, because we will also use 2666 // it when computing the final cached adj later. Note that we don't need to 2667 // worry about this for max adj above, since max adj will always be used to 2668 // keep it out of the cached vaues. 2669 state.setCurCapability(capability); 2670 state.updateLastInvisibleTime(hasVisibleActivities); 2671 state.setHasForegroundActivities(foregroundActivities); 2672 state.setCompletedAdjSeq(mAdjSeq); 2673 2674 schedGroup = setIntermediateAdjLSP(app, adj, prevAppAdj, schedGroup); 2675 setIntermediateProcStateLSP(app, procState, prevProcState); 2676 setIntermediateSchedGroupLSP(state, schedGroup); 2677 2678 // if curAdj or curProcState improved, then this process was promoted 2679 return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState 2680 || state.getCurCapability() != prevCapability; 2681 } 2682 2683 /** 2684 * @return The proposed change to the schedGroup. 2685 */ 2686 @GuardedBy({"mService", "mProcLock"}) setIntermediateAdjLSP(ProcessRecord app, int adj, int prevRawAppAdj, int schedGroup)2687 protected int setIntermediateAdjLSP(ProcessRecord app, int adj, int prevRawAppAdj, 2688 int schedGroup) { 2689 final ProcessStateRecord state = app.mState; 2690 state.setCurRawAdj(adj); 2691 2692 adj = app.mServices.modifyRawOomAdj(adj); 2693 if (adj > state.getMaxAdj()) { 2694 adj = state.getMaxAdj(); 2695 if (adj <= PERCEPTIBLE_LOW_APP_ADJ) { 2696 schedGroup = SCHED_GROUP_DEFAULT; 2697 } 2698 } 2699 2700 state.setCurAdj(adj); 2701 2702 return schedGroup; 2703 } 2704 2705 @GuardedBy({"mService", "mProcLock"}) setIntermediateProcStateLSP(ProcessRecord app, int procState, int prevProcState)2706 protected void setIntermediateProcStateLSP(ProcessRecord app, int procState, 2707 int prevProcState) { 2708 final ProcessStateRecord state = app.mState; 2709 state.setCurProcState(procState); 2710 state.setCurRawProcState(procState); 2711 } 2712 2713 @GuardedBy({"mService", "mProcLock"}) setIntermediateSchedGroupLSP(ProcessStateRecord state, int schedGroup)2714 protected void setIntermediateSchedGroupLSP(ProcessStateRecord state, int schedGroup) { 2715 // Put bound foreground services in a special sched group for additional 2716 // restrictions on screen off 2717 if (state.getCurProcState() >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE 2718 && !isDeviceFullyAwake() 2719 && !state.shouldScheduleLikeTopApp()) { 2720 if (schedGroup > SCHED_GROUP_RESTRICTED) { 2721 schedGroup = SCHED_GROUP_RESTRICTED; 2722 } 2723 } 2724 2725 state.setCurrentSchedulingGroup(schedGroup); 2726 } 2727 2728 @GuardedBy({"mService", "mProcLock"}) computeServiceHostOomAdjLSP(ConnectionRecord cr, ProcessRecord app, ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll, boolean cycleReEval, boolean computeClients, int oomAdjReason, int cachedAdj, boolean couldRecurse, boolean dryRun)2729 public boolean computeServiceHostOomAdjLSP(ConnectionRecord cr, ProcessRecord app, 2730 ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll, 2731 boolean cycleReEval, boolean computeClients, int oomAdjReason, int cachedAdj, 2732 boolean couldRecurse, boolean dryRun) { 2733 if (app.isPendingFinishAttach()) { 2734 // We've set the attaching process state in the computeInitialOomAdjLSP. Skip it here. 2735 return false; 2736 } 2737 2738 final ProcessStateRecord state = app.mState; 2739 ProcessStateRecord cstate = client.mState; 2740 boolean updated = false; 2741 2742 if (couldRecurse) { 2743 if (app.isSdkSandbox && cr.binding.attributedClient != null) { 2744 // For SDK sandboxes, use the attributed client (eg the app that 2745 // requested the sandbox) 2746 client = cr.binding.attributedClient; 2747 cstate = client.mState; 2748 } 2749 if (computeClients) { 2750 computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true, 2751 oomAdjReason, true); 2752 } else { 2753 cstate.setCurRawAdj(cstate.getCurAdj()); 2754 cstate.setCurRawProcState(cstate.getCurProcState()); 2755 } 2756 } 2757 2758 int clientAdj = cstate.getCurRawAdj(); 2759 int clientProcState = cstate.getCurRawProcState(); 2760 2761 final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP; 2762 2763 int adj = state.getCurRawAdj(); 2764 int procState = state.getCurRawProcState(); 2765 int schedGroup = state.getCurrentSchedulingGroup(); 2766 int capability = state.getCurCapability(); 2767 2768 final int prevRawAdj = adj; 2769 final int prevProcState = procState; 2770 final int prevSchedGroup = schedGroup; 2771 final int prevCapability = capability; 2772 2773 final int appUid = app.info.uid; 2774 final int logUid = mService.mCurOomAdjUid; 2775 2776 if (!dryRun) { 2777 state.setCurBoundByNonBgRestrictedApp(state.isCurBoundByNonBgRestrictedApp() 2778 || cstate.isCurBoundByNonBgRestrictedApp() 2779 || clientProcState <= PROCESS_STATE_BOUND_TOP 2780 || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE 2781 && !cstate.isBackgroundRestricted())); 2782 } 2783 2784 if (client.mOptRecord.shouldNotFreeze()) { 2785 // Propagate the shouldNotFreeze flag down the bindings. 2786 if (app.mOptRecord.setShouldNotFreeze(true, dryRun, 2787 app.mOptRecord.shouldNotFreezeReason() 2788 | client.mOptRecord.shouldNotFreezeReason(), mAdjSeq)) { 2789 if (Flags.useCpuTimeCapability()) { 2790 // Do nothing, capability updated check will handle the dryrun output. 2791 } else { 2792 // Bail out early, as we only care about the return value for a dryrun. 2793 return true; 2794 } 2795 } 2796 } 2797 2798 boolean trackedProcState = false; 2799 2800 // We always propagate PROCESS_CAPABILITY_BFSL over bindings here, 2801 // but, right before actually setting it to the process, 2802 // we check the final procstate, and remove it if the procsate is below BFGS. 2803 capability |= getBfslCapabilityFromClient(client); 2804 2805 capability |= getCpuCapabilityFromClient(cr, client); 2806 2807 if (cr.notHasFlag(Context.BIND_WAIVE_PRIORITY)) { 2808 if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { 2809 capability |= cstate.getCurCapability(); 2810 } 2811 2812 // If an app has network capability by default 2813 // (by having procstate <= BFGS), then the apps it binds to will get 2814 // elevated to a high enough procstate anyway to get network unless they 2815 // request otherwise, so don't propagate the network capability by default 2816 // in this case unless they explicitly request it. 2817 if ((cstate.getCurCapability() 2818 & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) { 2819 if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { 2820 // This is used to grant network access to Expedited Jobs. 2821 if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) { 2822 capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK; 2823 } 2824 } else { 2825 capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK; 2826 } 2827 } 2828 if ((cstate.getCurCapability() 2829 & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0) { 2830 if (clientProcState <= PROCESS_STATE_IMPORTANT_FOREGROUND) { 2831 // This is used to grant network access to User Initiated Jobs. 2832 if (cr.hasFlag(Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)) { 2833 capability |= PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK; 2834 } 2835 } 2836 } 2837 2838 // Sandbox should be able to control audio only when bound client 2839 // has this capability. 2840 if ((cstate.getCurCapability() 2841 & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0) { 2842 if (app.isSdkSandbox) { 2843 capability |= PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL; 2844 } 2845 } 2846 2847 if (couldRecurse && shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) { 2848 return false; 2849 } 2850 2851 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { 2852 // If the other app is cached for any reason, for purposes here 2853 // we are going to consider it empty. The specific cached state 2854 // doesn't propagate except under certain conditions. 2855 clientProcState = PROCESS_STATE_CACHED_EMPTY; 2856 } 2857 String adjType = null; 2858 if (cr.hasFlag(Context.BIND_ALLOW_OOM_MANAGEMENT)) { 2859 // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen. 2860 if (clientAdj < CACHED_APP_MIN_ADJ) { 2861 if (app.mOptRecord.setShouldNotFreeze(true, dryRun, 2862 app.mOptRecord.shouldNotFreezeReason() 2863 | ProcessCachedOptimizerRecord 2864 .SHOULD_NOT_FREEZE_REASON_BINDER_ALLOW_OOM_MANAGEMENT, mAdjSeq)) { 2865 if (Flags.useCpuTimeCapability()) { 2866 // Do nothing, capability updated check will handle the dryrun output. 2867 } else { 2868 // Bail out early, as we only care about the return value for a dryrun. 2869 return true; 2870 } 2871 } 2872 } 2873 // Not doing bind OOM management, so treat 2874 // this guy more like a started service. 2875 if (state.hasShownUi() && !state.getCachedIsHomeProcess()) { 2876 // If this process has shown some UI, let it immediately 2877 // go to the LRU list because it may be pretty heavy with 2878 // UI stuff. We'll tag it with a label just to help 2879 // debug and understand what is going on. 2880 if (adj > clientAdj) { 2881 adjType = "cch-bound-ui-services"; 2882 } 2883 2884 if (state.isCached() && dryRun) { 2885 // Bail out early, as we only care about the return value for a dryrun. 2886 return true; 2887 } 2888 2889 clientAdj = adj; 2890 clientProcState = procState; 2891 } else { 2892 if (now >= (cr.binding.service.lastActivity 2893 + mConstants.MAX_SERVICE_INACTIVITY)) { 2894 // This service has not seen activity within 2895 // recent memory, so allow it to drop to the 2896 // LRU list if there is no other reason to keep 2897 // it around. We'll also tag it with a label just 2898 // to help debug and undertand what is going on. 2899 if (adj > clientAdj) { 2900 adjType = "cch-bound-services"; 2901 } 2902 clientAdj = adj; 2903 } 2904 } 2905 } 2906 if (adj > clientAdj) { 2907 // If this process has recently shown UI, and the process that is binding to it 2908 // is less important than a state that can be actively running, then we don't 2909 // care about the binding as much as we care about letting this process get into 2910 // the LRU list to be killed and restarted if needed for memory. 2911 if (state.hasShownUi() && !state.getCachedIsHomeProcess() 2912 && clientAdj > CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD) { 2913 if (adj >= CACHED_APP_MIN_ADJ) { 2914 adjType = "cch-bound-ui-services"; 2915 } 2916 } else { 2917 int newAdj; 2918 int lbAdj = VISIBLE_APP_ADJ; // lower bound of adj. 2919 if (cr.hasFlag(Context.BIND_ABOVE_CLIENT 2920 | Context.BIND_IMPORTANT)) { 2921 if (clientAdj >= PERSISTENT_SERVICE_ADJ) { 2922 newAdj = clientAdj; 2923 } else { 2924 // make this service persistent 2925 newAdj = PERSISTENT_SERVICE_ADJ; 2926 schedGroup = SCHED_GROUP_DEFAULT; 2927 procState = ActivityManager.PROCESS_STATE_PERSISTENT; 2928 if (!dryRun) { 2929 cr.trackProcState(procState, mAdjSeq); 2930 } 2931 trackedProcState = true; 2932 } 2933 } else if (cr.hasFlag(Context.BIND_NOT_PERCEPTIBLE) 2934 && clientAdj <= PERCEPTIBLE_APP_ADJ 2935 && adj >= (lbAdj = PERCEPTIBLE_LOW_APP_ADJ)) { 2936 newAdj = PERCEPTIBLE_LOW_APP_ADJ; 2937 } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE) 2938 && cr.notHasFlag(Context.BIND_NOT_FOREGROUND) 2939 && clientAdj < PERCEPTIBLE_APP_ADJ 2940 && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) { 2941 // This is for user-initiated jobs. 2942 // We use APP_ADJ + 1 here, so we can tell them apart from FGS. 2943 newAdj = PERCEPTIBLE_APP_ADJ + 1; 2944 } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE) 2945 && cr.hasFlag(Context.BIND_NOT_FOREGROUND) 2946 && clientAdj < PERCEPTIBLE_APP_ADJ 2947 && adj >= (lbAdj = (PERCEPTIBLE_MEDIUM_APP_ADJ + 2))) { 2948 // This is for expedited jobs. 2949 // We use MEDIUM_APP_ADJ + 2 here, so we can tell apart 2950 // EJ and short-FGS. 2951 newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 2; 2952 } else if (cr.hasFlag(Context.BIND_NOT_VISIBLE) 2953 && clientAdj < PERCEPTIBLE_APP_ADJ 2954 && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) { 2955 newAdj = PERCEPTIBLE_APP_ADJ; 2956 } else if (clientAdj >= PERCEPTIBLE_APP_ADJ) { 2957 newAdj = clientAdj; 2958 } else if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE) 2959 && clientAdj <= VISIBLE_APP_ADJ 2960 && adj > VISIBLE_APP_ADJ) { 2961 newAdj = VISIBLE_APP_ADJ; 2962 } else { 2963 if (adj > VISIBLE_APP_ADJ) { 2964 // TODO: Is this too limiting for apps bound from TOP? 2965 newAdj = Math.max(clientAdj, lbAdj); 2966 } else { 2967 newAdj = adj; 2968 } 2969 } 2970 2971 if (!cstate.isCached()) { 2972 if (state.isCached() && dryRun) { 2973 // Bail out early, as we only care about the return value for a dryrun. 2974 return true; 2975 } 2976 } 2977 2978 if (newAdj == clientAdj && app.isolated) { 2979 // Make bound isolated processes have slightly worse score than their client 2980 newAdj = clientAdj + 1; 2981 } 2982 2983 if (adj > newAdj) { 2984 adj = newAdj; 2985 if (state.setCurRawAdj(adj, dryRun)) { 2986 // Bail out early, as we only care about the return value for a dryrun. 2987 } 2988 adjType = "service"; 2989 } 2990 } 2991 } 2992 if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND 2993 | Context.BIND_IMPORTANT_BACKGROUND)) { 2994 // This will treat important bound services identically to 2995 // the top app, which may behave differently than generic 2996 // foreground work. 2997 final int curSchedGroup = cstate.getCurrentSchedulingGroup(); 2998 if (curSchedGroup > schedGroup) { 2999 if (cr.hasFlag(Context.BIND_IMPORTANT)) { 3000 schedGroup = curSchedGroup; 3001 } else { 3002 schedGroup = SCHED_GROUP_DEFAULT; 3003 } 3004 } 3005 if (clientProcState < PROCESS_STATE_TOP) { 3006 // Special handling for above-top states (persistent 3007 // processes). These should not bring the current process 3008 // into the top state, since they are not on top. Instead 3009 // give them the best bound state after that. 3010 if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) { 3011 clientProcState = PROCESS_STATE_FOREGROUND_SERVICE; 3012 } else if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) { 3013 clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 3014 } else if (isDeviceFullyAwake() 3015 && cr.hasFlag(Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) { 3016 clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 3017 } else { 3018 clientProcState = 3019 PROCESS_STATE_IMPORTANT_FOREGROUND; 3020 } 3021 } else if (clientProcState == PROCESS_STATE_TOP) { 3022 // Go at most to BOUND_TOP, unless requested to elevate 3023 // to client's state. 3024 clientProcState = PROCESS_STATE_BOUND_TOP; 3025 final boolean enabled = cstate.getCachedCompatChange( 3026 CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY); 3027 if (enabled) { 3028 if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { 3029 // TOP process passes all capabilities to the service. 3030 capability |= cstate.getCurCapability(); 3031 } else { 3032 // TOP process passes no capability to the service. 3033 } 3034 } else { 3035 // TOP process passes all capabilities to the service. 3036 capability |= cstate.getCurCapability(); 3037 } 3038 } 3039 } else if (cr.notHasFlag(Context.BIND_IMPORTANT_BACKGROUND)) { 3040 if (clientProcState < PROCESS_STATE_TRANSIENT_BACKGROUND) { 3041 clientProcState = 3042 PROCESS_STATE_TRANSIENT_BACKGROUND; 3043 } 3044 } else { 3045 if (clientProcState < PROCESS_STATE_IMPORTANT_BACKGROUND) { 3046 clientProcState = 3047 PROCESS_STATE_IMPORTANT_BACKGROUND; 3048 } 3049 } 3050 3051 if (cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP) && clientIsSystem) { 3052 schedGroup = SCHED_GROUP_TOP_APP; 3053 if (dryRun) { 3054 if (prevSchedGroup < schedGroup) { 3055 // Bail out early, as we only care about the return value for a dryrun. 3056 return true; 3057 } 3058 } else { 3059 state.setScheduleLikeTopApp(true); 3060 } 3061 } 3062 3063 if (!trackedProcState && !dryRun) { 3064 cr.trackProcState(clientProcState, mAdjSeq); 3065 } 3066 3067 if (procState > clientProcState) { 3068 procState = clientProcState; 3069 if (state.setCurRawProcState(procState, dryRun)) { 3070 // Bail out early, as we only care about the return value for a dryrun. 3071 return true; 3072 } 3073 if (adjType == null) { 3074 adjType = "service"; 3075 } 3076 } 3077 if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND 3078 && cr.hasFlag(Context.BIND_SHOWING_UI) && !dryRun) { 3079 app.setPendingUiClean(true); 3080 } 3081 if (adjType != null && !dryRun) { 3082 state.setAdjType(adjType); 3083 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo 3084 .REASON_SERVICE_IN_USE); 3085 state.setAdjSource(client); 3086 state.setAdjSourceProcState(clientProcState); 3087 state.setAdjTarget(cr.binding.service.instanceName); 3088 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 3089 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType 3090 + ": " + app + ", due to " + client 3091 + " adj=" + adj + " procState=" 3092 + ProcessList.makeProcStateString(procState)); 3093 } 3094 } 3095 } else { // BIND_WAIVE_PRIORITY == true 3096 // BIND_WAIVE_PRIORITY bindings are special when it comes to the 3097 // freezer. Processes bound via WPRI are expected to be running, 3098 // but they are not promoted in the LRU list to keep them out of 3099 // cached. As a result, they can freeze based on oom_adj alone. 3100 // Normally, bindToDeath would fire when a cached app would die 3101 // in the background, but nothing will fire when a running process 3102 // pings a frozen process. Accordingly, any cached app that is 3103 // bound by an unfrozen app via a WPRI binding has to remain 3104 // unfrozen. 3105 if (clientAdj < CACHED_APP_MIN_ADJ) { 3106 if (app.mOptRecord.setShouldNotFreeze(true, dryRun, 3107 app.mOptRecord.shouldNotFreezeReason() 3108 | ProcessCachedOptimizerRecord 3109 .SHOULD_NOT_FREEZE_REASON_BIND_WAIVE_PRIORITY, mAdjSeq)) { 3110 if (Flags.useCpuTimeCapability()) { 3111 // Do nothing, capability updated check will handle the dryrun output. 3112 } else { 3113 // Bail out early, as we only care about the return value for a dryrun. 3114 return true; 3115 } 3116 } 3117 } 3118 } 3119 if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) { 3120 if (!dryRun) { 3121 app.mServices.setTreatLikeActivity(true); 3122 } 3123 if (clientProcState <= PROCESS_STATE_CACHED_ACTIVITY 3124 && procState > PROCESS_STATE_CACHED_ACTIVITY) { 3125 // This is a cached process, but somebody wants us to treat it like it has 3126 // an activity, okay! 3127 procState = PROCESS_STATE_CACHED_ACTIVITY; 3128 state.setAdjType("cch-as-act"); 3129 } 3130 } 3131 final ActivityServiceConnectionsHolder a = cr.activity; 3132 if (cr.hasFlag(Context.BIND_ADJUST_WITH_ACTIVITY)) { 3133 if (a != null && adj > FOREGROUND_APP_ADJ 3134 && a.isActivityVisible()) { 3135 adj = FOREGROUND_APP_ADJ; 3136 if (state.setCurRawAdj(adj, dryRun)) { 3137 return true; 3138 } 3139 if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND)) { 3140 if (cr.hasFlag(Context.BIND_IMPORTANT)) { 3141 schedGroup = SCHED_GROUP_TOP_APP_BOUND; 3142 } else { 3143 schedGroup = SCHED_GROUP_DEFAULT; 3144 } 3145 } 3146 3147 if (!dryRun) { 3148 state.setAdjType("service"); 3149 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo 3150 .REASON_SERVICE_IN_USE); 3151 state.setAdjSource(a); 3152 state.setAdjSourceProcState(procState); 3153 state.setAdjTarget(cr.binding.service.instanceName); 3154 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 3155 reportOomAdjMessageLocked(TAG_OOM_ADJ, 3156 "Raise to service w/activity: " + app); 3157 } 3158 } 3159 } 3160 } 3161 3162 capability |= getDefaultCapability(app, procState); 3163 3164 // Procstates below BFGS should never have this capability. 3165 if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { 3166 capability &= ~PROCESS_CAPABILITY_BFSL; 3167 } 3168 if (!updated) { 3169 if (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup) { 3170 updated = true; 3171 } 3172 3173 if (Flags.useCpuTimeCapability()) { 3174 if ((capability != prevCapability) 3175 && ((capability & prevCapability) == prevCapability)) { 3176 updated = true; 3177 } 3178 } else { 3179 // Ignore PROCESS_CAPABILITY_CPU_TIME in capability comparison 3180 final int curFiltered = capability & ~PROCESS_CAPABILITY_CPU_TIME; 3181 final int prevFiltered = prevCapability & ~PROCESS_CAPABILITY_CPU_TIME; 3182 if ((curFiltered != prevFiltered) 3183 && ((curFiltered & prevFiltered) == prevFiltered)) { 3184 updated = true; 3185 } 3186 } 3187 } 3188 3189 if (dryRun) { 3190 return updated; 3191 } 3192 if (adj < prevRawAdj) { 3193 schedGroup = setIntermediateAdjLSP(app, adj, prevRawAdj, schedGroup); 3194 } 3195 if (procState < prevProcState) { 3196 setIntermediateProcStateLSP(app, procState, prevProcState); 3197 } 3198 if (schedGroup > prevSchedGroup) { 3199 setIntermediateSchedGroupLSP(state, schedGroup); 3200 } 3201 state.setCurCapability(capability); 3202 3203 return updated; 3204 } 3205 3206 /** 3207 * Computes the impact on {@code app} the provider connections from {@code client} has. 3208 */ 3209 @GuardedBy({"mService", "mProcLock"}) computeProviderHostOomAdjLSP(ContentProviderConnection conn, ProcessRecord app, ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll, boolean cycleReEval, boolean computeClients, int oomAdjReason, int cachedAdj, boolean couldRecurse, boolean dryRun)3210 public boolean computeProviderHostOomAdjLSP(ContentProviderConnection conn, 3211 ProcessRecord app, ProcessRecord client, long now, ProcessRecord topApp, 3212 boolean doingAll, boolean cycleReEval, boolean computeClients, int oomAdjReason, 3213 int cachedAdj, boolean couldRecurse, boolean dryRun) { 3214 if (app.isPendingFinishAttach()) { 3215 // We've set the attaching process state in the computeInitialOomAdjLSP. Skip it here. 3216 return false; 3217 } 3218 3219 final ProcessStateRecord state = app.mState; 3220 final ProcessStateRecord cstate = client.mState; 3221 3222 if (client == app) { 3223 // Being our own client is not interesting. 3224 return false; 3225 } 3226 if (couldRecurse) { 3227 if (computeClients) { 3228 computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true, 3229 oomAdjReason, true); 3230 } else if (couldRecurse) { 3231 cstate.setCurRawAdj(cstate.getCurAdj()); 3232 cstate.setCurRawProcState(cstate.getCurProcState()); 3233 } 3234 3235 if (shouldSkipDueToCycle(app, cstate, state.getCurRawProcState(), state.getCurRawAdj(), 3236 cycleReEval)) { 3237 return false; 3238 } 3239 } 3240 3241 int clientAdj = cstate.getCurRawAdj(); 3242 int clientProcState = cstate.getCurRawProcState(); 3243 3244 int adj = state.getCurRawAdj(); 3245 int procState = state.getCurRawProcState(); 3246 int schedGroup = state.getCurrentSchedulingGroup(); 3247 int capability = state.getCurCapability(); 3248 3249 final int prevRawAdj = adj; 3250 final int prevProcState = procState; 3251 final int prevSchedGroup = schedGroup; 3252 final int prevCapability = capability; 3253 3254 final int appUid = app.info.uid; 3255 final int logUid = mService.mCurOomAdjUid; 3256 3257 // We always propagate PROCESS_CAPABILITY_BFSL to providers here, 3258 // but, right before actually setting it to the process, 3259 // we check the final procstate, and remove it if the procsate is below BFGS. 3260 capability |= getBfslCapabilityFromClient(client); 3261 3262 capability |= getCpuCapabilityFromClient(conn, client); 3263 3264 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { 3265 // If the other app is cached for any reason, for purposes here 3266 // we are going to consider it empty. 3267 clientProcState = PROCESS_STATE_CACHED_EMPTY; 3268 } 3269 if (client.mOptRecord.shouldNotFreeze()) { 3270 // Propagate the shouldNotFreeze flag down the bindings. 3271 if (app.mOptRecord.setShouldNotFreeze(true, dryRun, 3272 app.mOptRecord.shouldNotFreezeReason() 3273 | client.mOptRecord.shouldNotFreezeReason(), mAdjSeq)) { 3274 if (Flags.useCpuTimeCapability()) { 3275 // Do nothing, capability updated check will handle the dryrun output. 3276 } else { 3277 // Bail out early, as we only care about the return value for a dryrun. 3278 return true; 3279 } 3280 } 3281 } 3282 3283 if (!dryRun) { 3284 state.setCurBoundByNonBgRestrictedApp(state.isCurBoundByNonBgRestrictedApp() 3285 || cstate.isCurBoundByNonBgRestrictedApp() 3286 || clientProcState <= PROCESS_STATE_BOUND_TOP 3287 || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE 3288 && !cstate.isBackgroundRestricted())); 3289 } 3290 3291 String adjType = null; 3292 if (adj > clientAdj) { 3293 if (state.hasShownUi() && !state.getCachedIsHomeProcess() 3294 && clientAdj > PERCEPTIBLE_APP_ADJ) { 3295 adjType = "cch-ui-provider"; 3296 } else { 3297 adj = Math.max(clientAdj, FOREGROUND_APP_ADJ); 3298 if (state.setCurRawAdj(adj, dryRun)) { 3299 // Bail out early, as we only care about the return value for a dryrun. 3300 return true; 3301 } 3302 adjType = "provider"; 3303 } 3304 3305 if (state.isCached() && !cstate.isCached() && dryRun) { 3306 // Bail out early, as we only care about the return value for a dryrun. 3307 return true; 3308 } 3309 } 3310 3311 if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) { 3312 if (adjType == null) { 3313 adjType = "provider"; 3314 } 3315 if (clientProcState == PROCESS_STATE_TOP) { 3316 clientProcState = PROCESS_STATE_BOUND_TOP; 3317 } else { 3318 clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 3319 } 3320 } 3321 3322 if (!dryRun) { 3323 conn.trackProcState(clientProcState, mAdjSeq); 3324 } 3325 if (procState > clientProcState) { 3326 procState = clientProcState; 3327 if (state.setCurRawProcState(procState, dryRun)) { 3328 // Bail out early, as we only care about the return value for a dryrun. 3329 return true; 3330 } 3331 } 3332 if (cstate.getCurrentSchedulingGroup() > schedGroup) { 3333 schedGroup = SCHED_GROUP_DEFAULT; 3334 } 3335 if (adjType != null && !dryRun) { 3336 state.setAdjType(adjType); 3337 state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo 3338 .REASON_PROVIDER_IN_USE); 3339 state.setAdjSource(client); 3340 state.setAdjSourceProcState(clientProcState); 3341 state.setAdjTarget(conn.provider.name); 3342 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { 3343 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType 3344 + ": " + app + ", due to " + client 3345 + " adj=" + adj + " procState=" 3346 + ProcessList.makeProcStateString(procState)); 3347 } 3348 } 3349 3350 // Procstates below BFGS should never have this capability. 3351 if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { 3352 capability &= ~PROCESS_CAPABILITY_BFSL; 3353 } 3354 3355 if (dryRun) { 3356 if (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup) { 3357 return true; 3358 } 3359 3360 if (Flags.useCpuTimeCapability()) { 3361 if ((capability != prevCapability) 3362 && ((capability & prevCapability) == prevCapability)) { 3363 return true; 3364 } 3365 } else { 3366 // Ignore PROCESS_CAPABILITY_CPU_TIME in capability comparison 3367 final int curFiltered = capability & ~PROCESS_CAPABILITY_CPU_TIME; 3368 final int prevFiltered = prevCapability & ~PROCESS_CAPABILITY_CPU_TIME; 3369 if ((curFiltered != prevFiltered) 3370 && ((curFiltered & prevFiltered) == prevFiltered)) { 3371 return true; 3372 } 3373 } 3374 } 3375 3376 if (adj < prevRawAdj) { 3377 schedGroup = setIntermediateAdjLSP(app, adj, prevRawAdj, schedGroup); 3378 } 3379 if (procState < prevProcState) { 3380 setIntermediateProcStateLSP(app, procState, prevProcState); 3381 } 3382 if (schedGroup > prevSchedGroup) { 3383 setIntermediateSchedGroupLSP(state, schedGroup); 3384 } 3385 state.setCurCapability(capability); 3386 3387 return false; 3388 } 3389 getDefaultCapability(ProcessRecord app, int procState)3390 protected int getDefaultCapability(ProcessRecord app, int procState) { 3391 final int networkCapabilities = 3392 NetworkPolicyManager.getDefaultProcessNetworkCapabilities(procState); 3393 final int baseCapabilities; 3394 switch (procState) { 3395 case PROCESS_STATE_PERSISTENT: 3396 case PROCESS_STATE_PERSISTENT_UI: 3397 case PROCESS_STATE_TOP: 3398 baseCapabilities = PROCESS_CAPABILITY_ALL; // BFSL allowed 3399 break; 3400 case PROCESS_STATE_BOUND_TOP: 3401 if (app.getActiveInstrumentation() != null) { 3402 baseCapabilities = PROCESS_CAPABILITY_BFSL | 3403 PROCESS_CAPABILITY_ALL_IMPLICIT; 3404 } else { 3405 baseCapabilities = PROCESS_CAPABILITY_BFSL; 3406 } 3407 break; 3408 case PROCESS_STATE_FOREGROUND_SERVICE: 3409 if (app.getActiveInstrumentation() != null) { 3410 baseCapabilities = PROCESS_CAPABILITY_ALL_IMPLICIT; 3411 } else { 3412 // Capability from foreground service is conditional depending on 3413 // foregroundServiceType in the manifest file and the 3414 // mAllowWhileInUsePermissionInFgs flag. 3415 baseCapabilities = PROCESS_CAPABILITY_NONE; 3416 } 3417 break; 3418 default: 3419 baseCapabilities = PROCESS_CAPABILITY_NONE; 3420 break; 3421 } 3422 return baseCapabilities | networkCapabilities; 3423 } 3424 getCpuCapability(ProcessRecord app, long nowUptime, boolean hasForegroundActivities)3425 private static int getCpuCapability(ProcessRecord app, long nowUptime, 3426 boolean hasForegroundActivities) { 3427 // Note: persistent processes get all capabilities, including CPU_TIME. 3428 final UidRecord uidRec = app.getUidRecord(); 3429 if (uidRec != null && uidRec.isCurAllowListed()) { 3430 // Process is in the power allowlist. 3431 return PROCESS_CAPABILITY_CPU_TIME; 3432 } 3433 if (hasForegroundActivities) { 3434 // TODO: b/402987519 - This grants the Top Sleeping process CPU_TIME but eventually 3435 // should not. 3436 // Process has user perceptible activities. 3437 return PROCESS_CAPABILITY_CPU_TIME; 3438 } 3439 if (Flags.prototypeAggressiveFreezing()) { 3440 if (app.mServices.hasUndemotedShortForegroundService(nowUptime)) { 3441 // Grant cpu time for short FGS even when aggressively freezing. 3442 return PROCESS_CAPABILITY_CPU_TIME; 3443 } 3444 } else if (app.mServices.hasForegroundServices()) { 3445 return PROCESS_CAPABILITY_CPU_TIME; 3446 } 3447 if (app.mReceivers.numberOfCurReceivers() > 0) { 3448 return PROCESS_CAPABILITY_CPU_TIME; 3449 } 3450 if (app.hasActiveInstrumentation()) { 3451 return PROCESS_CAPABILITY_CPU_TIME; 3452 } 3453 // TODO(b/370817323): Populate this method with all of the reasons to keep a process 3454 // unfrozen. 3455 return 0; 3456 } 3457 3458 /** 3459 * @return the BFSL capability from a client (of a service binding or provider). 3460 */ getBfslCapabilityFromClient(ProcessRecord client)3461 protected int getBfslCapabilityFromClient(ProcessRecord client) { 3462 // Procstates above FGS should always have this flag. We shouldn't need this logic, 3463 // but let's do it just in case. 3464 if (client.mState.getCurProcState() < PROCESS_STATE_FOREGROUND_SERVICE) { 3465 return PROCESS_CAPABILITY_BFSL; 3466 } 3467 // Otherwise, use the process's cur capability. 3468 3469 // Note: BFSL is a per-UID check, not per-process, but here, the BFSL capability is still 3470 // propagated on a per-process basis. 3471 // 3472 // For example, consider this case: 3473 // - There are App 1 and App 2. 3474 // - App 1 has two processes 3475 // Proc #1A, procstate BFGS with CAPABILITY_BFSL 3476 // Proc #1B, procstate FGS with no CAPABILITY_BFSL (i.e. process has a short FGS) 3477 // And this process binds to Proc #2 of App 2. 3478 // 3479 // (Note because #1A has CAPABILITY_BFSL, App 1's UidRecord has CAPABILITY_BFSL.) 3480 // 3481 // - App 2 has one process: 3482 // Proc #2, procstate FGS due to the above binding, _with no CAPABILITY_BFSL_. 3483 // 3484 // In this case, #2 will not get CAPABILITY_BFSL because the binding client (#1B) 3485 // doesn't have this capability. (Even though App 1's UidRecord has it.) 3486 // 3487 // This may look weird, because App 2 _is_ still BFSL allowed, because "it's bound by 3488 // an app that is BFSL-allowed". (See [bookmark: 61867f60-007c-408c-a2c4-e19e96056135] 3489 // in ActiveServices.) 3490 // 3491 // So why don't we propagate PROCESS_CAPABILITY_BFSL from App 1's UID record? 3492 // This is because short-FGS acts like "below BFGS" as far as BFSL is concerned, 3493 // similar to how JobScheduler jobs are below BFGS and apps can't start FGS from there. 3494 // 3495 // If #1B was running a job instead of a short-FGS, then its procstate would be below BFGS. 3496 // Then #2's procstate would also be below BFGS. So #2 wouldn't get CAPABILITY_BFSL. 3497 // Similarly, if #1B has a short FGS, even though the procstate of #1B and #2 would be FGS, 3498 // they both still wouldn't get CAPABILITY_BFSL. 3499 // 3500 // However, again, because #2 is bound by App 1, which is BFSL-allowed (because of #1A) 3501 // App 2 would still BFSL-allowed, due to the aforementioned check in ActiveServices. 3502 return client.mState.getCurCapability() & PROCESS_CAPABILITY_BFSL; 3503 } 3504 3505 /** 3506 * @return the CPU capability from a client (of a service binding or provider). 3507 */ getCpuCapabilityFromClient(OomAdjusterModernImpl.Connection conn, ProcessRecord client)3508 private static int getCpuCapabilityFromClient(OomAdjusterModernImpl.Connection conn, 3509 ProcessRecord client) { 3510 if (conn == null || conn.transmitsCpuTime()) { 3511 return client.mState.getCurCapability() & PROCESS_CAPABILITY_CPU_TIME; 3512 } else { 3513 return 0; 3514 } 3515 } 3516 3517 /** 3518 * Checks if for the given app and client, there's a cycle that should skip over the client 3519 * for now or use partial values to evaluate the effect of the client binding. 3520 * @param app 3521 * @param client 3522 * @param procState procstate evaluated so far for this app 3523 * @param adj oom_adj evaluated so far for this app 3524 * @param cycleReEval whether we're currently re-evaluating due to a cycle, and not the first 3525 * evaluation. 3526 * @return whether to skip using the client connection at this time 3527 */ shouldSkipDueToCycle(ProcessRecord app, ProcessStateRecord client, int procState, int adj, boolean cycleReEval)3528 private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessStateRecord client, 3529 int procState, int adj, boolean cycleReEval) { 3530 if (client.containsCycle()) { 3531 // We've detected a cycle. We should retry computeOomAdjLSP later in 3532 // case a later-checked connection from a client would raise its 3533 // priority legitimately. 3534 app.mState.setContainsCycle(true); 3535 mProcessesInCycle.add(app); 3536 // If the client has not been completely evaluated, check if it's worth 3537 // using the partial values. 3538 if (client.getCompletedAdjSeq() < mAdjSeq) { 3539 if (cycleReEval) { 3540 // If the partial values are no better, skip until the next 3541 // attempt 3542 if (client.getCurRawProcState() >= procState 3543 && client.getCurRawAdj() >= adj 3544 && (client.getCurCapability() & app.mState.getCurCapability()) 3545 == client.getCurCapability()) { 3546 return true; 3547 } 3548 // Else use the client's partial procstate and adj to adjust the 3549 // effect of the binding 3550 } else { 3551 return false; 3552 } 3553 } 3554 } 3555 return false; 3556 } 3557 3558 /** Inform the oomadj observer of changes to oomadj. Used by tests. */ 3559 @GuardedBy("mService") reportOomAdjMessageLocked(String tag, String msg)3560 protected void reportOomAdjMessageLocked(String tag, String msg) { 3561 Slog.d(tag, msg); 3562 synchronized (mService.mOomAdjObserverLock) { 3563 if (mService.mCurOomAdjObserver != null) { 3564 mService.mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg) 3565 .sendToTarget(); 3566 } 3567 } 3568 } 3569 onWakefulnessChanged(int wakefulness)3570 void onWakefulnessChanged(int wakefulness) { 3571 mCachedAppOptimizer.onWakefulnessChanged(wakefulness); 3572 } 3573 3574 @GuardedBy({"mService", "mProcLock"}) applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, long nowElapsed, @OomAdjReason int oomAdjReason)3575 protected boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, 3576 long nowElapsed, @OomAdjReason int oomAdjReason) { 3577 return applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, false); 3578 } 3579 3580 /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */ 3581 @GuardedBy({"mService", "mProcLock"}) applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, long nowElapsed, @OomAdjReason int oomAdjReson, boolean isBatchingOomAdj)3582 protected boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, 3583 long nowElapsed, @OomAdjReason int oomAdjReson, boolean isBatchingOomAdj) { 3584 boolean success = true; 3585 final ProcessStateRecord state = app.mState; 3586 final UidRecord uidRec = app.getUidRecord(); 3587 3588 if (state.getCurRawAdj() != state.getSetRawAdj()) { 3589 state.setSetRawAdj(state.getCurRawAdj()); 3590 } 3591 3592 int changes = 0; 3593 3594 if (state.getCurAdj() != state.getSetAdj()) { 3595 mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app); 3596 } 3597 3598 final int oldOomAdj = state.getSetAdj(); 3599 if (state.getCurAdj() != state.getSetAdj()) { 3600 if (isBatchingOomAdj && mConstants.ENABLE_BATCHING_OOM_ADJ) { 3601 mProcsToOomAdj.add(app); 3602 } else { 3603 mInjector.setOomAdj(app.getPid(), app.uid, state.getCurAdj()); 3604 } 3605 3606 if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { 3607 String msg = "Set " + app.getPid() + " " + app.processName + " adj " 3608 + state.getCurAdj() + ": " + state.getAdjType(); 3609 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); 3610 } 3611 state.setSetAdj(state.getCurAdj()); 3612 if (uidRec != null) { 3613 uidRec.noteProcAdjChanged(); 3614 } 3615 state.setVerifiedAdj(INVALID_ADJ); 3616 } 3617 3618 final int curSchedGroup = state.getCurrentSchedulingGroup(); 3619 if (app.getWaitingToKill() != null && app.mReceivers.numberOfCurReceivers() == 0 3620 && ActivityManager.isProcStateBackground(state.getCurProcState()) 3621 && !state.hasStartedServices()) { 3622 app.killLocked(app.getWaitingToKill(), ApplicationExitInfo.REASON_USER_REQUESTED, 3623 ApplicationExitInfo.SUBREASON_REMOVE_TASK, true); 3624 success = false; 3625 } else if (state.getSetSchedGroup() != curSchedGroup) { 3626 int oldSchedGroup = state.getSetSchedGroup(); 3627 state.setSetSchedGroup(curSchedGroup); 3628 if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) { 3629 String msg = "Setting sched group of " + app.processName 3630 + " to " + curSchedGroup + ": " + state.getAdjType(); 3631 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); 3632 } 3633 int processGroup; 3634 switch (curSchedGroup) { 3635 case SCHED_GROUP_BACKGROUND: 3636 processGroup = THREAD_GROUP_BACKGROUND; 3637 break; 3638 case SCHED_GROUP_TOP_APP: 3639 case SCHED_GROUP_TOP_APP_BOUND: 3640 processGroup = THREAD_GROUP_TOP_APP; 3641 break; 3642 case SCHED_GROUP_RESTRICTED: 3643 processGroup = THREAD_GROUP_RESTRICTED; 3644 break; 3645 case SCHED_GROUP_FOREGROUND_WINDOW: 3646 processGroup = THREAD_GROUP_FOREGROUND_WINDOW; 3647 break; 3648 default: 3649 processGroup = THREAD_GROUP_DEFAULT; 3650 break; 3651 } 3652 setAppAndChildProcessGroup(app, processGroup); 3653 try { 3654 final int renderThreadTid = app.getRenderThreadTid(); 3655 if (curSchedGroup == SCHED_GROUP_TOP_APP) { 3656 // do nothing if we already switched to RT 3657 if (oldSchedGroup != SCHED_GROUP_TOP_APP) { 3658 app.getWindowProcessController().onTopProcChanged(); 3659 if (app.useFifoUiScheduling()) { 3660 // Switch UI pipeline for app to SCHED_FIFO 3661 state.setSavedPriority(Process.getThreadPriority(app.getPid())); 3662 ActivityManagerService.setFifoPriority(app, true /* enable */); 3663 } else { 3664 // Boost priority for top app UI and render threads 3665 mInjector.setThreadPriority(app.getPid(), 3666 THREAD_PRIORITY_TOP_APP_BOOST); 3667 if (renderThreadTid != 0) { 3668 try { 3669 mInjector.setThreadPriority(renderThreadTid, 3670 THREAD_PRIORITY_TOP_APP_BOOST); 3671 } catch (IllegalArgumentException e) { 3672 // thread died, ignore 3673 } 3674 } 3675 } 3676 } 3677 } else if (oldSchedGroup == SCHED_GROUP_TOP_APP 3678 && curSchedGroup != SCHED_GROUP_TOP_APP) { 3679 app.getWindowProcessController().onTopProcChanged(); 3680 if (app.useFifoUiScheduling()) { 3681 // Reset UI pipeline to SCHED_OTHER 3682 ActivityManagerService.setFifoPriority(app, false /* enable */); 3683 mInjector.setThreadPriority(app.getPid(), state.getSavedPriority()); 3684 } else { 3685 // Reset priority for top app UI and render threads 3686 mInjector.setThreadPriority(app.getPid(), 0); 3687 } 3688 3689 if (renderThreadTid != 0) { 3690 mInjector.setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY); 3691 } 3692 } 3693 } catch (Exception e) { 3694 if (DEBUG_ALL) { 3695 Slog.w(TAG, "Failed setting thread priority of " + app.getPid(), e); 3696 } 3697 } 3698 } 3699 if (state.hasRepForegroundActivities() != state.hasForegroundActivities()) { 3700 state.setRepForegroundActivities(state.hasForegroundActivities()); 3701 changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES; 3702 } 3703 3704 updateAppFreezeStateLSP(app, oomAdjReson, false, oldOomAdj); 3705 3706 if (state.getReportedProcState() != state.getCurProcState()) { 3707 state.setReportedProcState(state.getCurProcState()); 3708 if (app.getThread() != null) { 3709 try { 3710 if (false) { 3711 //RuntimeException h = new RuntimeException("here"); 3712 Slog.i(TAG, "Sending new process state " + state.getReportedProcState() 3713 + " to " + app /*, h*/); 3714 } 3715 app.getThread().setProcessState(state.getReportedProcState()); 3716 } catch (RemoteException e) { 3717 } 3718 } 3719 } 3720 boolean forceUpdatePssTime = false; 3721 if (state.getSetProcState() == PROCESS_STATE_NONEXISTENT 3722 || ProcessList.procStatesDifferForMem( 3723 state.getCurProcState(), state.getSetProcState())) { 3724 state.setLastStateTime(now); 3725 forceUpdatePssTime = true; 3726 if (DEBUG_PSS) { 3727 Slog.d(TAG_PSS, "Process state change from " 3728 + ProcessList.makeProcStateString(state.getSetProcState()) + " to " 3729 + ProcessList.makeProcStateString(state.getCurProcState()) + " next pss in " 3730 + (app.mProfile.getNextPssTime() - now) + ": " + app); 3731 } 3732 } 3733 synchronized (mService.mAppProfiler.mProfilerLock) { 3734 app.mProfile.updateProcState(app.mState); 3735 mService.mAppProfiler.updateNextPssTimeLPf( 3736 state.getCurProcState(), app.mProfile, now, forceUpdatePssTime); 3737 } 3738 int oldProcState = state.getSetProcState(); 3739 if (state.getSetProcState() != state.getCurProcState()) { 3740 if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) { 3741 String msg = "Proc state change of " + app.processName 3742 + " to " + ProcessList.makeProcStateString(state.getCurProcState()) 3743 + " (" + state.getCurProcState() + ")" + ": " + state.getAdjType(); 3744 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); 3745 } 3746 boolean setImportant = state.getSetProcState() < PROCESS_STATE_SERVICE; 3747 boolean curImportant = state.getCurProcState() < PROCESS_STATE_SERVICE; 3748 if (setImportant && !curImportant) { 3749 // This app is no longer something we consider important enough to allow to use 3750 // arbitrary amounts of battery power. Note its current CPU time to later know to 3751 // kill it if it is not behaving well. 3752 state.setWhenUnimportant(now); 3753 app.mProfile.mLastCpuTime.set(0); 3754 } 3755 // Inform UsageStats of important process state change 3756 // Must be called before updating setProcState 3757 maybeUpdateUsageStatsLSP(app, nowElapsed); 3758 3759 maybeUpdateLastTopTime(state, now); 3760 3761 state.setSetProcState(state.getCurProcState()); 3762 if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) { 3763 state.setNotCachedSinceIdle(false); 3764 } 3765 if (!doingAll) { 3766 synchronized (mService.mProcessStats.mLock) { 3767 mService.setProcessTrackerStateLOSP(app, 3768 mService.mProcessStats.getMemFactorLocked()); 3769 } 3770 } else { 3771 state.setProcStateChanged(true); 3772 } 3773 } else if (state.hasReportedInteraction()) { 3774 final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( 3775 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); 3776 final long interactionThreshold = fgsInteractionChangeEnabled 3777 ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S 3778 : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S; 3779 // For apps that sit around for a long time in the interactive state, we need 3780 // to report this at least once a day so they don't go idle. 3781 if ((nowElapsed - state.getInteractionEventTime()) > interactionThreshold) { 3782 maybeUpdateUsageStatsLSP(app, nowElapsed); 3783 } 3784 } else { 3785 final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( 3786 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); 3787 final long interactionThreshold = fgsInteractionChangeEnabled 3788 ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S 3789 : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S; 3790 // For foreground services that sit around for a long time but are not interacted with. 3791 if ((nowElapsed - state.getFgInteractionTime()) > interactionThreshold) { 3792 maybeUpdateUsageStatsLSP(app, nowElapsed); 3793 } 3794 } 3795 3796 if (state.getCurCapability() != state.getSetCapability()) { 3797 state.setSetCapability(state.getCurCapability()); 3798 } 3799 3800 final boolean curBoundByNonBgRestrictedApp = state.isCurBoundByNonBgRestrictedApp(); 3801 if (curBoundByNonBgRestrictedApp != state.isSetBoundByNonBgRestrictedApp()) { 3802 state.setSetBoundByNonBgRestrictedApp(curBoundByNonBgRestrictedApp); 3803 if (!curBoundByNonBgRestrictedApp && state.isBackgroundRestricted()) { 3804 mService.mHandler.post(() -> { 3805 synchronized (mService) { 3806 mService.mServices.stopAllForegroundServicesLocked( 3807 app.uid, app.info.packageName); 3808 } 3809 }); 3810 } 3811 } 3812 3813 if (changes != 0) { 3814 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, 3815 "Changes in " + app + ": " + changes); 3816 mProcessList.enqueueProcessChangeItemLocked(app.getPid(), app.info.uid, 3817 changes, state.hasRepForegroundActivities()); 3818 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, 3819 "Enqueued process change item for " 3820 + app.toShortString() + ": changes=" + changes 3821 + " foreground=" + state.hasRepForegroundActivities() 3822 + " type=" + state.getAdjType() + " source=" + state.getAdjSource() 3823 + " target=" + state.getAdjTarget()); 3824 } 3825 3826 if (state.isCached() && !state.shouldNotKillOnBgRestrictedAndIdle()) { 3827 // It's eligible to get killed when in UID idle and bg restricted mode, 3828 // check if these states are just flipped. 3829 if (!state.isSetCached() || state.isSetNoKillOnBgRestrictedAndIdle()) { 3830 // Take the timestamp, we'd hold the killing for the background settle time 3831 // (for states debouncing to avoid from thrashing). 3832 state.setLastCanKillOnBgRestrictedAndIdleTime(nowElapsed); 3833 // Kick off the delayed checkup message if needed. 3834 if (mService.mDeterministicUidIdle 3835 || !mService.mHandler.hasMessages(IDLE_UIDS_MSG)) { 3836 if (mLogger.shouldLog(app.uid)) { 3837 mLogger.logScheduleUidIdle2( 3838 uidRec.getUid(), app.getPid(), 3839 mConstants.mKillBgRestrictedAndCachedIdleSettleTimeMs); 3840 } 3841 mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, 3842 mConstants.mKillBgRestrictedAndCachedIdleSettleTimeMs); 3843 } 3844 } 3845 } 3846 state.setSetCached(state.isCached()); 3847 state.setSetNoKillOnBgRestrictedAndIdle(state.shouldNotKillOnBgRestrictedAndIdle()); 3848 if (((oldProcState != state.getSetProcState()) || (oldOomAdj != state.getSetAdj())) 3849 && mLogger.shouldLog(app.uid)) { 3850 mLogger.logProcStateChanged(app.uid, app.getPid(), 3851 state.getSetProcState(), oldProcState, 3852 state.getSetAdj(), oldOomAdj); 3853 } 3854 3855 return success; 3856 } 3857 3858 @GuardedBy({"mService", "mProcLock"}) setAttachingProcessStatesLSP(ProcessRecord app)3859 void setAttachingProcessStatesLSP(ProcessRecord app) { 3860 int initialSchedGroup = SCHED_GROUP_DEFAULT; 3861 int initialProcState = PROCESS_STATE_CACHED_EMPTY; 3862 int initialCapability = PROCESS_CAPABILITY_NONE; 3863 boolean initialCached = true; 3864 final ProcessStateRecord state = app.mState; 3865 final int prevProcState = state.getCurProcState(); 3866 final int prevAdj = state.getCurRawAdj(); 3867 // If the process has been marked as foreground, it is starting as the top app (with 3868 // Zygote#START_AS_TOP_APP_ARG), so boost the thread priority of its default UI thread. 3869 if (state.hasForegroundActivities()) { 3870 try { 3871 // The priority must be the same as how does {@link #applyOomAdjLSP} set for 3872 // {@link SCHED_GROUP_TOP_APP}. We don't check render thread because it 3873 // is not ready when attaching. 3874 app.getWindowProcessController().onTopProcChanged(); 3875 if (app.useFifoUiScheduling()) { 3876 mService.scheduleAsFifoPriority(app.getPid(), true); 3877 } else { 3878 mInjector.setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST); 3879 } 3880 if (isScreenOnOrAnimatingLocked(state)) { 3881 initialSchedGroup = SCHED_GROUP_TOP_APP; 3882 initialProcState = PROCESS_STATE_TOP; 3883 } 3884 initialCapability = PROCESS_CAPABILITY_ALL; 3885 initialCached = false; 3886 } catch (Exception e) { 3887 Slog.w(TAG, "Failed to pre-set top priority to " + app + " " + e); 3888 } 3889 } 3890 3891 state.setCurrentSchedulingGroup(initialSchedGroup); 3892 state.setCurProcState(initialProcState); 3893 state.setCurRawProcState(initialProcState); 3894 state.setCurCapability(initialCapability); 3895 3896 state.setCurAdj(ProcessList.FOREGROUND_APP_ADJ); 3897 state.setCurRawAdj(ProcessList.FOREGROUND_APP_ADJ); 3898 state.setForcingToImportant(null); 3899 state.setHasShownUi(false); 3900 3901 onProcessStateChanged(app, prevProcState); 3902 onProcessOomAdjChanged(app, prevAdj); 3903 } 3904 3905 // ONLY used for unit testing in OomAdjusterTests.java 3906 @VisibleForTesting maybeUpdateUsageStats(ProcessRecord app, long nowElapsed)3907 void maybeUpdateUsageStats(ProcessRecord app, long nowElapsed) { 3908 synchronized (mService) { 3909 synchronized (mProcLock) { 3910 maybeUpdateUsageStatsLSP(app, nowElapsed); 3911 } 3912 } 3913 } 3914 3915 @GuardedBy({"mService", "mProcLock"}) maybeUpdateUsageStatsLSP(ProcessRecord app, long nowElapsed)3916 private void maybeUpdateUsageStatsLSP(ProcessRecord app, long nowElapsed) { 3917 final ProcessStateRecord state = app.mState; 3918 if (DEBUG_USAGE_STATS) { 3919 Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList()) 3920 + "] state changes: old = " + state.getSetProcState() + ", new = " 3921 + state.getCurProcState()); 3922 } 3923 if (mService.mUsageStatsService == null) { 3924 return; 3925 } 3926 final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( 3927 CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); 3928 boolean isInteraction; 3929 // To avoid some abuse patterns, we are going to be careful about what we consider 3930 // to be an app interaction. Being the top activity doesn't count while the display 3931 // is sleeping, nor do short foreground services. 3932 if (ActivityManager.isProcStateConsideredInteraction(state.getCurProcState())) { 3933 isInteraction = true; 3934 state.setFgInteractionTime(0); 3935 } else if (state.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) { 3936 if (state.getFgInteractionTime() == 0) { 3937 state.setFgInteractionTime(nowElapsed); 3938 isInteraction = false; 3939 } else { 3940 final long interactionTime = fgsInteractionChangeEnabled 3941 ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S 3942 : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S; 3943 isInteraction = nowElapsed > state.getFgInteractionTime() + interactionTime; 3944 } 3945 } else { 3946 isInteraction = 3947 state.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND; 3948 state.setFgInteractionTime(0); 3949 } 3950 final long interactionThreshold = fgsInteractionChangeEnabled 3951 ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S 3952 : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S; 3953 if (isInteraction 3954 && (!state.hasReportedInteraction() 3955 || (nowElapsed - state.getInteractionEventTime()) > interactionThreshold)) { 3956 state.setInteractionEventTime(nowElapsed); 3957 String[] packages = app.getPackageList(); 3958 if (packages != null) { 3959 for (int i = 0; i < packages.length; i++) { 3960 mService.mUsageStatsService.reportEvent(packages[i], app.userId, 3961 UsageEvents.Event.SYSTEM_INTERACTION); 3962 } 3963 } 3964 } 3965 state.setReportedInteraction(isInteraction); 3966 if (!isInteraction) { 3967 state.setInteractionEventTime(0); 3968 } 3969 } 3970 maybeUpdateLastTopTime(ProcessStateRecord state, long nowUptime)3971 private void maybeUpdateLastTopTime(ProcessStateRecord state, long nowUptime) { 3972 if (state.getSetProcState() <= PROCESS_STATE_TOP 3973 && state.getCurProcState() > PROCESS_STATE_TOP) { 3974 state.setLastTopTime(nowUptime); 3975 } 3976 } 3977 3978 /** 3979 * Look for recently inactive apps and mark them idle after a grace period. If idled, stop 3980 * any background services and inform listeners. 3981 */ 3982 @GuardedBy("mService") idleUidsLocked()3983 void idleUidsLocked() { 3984 final int N = mActiveUids.size(); 3985 mService.mHandler.removeMessages(IDLE_UIDS_MSG); 3986 if (N <= 0) { 3987 return; 3988 } 3989 final long nowElapsed = mInjector.getElapsedRealtimeMillis(); 3990 final long maxBgTime = nowElapsed - mConstants.BACKGROUND_SETTLE_TIME; 3991 long nextTime = 0; 3992 if (mService.mLocalPowerManager != null) { 3993 mService.mLocalPowerManager.startUidChanges(); 3994 } 3995 boolean shouldLogMisc = false; 3996 for (int i = N - 1; i >= 0; i--) { 3997 final UidRecord uidRec = mActiveUids.valueAt(i); 3998 final long bgTime = uidRec.getLastBackgroundTime(); 3999 final long idleTime = uidRec.getLastIdleTimeIfStillIdle(); 4000 if (bgTime > 0 && (!uidRec.isIdle() || idleTime == 0)) { 4001 if (bgTime <= maxBgTime) { 4002 EventLogTags.writeAmUidIdle(uidRec.getUid()); 4003 synchronized (mProcLock) { 4004 uidRec.setIdle(true); 4005 uidRec.setSetIdle(true); 4006 uidRec.setLastIdleTime(nowElapsed); 4007 } 4008 mService.doStopUidLocked(uidRec.getUid(), uidRec); 4009 } else { 4010 if (nextTime == 0 || nextTime > bgTime) { 4011 nextTime = bgTime; 4012 } 4013 if (mLogger.shouldLog(uidRec.getUid())) { 4014 shouldLogMisc = true; 4015 } 4016 } 4017 } 4018 } 4019 if (mService.mLocalPowerManager != null) { 4020 mService.mLocalPowerManager.finishUidChanges(); 4021 } 4022 // Also check if there are any apps in cached and background restricted mode, 4023 // if so, kill it if it's been there long enough, or kick off a msg to check 4024 // it later. 4025 if (mService.mConstants.mKillBgRestrictedAndCachedIdle) { 4026 final ArraySet<ProcessRecord> apps = mProcessList.mAppsInBackgroundRestricted; 4027 for (int i = 0, size = apps.size(); i < size; i++) { 4028 // Check to see if needs to be killed. 4029 final long bgTime = mProcessList.killAppIfBgRestrictedAndCachedIdleLocked( 4030 apps.valueAt(i), nowElapsed) - mConstants.BACKGROUND_SETTLE_TIME; 4031 if (bgTime > 0 && (nextTime == 0 || nextTime > bgTime)) { 4032 nextTime = bgTime; 4033 } 4034 } 4035 } 4036 if (nextTime > 0) { 4037 long delay = nextTime + mConstants.BACKGROUND_SETTLE_TIME - nowElapsed; 4038 if (shouldLogMisc) { 4039 mLogger.logScheduleUidIdle3(delay); 4040 } 4041 mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, delay); 4042 } 4043 } 4044 4045 @GuardedBy({"mService", "mProcLock"}) setUidTempAllowlistStateLSP(int uid, boolean onAllowlist)4046 void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) { 4047 final UidRecord uidRec = mActiveUids.get(uid); 4048 if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) { 4049 uidRec.setCurAllowListed(onAllowlist); 4050 if (Flags.migrateFullOomadjUpdates()) { 4051 for (int i = uidRec.getNumOfProcs() - 1; i >= 0; i--) { 4052 enqueueOomAdjTargetLocked(uidRec.getProcessRecordByIndex(i)); 4053 } 4054 updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_ALLOWLIST); 4055 } else { 4056 updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST); 4057 } 4058 } 4059 } 4060 4061 @GuardedBy("mService") dumpProcessListVariablesLocked(ProtoOutputStream proto)4062 void dumpProcessListVariablesLocked(ProtoOutputStream proto) { 4063 proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq); 4064 proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.getLruSeqLOSP()); 4065 proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS, 4066 mNumNonCachedProcs); 4067 proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs); 4068 proto.write(ActivityManagerServiceDumpProcessesProto.NEW_NUM_SERVICE_PROCS, 4069 mNewNumServiceProcs); 4070 4071 } 4072 4073 @GuardedBy("mService") dumpSequenceNumbersLocked(PrintWriter pw)4074 void dumpSequenceNumbersLocked(PrintWriter pw) { 4075 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.getLruSeqLOSP()); 4076 } 4077 4078 @GuardedBy("mService") dumpProcCountsLocked(PrintWriter pw)4079 void dumpProcCountsLocked(PrintWriter pw) { 4080 pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs 4081 + " (" + mProcessList.getLruSizeLOSP() + " total)" 4082 + " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs 4083 + " mNumServiceProcs=" + mNumServiceProcs 4084 + " mNewNumServiceProcs=" + mNewNumServiceProcs); 4085 } 4086 dumpCachedAppOptimizerSettings(PrintWriter pw)4087 void dumpCachedAppOptimizerSettings(PrintWriter pw) { 4088 mCachedAppOptimizer.dump(pw); 4089 } 4090 4091 @GuardedBy("mService") dumpCacheOomRankerSettings(PrintWriter pw)4092 void dumpCacheOomRankerSettings(PrintWriter pw) { 4093 mCacheOomRanker.dump(pw); 4094 } 4095 4096 /** 4097 * Return whether or not a process should be frozen. 4098 */ getFreezePolicy(ProcessRecord proc)4099 boolean getFreezePolicy(ProcessRecord proc) { 4100 // Reasons to not freeze: 4101 if (Flags.useCpuTimeCapability()) { 4102 if ((proc.mState.getCurCapability() & PROCESS_CAPABILITY_CPU_TIME) != 0) { 4103 /// App is important enough (see {@link #getCpuCapability}) or bound by something 4104 /// important enough to not be frozen. 4105 return false; 4106 } 4107 } else { 4108 // The CPU capability handling covers all setShouldNotFreeze paths. Must check 4109 // shouldNotFreeze, if the CPU capability is not being used. 4110 if (proc.mOptRecord.shouldNotFreeze()) { 4111 return false; 4112 } 4113 } 4114 4115 if (proc.mOptRecord.isFreezeExempt()) { 4116 return false; 4117 } 4118 4119 // Reasons to freeze: 4120 if (proc.mState.getCurAdj() >= mConstants.FREEZER_CUTOFF_ADJ) { 4121 // Oomscore is in a high enough state, it is safe to freeze. 4122 return true; 4123 } 4124 4125 // Default, do not freeze a process. 4126 return false; 4127 } 4128 4129 @GuardedBy({"mService", "mProcLock"}) updateAppFreezeStateLSP(ProcessRecord app, @OomAdjReason int oomAdjReason, boolean immediate, int oldOomAdj)4130 void updateAppFreezeStateLSP(ProcessRecord app, @OomAdjReason int oomAdjReason, 4131 boolean immediate, int oldOomAdj) { 4132 if (!mCachedAppOptimizer.useFreezer()) { 4133 return; 4134 } 4135 4136 final boolean freezePolicy = getFreezePolicy(app); 4137 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 4138 final ProcessStateRecord state = app.mState; 4139 if (Flags.traceUpdateAppFreezeStateLsp()) { 4140 final boolean oomAdjChanged = (state.getCurAdj() >= mConstants.FREEZER_CUTOFF_ADJ 4141 ^ oldOomAdj >= mConstants.FREEZER_CUTOFF_ADJ) || oldOomAdj == UNKNOWN_ADJ; 4142 final boolean shouldNotFreezeChanged = opt.shouldNotFreezeAdjSeq() == mAdjSeq; 4143 final boolean hasCpuCapability = 4144 (PROCESS_CAPABILITY_CPU_TIME & app.mState.getCurCapability()) 4145 == PROCESS_CAPABILITY_CPU_TIME; 4146 final boolean usedToHaveCpuCapability = 4147 (PROCESS_CAPABILITY_CPU_TIME & app.mState.getSetCapability()) 4148 == PROCESS_CAPABILITY_CPU_TIME; 4149 final boolean cpuCapabilityChanged = hasCpuCapability != usedToHaveCpuCapability; 4150 if ((oomAdjChanged || shouldNotFreezeChanged || cpuCapabilityChanged) 4151 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 4152 Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, 4153 "FreezeLite", 4154 (opt.isFrozen() ? "F" : "-") 4155 + (opt.isPendingFreeze() ? "P" : "-") 4156 + (opt.isFreezeExempt() ? "E" : "-") 4157 + (opt.shouldNotFreeze() ? "N" : "-") 4158 + (hasCpuCapability ? "T" : "-") 4159 + (immediate ? "I" : "-") 4160 + (freezePolicy ? "Z" : "-") 4161 + (Flags.useCpuTimeCapability() ? "t" : "-") 4162 + (Flags.prototypeAggressiveFreezing() ? "a" : "-") 4163 + "/" + app.getPid() 4164 + "/" + state.getCurAdj() 4165 + "/" + oldOomAdj 4166 + "/" + opt.shouldNotFreezeReason()); 4167 Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, 4168 CachedAppOptimizer.ATRACE_FREEZER_TRACK, 4169 "updateAppFreezeStateLSP " + app.processName 4170 + " pid: " + app.getPid() 4171 + " isFreezeExempt: " + opt.isFreezeExempt() 4172 + " isFrozen: " + opt.isFrozen() 4173 + " shouldNotFreeze: " + opt.shouldNotFreeze() 4174 + " shouldNotFreezeReason: " + opt.shouldNotFreezeReason() 4175 + " curAdj: " + state.getCurAdj() 4176 + " oldOomAdj: " + oldOomAdj 4177 + " immediate: " + immediate 4178 + " cpuCapability: " + hasCpuCapability); 4179 } 4180 } 4181 4182 if (freezePolicy) { 4183 // This process should be frozen. 4184 if (immediate && !opt.isFrozen()) { 4185 // And it will be frozen immediately. 4186 mCachedAppOptimizer.freezeAppAsyncAtEarliestLSP(app); 4187 } else if (!opt.isFrozen() || !opt.isPendingFreeze()) { 4188 mCachedAppOptimizer.freezeAppAsyncLSP(app); 4189 } 4190 } else { 4191 // This process should not be frozen. 4192 if (opt.isFrozen() || opt.isPendingFreeze()) { 4193 mCachedAppOptimizer.unfreezeAppLSP(app, 4194 CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(oomAdjReason)); 4195 } 4196 } 4197 } 4198 4199 @GuardedBy("mService") unfreezeTemporarily(ProcessRecord app, @OomAdjReason int reason)4200 void unfreezeTemporarily(ProcessRecord app, @OomAdjReason int reason) { 4201 if (!mCachedAppOptimizer.useFreezer()) { 4202 return; 4203 } 4204 4205 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 4206 if (!opt.isFrozen() && !opt.isPendingFreeze()) { 4207 return; 4208 } 4209 4210 final ArrayList<ProcessRecord> processes = mTmpProcessList; 4211 final ActiveUids uids = mTmpUidRecords; 4212 mTmpProcessSet.add(app); 4213 collectReachableProcessesLocked(mTmpProcessSet, processes, uids); 4214 mTmpProcessSet.clear(); 4215 // Now processes contains app's downstream and app 4216 final int size = processes.size(); 4217 for (int i = 0; i < size; i++) { 4218 ProcessRecord proc = processes.get(i); 4219 mCachedAppOptimizer.unfreezeTemporarily(proc, 4220 CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(reason)); 4221 } 4222 processes.clear(); 4223 } 4224 4225 @GuardedBy("mService") onProcessEndLocked(@onNull ProcessRecord app)4226 void onProcessEndLocked(@NonNull ProcessRecord app) { 4227 // Empty, the OomAdjusterModernImpl will have an implementation. 4228 } 4229 4230 /** 4231 * Called when the process state is changed outside of the OomAdjuster. 4232 */ 4233 @GuardedBy("mService") onProcessStateChanged(@onNull ProcessRecord app, int prevProcState)4234 void onProcessStateChanged(@NonNull ProcessRecord app, int prevProcState) { 4235 // Empty, the OomAdjusterModernImpl will have an implementation. 4236 } 4237 4238 /** 4239 * Called when the oom adj is changed outside of the OomAdjuster. 4240 */ 4241 @GuardedBy("mService") onProcessOomAdjChanged(@onNull ProcessRecord app, int prevAdj)4242 void onProcessOomAdjChanged(@NonNull ProcessRecord app, int prevAdj) { 4243 // Empty, the OomAdjusterModernImpl will have an implementation. 4244 } 4245 4246 @VisibleForTesting resetInternal()4247 void resetInternal() { 4248 // Empty, the OomAdjusterModernImpl will have an implementation. 4249 } 4250 4251 @GuardedBy("mService") getInitialAdj(@onNull ProcessRecord app)4252 protected int getInitialAdj(@NonNull ProcessRecord app) { 4253 return app.mState.getCurAdj(); 4254 } 4255 4256 @GuardedBy("mService") getInitialProcState(@onNull ProcessRecord app)4257 protected int getInitialProcState(@NonNull ProcessRecord app) { 4258 return app.mState.getCurProcState(); 4259 } 4260 4261 @GuardedBy("mService") getInitialCapability(@onNull ProcessRecord app)4262 protected int getInitialCapability(@NonNull ProcessRecord app) { 4263 return app.mState.getCurCapability(); 4264 } 4265 4266 @GuardedBy("mService") getInitialIsCurBoundByNonBgRestrictedApp(@onNull ProcessRecord app)4267 protected boolean getInitialIsCurBoundByNonBgRestrictedApp(@NonNull ProcessRecord app) { 4268 // The caller will set the initial value in this implementation. 4269 return app.mState.isCurBoundByNonBgRestrictedApp(); 4270 } 4271 4272 /** 4273 * Evaluate the service connection, return {@code true} if the client will change any state 4274 * (ie. ProcessState, oomAdj, capability, etc) of the service host process by the given 4275 * connection. 4276 */ 4277 @GuardedBy("mService") evaluateServiceConnectionAdd(ProcessRecord client, ProcessRecord app, ConnectionRecord cr)4278 boolean evaluateServiceConnectionAdd(ProcessRecord client, ProcessRecord app, 4279 ConnectionRecord cr) { 4280 if (evaluateConnectionPrelude(client, app)) { 4281 return true; 4282 } 4283 4284 boolean needDryRun = false; 4285 if (app.getSetAdj() > client.getSetAdj()) { 4286 // The connection might elevate the importance of the service's oom adj score. 4287 needDryRun = true; 4288 } else if (app.getSetProcState() > client.getSetProcState()) { 4289 // The connection might elevate the importance of the service's process state. 4290 needDryRun = true; 4291 } else if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES 4292 | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS) 4293 && (app.getSetCapability() & client.getSetCapability()) 4294 != client.getSetCapability()) { 4295 // The connection might elevate the importance of the service's capabilities. 4296 needDryRun = true; 4297 } else if (Flags.useCpuTimeCapability() 4298 && (client.getSetCapability() & ~app.getSetCapability() 4299 & PROCESS_CAPABILITY_CPU_TIME) != 0) { 4300 // The connection might grant PROCESS_CAPABILITY_CPU_TIME to the service. 4301 needDryRun = true; 4302 } else if (Flags.unfreezeBindPolicyFix() 4303 && cr.hasFlag(Context.BIND_WAIVE_PRIORITY 4304 | Context.BIND_ALLOW_OOM_MANAGEMENT)) { 4305 // These bind flags can grant the shouldNotFreeze state to the service. 4306 needDryRun = true; 4307 } else if (Flags.unfreezeBindPolicyFix() 4308 && client.mOptRecord.shouldNotFreeze() 4309 && !app.mOptRecord.shouldNotFreeze()) { 4310 // The shouldNotFreeze state can be propagated and needs to be checked. 4311 needDryRun = true; 4312 } 4313 4314 if (needDryRun) { 4315 // Take a dry run of the computeServiceHostOomAdjLSP, this would't be expensive 4316 // since it's only evaluating one service connection. 4317 return computeServiceHostOomAdjLSP(cr, app, client, mInjector.getUptimeMillis(), 4318 mService.getTopApp(), false, false, false, OOM_ADJ_REASON_NONE, 4319 CACHED_APP_MIN_ADJ, false, true /* dryRun */); 4320 } 4321 return false; 4322 } 4323 4324 @GuardedBy("mService") evaluateServiceConnectionRemoval(ProcessRecord client, ProcessRecord app, ConnectionRecord cr)4325 boolean evaluateServiceConnectionRemoval(ProcessRecord client, ProcessRecord app, 4326 ConnectionRecord cr) { 4327 if (evaluateConnectionPrelude(client, app)) { 4328 return true; 4329 } 4330 4331 if (app.getSetAdj() >= client.getSetAdj()) { 4332 return true; 4333 } else if (app.getSetProcState() >= client.getSetProcState()) { 4334 return true; 4335 } else if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES 4336 | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS) 4337 && (app.getSetCapability() & client.getSetCapability()) 4338 != PROCESS_CAPABILITY_NONE) { 4339 return true; 4340 } else if (Flags.unfreezeBindPolicyFix() 4341 && cr.hasFlag(Context.BIND_WAIVE_PRIORITY 4342 | Context.BIND_ALLOW_OOM_MANAGEMENT)) { 4343 return true; 4344 } else if (Flags.unfreezeBindPolicyFix() 4345 && app.mOptRecord.shouldNotFreeze() 4346 && client.mOptRecord.shouldNotFreeze()) { 4347 // Process has shouldNotFreeze and it could have gotten it from the client. 4348 return true; 4349 } else if (Flags.useCpuTimeCapability() 4350 && (client.getSetCapability() & app.getSetCapability() 4351 & PROCESS_CAPABILITY_CPU_TIME) != 0) { 4352 return true; 4353 } 4354 return false; 4355 } 4356 4357 @GuardedBy("mService") evaluateProviderConnectionAdd(ProcessRecord client, ProcessRecord app)4358 boolean evaluateProviderConnectionAdd(ProcessRecord client, ProcessRecord app) { 4359 if (evaluateConnectionPrelude(client, app)) { 4360 return true; 4361 } 4362 4363 boolean needDryRun = false; 4364 if (app.getSetAdj() > client.getSetAdj()) { 4365 needDryRun = true; 4366 } else if (app.getSetProcState() > client.getSetProcState()) { 4367 needDryRun = true; 4368 } else if (Flags.unfreezeBindPolicyFix() 4369 && client.mOptRecord.shouldNotFreeze() 4370 && !app.mOptRecord.shouldNotFreeze()) { 4371 needDryRun = true; 4372 } else if (Flags.useCpuTimeCapability() 4373 && (client.getSetCapability() & ~app.getSetCapability() 4374 & PROCESS_CAPABILITY_CPU_TIME) != 0) { 4375 // The connection might grant PROCESS_CAPABILITY_CPU_TIME to the provider. 4376 needDryRun = true; 4377 } 4378 4379 if (needDryRun) { 4380 return computeProviderHostOomAdjLSP(null, app, client, mInjector.getUptimeMillis(), 4381 mService.getTopApp(), false, false, false, OOM_ADJ_REASON_NONE, 4382 CACHED_APP_MIN_ADJ, 4383 false, true /* dryRun */); 4384 } 4385 return false; 4386 } 4387 4388 @GuardedBy("mService") evaluateProviderConnectionRemoval(ProcessRecord client, ProcessRecord app)4389 boolean evaluateProviderConnectionRemoval(ProcessRecord client, ProcessRecord app) { 4390 if (evaluateConnectionPrelude(client, app)) { 4391 return true; 4392 } 4393 4394 if (app.getSetAdj() >= client.getSetAdj()) { 4395 return true; 4396 } else if (app.getSetProcState() >= client.getSetProcState()) { 4397 return true; 4398 } else if (Flags.unfreezeBindPolicyFix() 4399 && app.mOptRecord.shouldNotFreeze() 4400 && client.mOptRecord.shouldNotFreeze()) { 4401 // Process has shouldNotFreeze and it could have gotten it from the client. 4402 return true; 4403 } else if (Flags.useCpuTimeCapability() 4404 && (client.getSetCapability() & app.getSetCapability() 4405 & PROCESS_CAPABILITY_CPU_TIME) != 0) { 4406 return true; 4407 } 4408 4409 return false; 4410 } 4411 evaluateConnectionPrelude(ProcessRecord client, ProcessRecord app)4412 private boolean evaluateConnectionPrelude(ProcessRecord client, ProcessRecord app) { 4413 if (client == null || app == null) { 4414 return true; 4415 } 4416 if (app.isSdkSandbox || app.isolated || app.isKilledByAm() || app.isKilled()) { 4417 // Let's always re-evaluate them for now. 4418 return true; 4419 } 4420 return false; 4421 } 4422 4423 @GuardedBy("mService") maybeSetProcessFollowUpUpdateLocked(ProcessRecord proc, long updateUptimeMs, long now)4424 private void maybeSetProcessFollowUpUpdateLocked(ProcessRecord proc, 4425 long updateUptimeMs, long now) { 4426 if (!Flags.followUpOomadjUpdates()) { 4427 return; 4428 } 4429 if (updateUptimeMs <= now) { 4430 // Time sensitive period has already passed. No need to schedule a follow up. 4431 return; 4432 } 4433 4434 mFollowUpUpdateSet.add(proc); 4435 proc.mState.setFollowupUpdateUptimeMs(updateUptimeMs); 4436 4437 scheduleFollowUpOomAdjusterUpdateLocked(updateUptimeMs, now); 4438 } 4439 4440 4441 @GuardedBy("mService") scheduleFollowUpOomAdjusterUpdateLocked(long updateUptimeMs, long now)4442 private void scheduleFollowUpOomAdjusterUpdateLocked(long updateUptimeMs, 4443 long now) { 4444 if (updateUptimeMs + mConstants.FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION 4445 >= mNextFollowUpUpdateUptimeMs) { 4446 // Update time is too close or later than the next follow up update. 4447 return; 4448 } 4449 if (updateUptimeMs < now + mConstants.FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION) { 4450 // Use a minimum delay for the follow up to possibly batch multiple process 4451 // evaluations and avoid rapid updates. 4452 updateUptimeMs = now + mConstants.FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION; 4453 } 4454 4455 // Schedulate a follow up update. Don't bother deleting existing handler messages, they 4456 // will be cleared during the message while no locks are being held. 4457 mNextFollowUpUpdateUptimeMs = updateUptimeMs; 4458 mService.mHandler.sendEmptyMessageAtTime(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG, 4459 mNextFollowUpUpdateUptimeMs); 4460 } 4461 } 4462