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