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