1 /* 2 * Copyright (C) 2018 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.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN; 20 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN; 21 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY; 22 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST; 23 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP; 24 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BIND_SERVICE; 25 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED; 26 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE; 27 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER; 28 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FOLLOW_UP; 29 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_GET_PROVIDER; 30 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_BEGIN; 31 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END; 32 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION; 33 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER; 34 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK; 35 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE; 36 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHELL; 37 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT; 38 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER; 39 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_SERVICE; 40 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_STOP_SERVICE; 41 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SYSTEM_INIT; 42 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UID_IDLE; 43 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UI_VISIBILITY; 44 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UNBIND_SERVICE; 45 import static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; 46 47 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_COMPACTION; 48 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FREEZER; 49 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 50 51 import android.annotation.IntDef; 52 import android.annotation.UptimeMillisLong; 53 import android.app.ActivityManager; 54 import android.app.ActivityManagerInternal.FrozenProcessListener; 55 import android.app.ActivityManagerInternal.OomAdjReason; 56 import android.app.ActivityThread; 57 import android.app.ApplicationExitInfo; 58 import android.app.ApplicationExitInfo.Reason; 59 import android.app.ApplicationExitInfo.SubReason; 60 import android.app.IApplicationThread; 61 import android.database.ContentObserver; 62 import android.net.Uri; 63 import android.os.Handler; 64 import android.os.Message; 65 import android.os.PowerManagerInternal; 66 import android.os.Process; 67 import android.os.RemoteException; 68 import android.os.SystemClock; 69 import android.os.Trace; 70 import android.provider.DeviceConfig; 71 import android.provider.DeviceConfig.OnPropertiesChangedListener; 72 import android.provider.DeviceConfig.Properties; 73 import android.provider.Settings; 74 import android.text.TextUtils; 75 import android.util.ArraySet; 76 import android.util.EventLog; 77 import android.util.IntArray; 78 import android.util.Pair; 79 import android.util.Slog; 80 import android.util.SparseArray; 81 82 import com.android.internal.annotations.GuardedBy; 83 import com.android.internal.annotations.VisibleForTesting; 84 import com.android.internal.os.BinderfsStatsReader; 85 import com.android.internal.os.ProcLocksReader; 86 import com.android.internal.util.FrameworkStatsLog; 87 import com.android.server.ServiceThread; 88 import com.android.server.am.compaction.CompactionStatsManager; 89 import com.android.server.am.compaction.SingleCompactionStats; 90 91 import dalvik.annotation.optimization.NeverCompile; 92 93 import java.io.IOException; 94 import java.io.PrintWriter; 95 import java.lang.annotation.Retention; 96 import java.lang.annotation.RetentionPolicy; 97 import java.util.ArrayList; 98 import java.util.Arrays; 99 import java.util.HashSet; 100 import java.util.Random; 101 import java.util.Set; 102 import java.util.concurrent.Executor; 103 104 public class CachedAppOptimizer { 105 106 // Flags stored in the DeviceConfig API. 107 @VisibleForTesting static final String KEY_USE_COMPACTION = "use_compaction"; 108 @VisibleForTesting static final String KEY_USE_FREEZER = "use_freezer"; 109 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_1 = "compact_throttle_1"; 110 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2"; 111 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3"; 112 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4"; 113 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5"; 114 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6"; 115 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_MIN_OOM_ADJ = 116 "compact_throttle_min_oom_adj"; 117 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_MAX_OOM_ADJ = 118 "compact_throttle_max_oom_adj"; 119 @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE = 120 "compact_statsd_sample_rate"; 121 @VisibleForTesting static final String KEY_FREEZER_STATSD_SAMPLE_RATE = 122 "freeze_statsd_sample_rate"; 123 @VisibleForTesting static final String KEY_COMPACT_FULL_RSS_THROTTLE_KB = 124 "compact_full_rss_throttle_kb"; 125 @VisibleForTesting static final String KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB = 126 "compact_full_delta_rss_throttle_kb"; 127 @VisibleForTesting static final String KEY_COMPACT_PROC_STATE_THROTTLE = 128 "compact_proc_state_throttle"; 129 @VisibleForTesting static final String KEY_FREEZER_DEBOUNCE_TIMEOUT = 130 "freeze_debounce_timeout"; 131 @VisibleForTesting static final String KEY_FREEZER_EXEMPT_INST_PKG = 132 "freeze_exempt_inst_pkg"; 133 @VisibleForTesting static final String KEY_FREEZER_BINDER_ENABLED = 134 "freeze_binder_enabled"; 135 @VisibleForTesting static final String KEY_FREEZER_BINDER_DIVISOR = 136 "freeze_binder_divisor"; 137 @VisibleForTesting static final String KEY_FREEZER_BINDER_OFFSET = 138 "freeze_binder_offset"; 139 @VisibleForTesting static final String KEY_FREEZER_BINDER_THRESHOLD = 140 "freeze_binder_threshold"; 141 @VisibleForTesting static final String KEY_FREEZER_BINDER_CALLBACK_ENABLED = 142 "freeze_binder_callback_enabled"; 143 @VisibleForTesting static final String KEY_FREEZER_BINDER_CALLBACK_THROTTLE = 144 "freeze_binder_callback_throttle"; 145 @VisibleForTesting static final String KEY_FREEZER_BINDER_ASYNC_THRESHOLD = 146 "freeze_binder_async_threshold"; 147 148 static final int UNFREEZE_REASON_NONE = 149 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_NONE; 150 static final int UNFREEZE_REASON_ACTIVITY = 151 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_ACTIVITY; 152 static final int UNFREEZE_REASON_FINISH_RECEIVER = 153 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_FINISH_RECEIVER; 154 static final int UNFREEZE_REASON_START_RECEIVER = 155 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_START_RECEIVER; 156 static final int UNFREEZE_REASON_BIND_SERVICE = 157 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_BIND_SERVICE; 158 static final int UNFREEZE_REASON_UNBIND_SERVICE = 159 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_UNBIND_SERVICE; 160 static final int UNFREEZE_REASON_START_SERVICE = 161 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_START_SERVICE; 162 static final int UNFREEZE_REASON_GET_PROVIDER = 163 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_GET_PROVIDER; 164 static final int UNFREEZE_REASON_REMOVE_PROVIDER = 165 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_REMOVE_PROVIDER; 166 static final int UNFREEZE_REASON_UI_VISIBILITY = 167 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_UI_VISIBILITY; 168 static final int UNFREEZE_REASON_ALLOWLIST = 169 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_ALLOWLIST; 170 static final int UNFREEZE_REASON_PROCESS_BEGIN = 171 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_PROCESS_BEGIN; 172 static final int UNFREEZE_REASON_PROCESS_END = 173 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_PROCESS_END; 174 static final int UNFREEZE_REASON_TRIM_MEMORY = 175 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_TRIM_MEMORY; 176 static final int UNFREEZE_REASON_PING = 177 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_PING; 178 static final int UNFREEZE_REASON_FILE_LOCKS = 179 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_FILE_LOCKS; 180 static final int UNFREEZE_REASON_FILE_LOCK_CHECK_FAILURE = 181 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_FILE_LOCK_CHECK_FAILURE; 182 static final int UNFREEZE_REASON_BINDER_TXNS = 183 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_BINDER_TXNS; 184 static final int UNFREEZE_REASON_FEATURE_FLAGS = 185 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_FEATURE_FLAGS; 186 static final int UNFREEZE_REASON_SHORT_FGS_TIMEOUT = 187 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_SHORT_FGS_TIMEOUT; 188 static final int UNFREEZE_REASON_SYSTEM_INIT = 189 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_SYSTEM_INIT; 190 static final int UNFREEZE_REASON_BACKUP = 191 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_BACKUP; 192 static final int UNFREEZE_REASON_SHELL = 193 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_SHELL; 194 static final int UNFREEZE_REASON_REMOVE_TASK = 195 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_REMOVE_TASK; 196 static final int UNFREEZE_REASON_UID_IDLE = 197 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_UID_IDLE; 198 static final int UNFREEZE_REASON_STOP_SERVICE = 199 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_STOP_SERVICE; 200 static final int UNFREEZE_REASON_EXECUTING_SERVICE = 201 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_EXECUTING_SERVICE; 202 static final int UNFREEZE_REASON_RESTRICTION_CHANGE = 203 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_RESTRICTION_CHANGE; 204 static final int UNFREEZE_REASON_COMPONENT_DISABLED = 205 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_COMPONENT_DISABLED; 206 static final int UNFREEZE_REASON_OOM_ADJ_FOLLOW_UP = 207 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_OOM_ADJ_FOLLOW_UP; 208 static final int UNFREEZE_REASON_OOM_ADJ_RECONFIGURATION = 209 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_OOM_ADJ_RECONFIGURATION; 210 211 @IntDef(prefix = {"UNFREEZE_REASON_"}, value = { 212 UNFREEZE_REASON_NONE, 213 UNFREEZE_REASON_ACTIVITY, 214 UNFREEZE_REASON_FINISH_RECEIVER, 215 UNFREEZE_REASON_START_RECEIVER, 216 UNFREEZE_REASON_BIND_SERVICE, 217 UNFREEZE_REASON_UNBIND_SERVICE, 218 UNFREEZE_REASON_START_SERVICE, 219 UNFREEZE_REASON_GET_PROVIDER, 220 UNFREEZE_REASON_REMOVE_PROVIDER, 221 UNFREEZE_REASON_UI_VISIBILITY, 222 UNFREEZE_REASON_ALLOWLIST, 223 UNFREEZE_REASON_PROCESS_BEGIN, 224 UNFREEZE_REASON_PROCESS_END, 225 UNFREEZE_REASON_TRIM_MEMORY, 226 UNFREEZE_REASON_PING, 227 UNFREEZE_REASON_FILE_LOCKS, 228 UNFREEZE_REASON_FILE_LOCK_CHECK_FAILURE, 229 UNFREEZE_REASON_BINDER_TXNS, 230 UNFREEZE_REASON_FEATURE_FLAGS, 231 UNFREEZE_REASON_SHORT_FGS_TIMEOUT, 232 UNFREEZE_REASON_SYSTEM_INIT, 233 UNFREEZE_REASON_BACKUP, 234 UNFREEZE_REASON_SHELL, 235 UNFREEZE_REASON_REMOVE_TASK, 236 UNFREEZE_REASON_UID_IDLE, 237 UNFREEZE_REASON_STOP_SERVICE, 238 UNFREEZE_REASON_EXECUTING_SERVICE, 239 UNFREEZE_REASON_RESTRICTION_CHANGE, 240 UNFREEZE_REASON_COMPONENT_DISABLED, 241 UNFREEZE_REASON_OOM_ADJ_FOLLOW_UP, 242 UNFREEZE_REASON_OOM_ADJ_RECONFIGURATION, 243 }) 244 @Retention(RetentionPolicy.SOURCE) 245 public @interface UnfreezeReason {} 246 247 // RSS Indices 248 private static final int RSS_TOTAL_INDEX = 0; 249 private static final int RSS_FILE_INDEX = 1; 250 private static final int RSS_ANON_INDEX = 2; 251 private static final int RSS_SWAP_INDEX = 3; 252 253 // Keeps these flags in sync with services/core/jni/com_android_server_am_CachedAppOptimizer.cpp 254 private static final int COMPACT_ACTION_FILE_FLAG = 1; 255 private static final int COMPACT_ACTION_ANON_FLAG = 2; 256 257 private static final String ATRACE_COMPACTION_TRACK = "Compaction"; 258 public static final String ATRACE_FREEZER_TRACK = "Freezer"; 259 260 private static final int FREEZE_BINDER_TIMEOUT_MS = 0; 261 private static final int FREEZE_DEADLOCK_TIMEOUT_MS = 1000; 262 263 // If enabled, any compaction issued will apply to code mappings and share memory mappings. 264 @VisibleForTesting static final boolean ENABLE_SHARED_AND_CODE_COMPACT = false; 265 266 // Defaults for phenotype flags. 267 @VisibleForTesting static final boolean DEFAULT_USE_COMPACTION = true; 268 @VisibleForTesting static final boolean DEFAULT_USE_FREEZER = true; 269 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000; 270 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000; 271 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500; 272 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000; 273 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000; 274 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_6 = 10 * 60 * 1000; 275 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ = 276 ProcessList.CACHED_APP_MIN_ADJ; 277 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ = 278 ProcessList.CACHED_APP_MAX_ADJ; 279 // The sampling rate to push app compaction events into statsd for upload. 280 @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f; 281 @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L; 282 @VisibleForTesting static final long DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB = 8_000L; 283 // Format of this string should be a comma separated list of integers. 284 @VisibleForTesting static final String DEFAULT_COMPACT_PROC_STATE_THROTTLE = 285 String.valueOf(ActivityManager.PROCESS_STATE_RECEIVER); 286 @VisibleForTesting static final long DEFAULT_FREEZER_DEBOUNCE_TIMEOUT = 10_000L; 287 @VisibleForTesting static final boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = false; 288 @VisibleForTesting static final boolean DEFAULT_FREEZER_BINDER_ENABLED = true; 289 @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_DIVISOR = 4; 290 @VisibleForTesting static final int DEFAULT_FREEZER_BINDER_OFFSET = 500; 291 @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_THRESHOLD = 1_000; 292 @VisibleForTesting static final boolean DEFAULT_FREEZER_BINDER_CALLBACK_ENABLED = true; 293 @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_CALLBACK_THROTTLE = 10_000L; 294 @VisibleForTesting static final int DEFAULT_FREEZER_BINDER_ASYNC_THRESHOLD = 1_024; 295 296 @VisibleForTesting static final Uri CACHED_APP_FREEZER_ENABLED_URI = Settings.Global.getUriFor( 297 Settings.Global.CACHED_APPS_FREEZER_ENABLED); 298 299 @VisibleForTesting 300 interface PropertyChangedCallbackForTest { onPropertyChanged()301 void onPropertyChanged(); 302 } 303 private PropertyChangedCallbackForTest mTestCallback; 304 305 // This interface is for functions related to the Process object that need a different 306 // implementation in the tests as we are not creating real processes when testing compaction. 307 @VisibleForTesting 308 interface ProcessDependencies { getRss(int pid)309 long[] getRss(int pid); performCompaction(CompactProfile action, int pid)310 void performCompaction(CompactProfile action, int pid) throws IOException; 311 } 312 313 // This indicates the compaction we want to perform 314 public enum CompactProfile { 315 NONE, // No compaction 316 SOME, // File compaction 317 ANON, // Anon compaction 318 FULL // File+anon compaction 319 } 320 321 // This indicates who initiated the compaction request 322 public enum CompactSource { APP, SHELL } 323 324 public enum CancelCompactReason { 325 SCREEN_ON, // screen was turned on which cancels all compactions. 326 OOM_IMPROVEMENT // process moved out of cached state and into a more perceptible state. 327 } 328 329 // Handler constants. 330 static final int COMPACT_PROCESS_MSG = 1; 331 static final int COMPACT_SYSTEM_MSG = 2; 332 static final int SET_FROZEN_PROCESS_MSG = 3; 333 static final int REPORT_UNFREEZE_MSG = 4; 334 static final int COMPACT_NATIVE_MSG = 5; 335 static final int UID_FROZEN_STATE_CHANGED_MSG = 6; 336 static final int DEADLOCK_WATCHDOG_MSG = 7; 337 static final int BINDER_ERROR_MSG = 8; 338 339 // When free swap falls below this percentage threshold any full (file + anon) 340 // compactions will be downgraded to file only compactions to reduce pressure 341 // on swap resources as file. 342 static final double COMPACT_DOWNGRADE_FREE_SWAP_THRESHOLD = 0.2; 343 344 static final int DO_FREEZE = 1; 345 static final int REPORT_UNFREEZE = 2; 346 347 // Bitfield values for sync/async transactions reveived by frozen processes 348 static final int SYNC_RECEIVED_WHILE_FROZEN = 1; 349 static final int ASYNC_RECEIVED_WHILE_FROZEN = 2; 350 351 // Bitfield values for sync transactions received by frozen binder threads 352 static final int TXNS_PENDING_WHILE_FROZEN = 4; 353 354 /** 355 * This thread must be moved to the system background cpuset. 356 * If that doesn't happen, it's probably going to draw a lot of power. 357 * However, this has to happen after the first updateOomAdjLocked, because 358 * that will wipe out the cpuset assignment for system_server threads. 359 * Accordingly, this is in the AMS constructor. 360 */ 361 final ServiceThread mCachedAppOptimizerThread; 362 363 @GuardedBy("mProcLock") 364 private final ArrayList<ProcessRecord> mPendingCompactionProcesses = 365 new ArrayList<ProcessRecord>(); 366 367 @GuardedBy("mProcLock") 368 private final SparseArray<ProcessRecord> mFrozenProcesses = 369 new SparseArray<>(); 370 371 private final ActivityManagerService mAm; 372 373 private final ActivityManagerGlobalLock mProcLock; 374 375 public final Object mFreezerLock = new Object(); 376 377 private final OnPropertiesChangedListener mOnFlagsChangedListener = 378 new OnPropertiesChangedListener() { 379 @Override 380 public void onPropertiesChanged(Properties properties) { 381 synchronized (mPhenotypeFlagLock) { 382 for (String name : properties.getKeyset()) { 383 if (KEY_USE_COMPACTION.equals(name)) { 384 updateUseCompaction(); 385 } else if (KEY_COMPACT_THROTTLE_1.equals(name) 386 || KEY_COMPACT_THROTTLE_2.equals(name) 387 || KEY_COMPACT_THROTTLE_3.equals(name) 388 || KEY_COMPACT_THROTTLE_4.equals(name) 389 || KEY_COMPACT_THROTTLE_5.equals(name) 390 || KEY_COMPACT_THROTTLE_6.equals(name)) { 391 updateCompactionThrottles(); 392 } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) { 393 updateCompactStatsdSampleRate(); 394 } else if (KEY_FREEZER_STATSD_SAMPLE_RATE.equals(name)) { 395 updateFreezerStatsdSampleRate(); 396 } else if (KEY_COMPACT_FULL_RSS_THROTTLE_KB.equals(name)) { 397 updateFullRssThrottle(); 398 } else if (KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB.equals(name)) { 399 updateFullDeltaRssThrottle(); 400 } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) { 401 updateProcStateThrottle(); 402 } else if (KEY_COMPACT_THROTTLE_MIN_OOM_ADJ.equals(name)) { 403 updateMinOomAdjThrottle(); 404 } else if (KEY_COMPACT_THROTTLE_MAX_OOM_ADJ.equals(name)) { 405 updateMaxOomAdjThrottle(); 406 } 407 } 408 } 409 if (mTestCallback != null) { 410 mTestCallback.onPropertyChanged(); 411 } 412 } 413 }; 414 415 private final OnPropertiesChangedListener mOnNativeBootFlagsChangedListener = 416 new OnPropertiesChangedListener() { 417 @Override 418 public void onPropertiesChanged(Properties properties) { 419 synchronized (mPhenotypeFlagLock) { 420 for (String name : properties.getKeyset()) { 421 if (KEY_FREEZER_DEBOUNCE_TIMEOUT.equals(name)) { 422 updateFreezerDebounceTimeout(); 423 } else if (KEY_FREEZER_EXEMPT_INST_PKG.equals(name)) { 424 updateFreezerExemptInstPkg(); 425 } else if (KEY_FREEZER_BINDER_ENABLED.equals(name) 426 || KEY_FREEZER_BINDER_DIVISOR.equals(name) 427 || KEY_FREEZER_BINDER_THRESHOLD.equals(name) 428 || KEY_FREEZER_BINDER_OFFSET.equals(name) 429 || KEY_FREEZER_BINDER_CALLBACK_ENABLED.equals(name) 430 || KEY_FREEZER_BINDER_CALLBACK_THROTTLE.equals(name) 431 || KEY_FREEZER_BINDER_ASYNC_THRESHOLD.equals(name)) { 432 updateFreezerBinderState(); 433 } 434 } 435 } 436 if (mTestCallback != null) { 437 mTestCallback.onPropertyChanged(); 438 } 439 } 440 }; 441 442 private final class SettingsContentObserver extends ContentObserver { SettingsContentObserver()443 SettingsContentObserver() { 444 super(mAm.mHandler); 445 } 446 447 @Override onChange(boolean selfChange, Uri uri)448 public void onChange(boolean selfChange, Uri uri) { 449 if (CACHED_APP_FREEZER_ENABLED_URI.equals(uri)) { 450 synchronized (mPhenotypeFlagLock) { 451 updateUseFreezer(); 452 } 453 } 454 } 455 } 456 457 private final SettingsContentObserver mSettingsObserver; 458 459 @VisibleForTesting 460 final Object mPhenotypeFlagLock = new Object(); 461 462 // Configured by phenotype. Updates from the server take effect immediately. 463 @GuardedBy("mPhenotypeFlagLock") 464 @VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1; 465 @GuardedBy("mPhenotypeFlagLock") 466 @VisibleForTesting volatile long mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2; 467 @GuardedBy("mPhenotypeFlagLock") 468 @VisibleForTesting volatile long mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3; 469 @GuardedBy("mPhenotypeFlagLock") 470 @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; 471 @GuardedBy("mPhenotypeFlagLock") 472 @VisibleForTesting volatile long mCompactThrottleMinOomAdj = 473 DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ; 474 @GuardedBy("mPhenotypeFlagLock") 475 @VisibleForTesting volatile long mCompactThrottleMaxOomAdj = 476 DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ; 477 @GuardedBy("mPhenotypeFlagLock") 478 private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION; 479 private volatile boolean mUseFreezer = false; // set to DEFAULT in init() 480 @GuardedBy("this") 481 private int mFreezerDisableCount = 1; // Freezer is initially disabled, until enabled 482 private final Random mRandom = new Random(); 483 @GuardedBy("mPhenotypeFlagLock") 484 @VisibleForTesting volatile float mCompactStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE; 485 @VisibleForTesting volatile float mFreezerStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE; 486 @GuardedBy("mPhenotypeFlagLock") 487 @VisibleForTesting volatile long mFullAnonRssThrottleKb = 488 DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB; 489 @GuardedBy("mPhenotypeFlagLock") 490 @VisibleForTesting volatile long mFullDeltaRssThrottleKb = 491 DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB; 492 @GuardedBy("mPhenotypeFlagLock") 493 @VisibleForTesting final Set<Integer> mProcStateThrottle; 494 495 @GuardedBy("mPhenotypeFlagLock") 496 @VisibleForTesting volatile boolean mFreezerBinderEnabled = DEFAULT_FREEZER_BINDER_ENABLED; 497 @GuardedBy("mPhenotypeFlagLock") 498 @VisibleForTesting volatile long mFreezerBinderDivisor = DEFAULT_FREEZER_BINDER_DIVISOR; 499 @GuardedBy("mPhenotypeFlagLock") 500 @VisibleForTesting volatile int mFreezerBinderOffset = DEFAULT_FREEZER_BINDER_OFFSET; 501 @GuardedBy("mPhenotypeFlagLock") 502 @VisibleForTesting volatile long mFreezerBinderThreshold = DEFAULT_FREEZER_BINDER_THRESHOLD; 503 @GuardedBy("mPhenotypeFlagLock") 504 @VisibleForTesting volatile boolean mFreezerBinderCallbackEnabled = 505 DEFAULT_FREEZER_BINDER_CALLBACK_ENABLED; 506 @GuardedBy("mPhenotypeFlagLock") 507 @VisibleForTesting volatile long mFreezerBinderCallbackThrottle = 508 DEFAULT_FREEZER_BINDER_CALLBACK_THROTTLE; 509 @GuardedBy("mPhenotypeFlagLock") 510 @VisibleForTesting volatile int mFreezerBinderAsyncThreshold = 511 DEFAULT_FREEZER_BINDER_ASYNC_THRESHOLD; 512 513 // Handler on which compaction runs. 514 @VisibleForTesting 515 Handler mCompactionHandler; 516 @VisibleForTesting 517 CompactionStatsManager mCompactStatsManager; 518 519 private Handler mFreezeHandler; 520 @GuardedBy("mProcLock") 521 private boolean mFreezerOverride = false; 522 private long mFreezerBinderCallbackLast = -1; 523 524 @VisibleForTesting volatile long mFreezerDebounceTimeout = DEFAULT_FREEZER_DEBOUNCE_TIMEOUT; 525 @VisibleForTesting volatile boolean mFreezerExemptInstPkg = DEFAULT_FREEZER_EXEMPT_INST_PKG; 526 527 private final ProcessDependencies mProcessDependencies; 528 private final ProcLocksReader mProcLocksReader; 529 530 private final Freezer mFreezer; 531 CachedAppOptimizer(ActivityManagerService am)532 public CachedAppOptimizer(ActivityManagerService am) { 533 this(am, null, new DefaultProcessDependencies()); 534 } 535 536 @VisibleForTesting CachedAppOptimizer(ActivityManagerService am, PropertyChangedCallbackForTest callback, ProcessDependencies processDependencies)537 CachedAppOptimizer(ActivityManagerService am, PropertyChangedCallbackForTest callback, 538 ProcessDependencies processDependencies) { 539 mAm = am; 540 mProcLock = am.mProcLock; 541 mCachedAppOptimizerThread = new ServiceThread("CachedAppOptimizerThread", 542 Process.THREAD_GROUP_SYSTEM, true); 543 mProcStateThrottle = new HashSet<>(); 544 mProcessDependencies = processDependencies; 545 mTestCallback = callback; 546 mSettingsObserver = new SettingsContentObserver(); 547 mProcLocksReader = new ProcLocksReader(); 548 mFreezer = mAm.getFreezer(); 549 } 550 551 /** 552 * Reads phenotype config to determine whether app compaction is enabled or not and 553 * starts the background thread if necessary. 554 */ init()555 public void init() { 556 // TODO: initialize flags to default and only update them if values are set in DeviceConfig 557 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 558 ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener); 559 DeviceConfig.addOnPropertiesChangedListener( 560 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 561 ActivityThread.currentApplication().getMainExecutor(), 562 mOnNativeBootFlagsChangedListener); 563 mAm.mContext.getContentResolver().registerContentObserver( 564 CACHED_APP_FREEZER_ENABLED_URI, false, mSettingsObserver); 565 synchronized (mPhenotypeFlagLock) { 566 updateUseCompaction(); 567 updateCompactionThrottles(); 568 updateCompactStatsdSampleRate(); 569 updateFreezerStatsdSampleRate(); 570 updateFullRssThrottle(); 571 updateFullDeltaRssThrottle(); 572 updateProcStateThrottle(); 573 updateUseFreezer(); 574 updateMinOomAdjThrottle(); 575 updateMaxOomAdjThrottle(); 576 } 577 } 578 579 /** 580 * Returns whether compaction is enabled. 581 */ useCompaction()582 public boolean useCompaction() { 583 synchronized (mPhenotypeFlagLock) { 584 return mUseCompaction; 585 } 586 } 587 588 /** 589 * Returns whether freezer is enabled. 590 */ useFreezer()591 public boolean useFreezer() { 592 synchronized (mPhenotypeFlagLock) { 593 return mUseFreezer; 594 } 595 } 596 597 /** 598 * Returns whether freezer exempts INSTALL_PACKAGES. 599 */ freezerExemptInstPkg()600 public boolean freezerExemptInstPkg() { 601 synchronized (mPhenotypeFlagLock) { 602 return mUseFreezer && mFreezerExemptInstPkg; 603 } 604 } 605 606 @NeverCompile dump(PrintWriter pw)607 void dump(PrintWriter pw) { 608 dumpCompact(pw); 609 dumpFreezer(pw); 610 } 611 612 @NeverCompile dumpCompact(PrintWriter pw)613 void dumpCompact(PrintWriter pw) { 614 pw.println("Compaction settings"); 615 synchronized (mPhenotypeFlagLock) { 616 pw.println(" " + KEY_USE_COMPACTION + "=" + mUseCompaction); 617 pw.println(" " + KEY_COMPACT_THROTTLE_1 + "=" + mCompactThrottleSomeSome); 618 pw.println(" " + KEY_COMPACT_THROTTLE_2 + "=" + mCompactThrottleSomeFull); 619 pw.println(" " + KEY_COMPACT_THROTTLE_3 + "=" + mCompactThrottleFullSome); 620 pw.println(" " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull); 621 pw.println(" " + KEY_COMPACT_THROTTLE_MIN_OOM_ADJ + "=" + mCompactThrottleMinOomAdj); 622 pw.println(" " + KEY_COMPACT_THROTTLE_MAX_OOM_ADJ + "=" + mCompactThrottleMaxOomAdj); 623 pw.println(" " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate); 624 pw.println(" " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "=" 625 + mFullAnonRssThrottleKb); 626 pw.println(" " + KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + "=" 627 + mFullDeltaRssThrottleKb); 628 pw.println(" " + KEY_COMPACT_PROC_STATE_THROTTLE + "=" 629 + Arrays.toString(mProcStateThrottle.toArray(new Integer[0]))); 630 } 631 632 mCompactStatsManager.dump(pw); 633 634 synchronized (mProcLock) { 635 if (!mPendingCompactionProcesses.isEmpty()) { 636 pw.println(" Pending compactions:"); 637 int size = mPendingCompactionProcesses.size(); 638 for (int i = 0; i < size; i++) { 639 ProcessRecord app = mPendingCompactionProcesses.get(i); 640 pw.println(" pid: " + app.getPid() + ". name: " + app.processName 641 + ". hasPendingCompact: " + app.mOptRecord.hasPendingCompact()); 642 } 643 } 644 } 645 pw.println(); 646 } 647 648 @NeverCompile dumpFreezer(PrintWriter pw)649 void dumpFreezer(PrintWriter pw) { 650 pw.println("Freezer settings"); 651 synchronized (mPhenotypeFlagLock) { 652 pw.println(" " + KEY_USE_FREEZER + "=" + mUseFreezer); 653 pw.println(" " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate); 654 pw.println(" " + KEY_FREEZER_DEBOUNCE_TIMEOUT + "=" + mFreezerDebounceTimeout); 655 pw.println(" " + KEY_FREEZER_EXEMPT_INST_PKG + "=" + mFreezerExemptInstPkg); 656 pw.println(" " + KEY_FREEZER_BINDER_ENABLED + "=" + mFreezerBinderEnabled); 657 pw.println(" " + KEY_FREEZER_BINDER_THRESHOLD + "=" + mFreezerBinderThreshold); 658 pw.println(" " + KEY_FREEZER_BINDER_DIVISOR + "=" + mFreezerBinderDivisor); 659 pw.println(" " + KEY_FREEZER_BINDER_OFFSET + "=" + mFreezerBinderOffset); 660 pw.println(" " + KEY_FREEZER_BINDER_CALLBACK_ENABLED + "=" 661 + mFreezerBinderCallbackEnabled); 662 pw.println(" " + KEY_FREEZER_BINDER_CALLBACK_THROTTLE + "=" 663 + mFreezerBinderCallbackThrottle); 664 pw.println(" " + KEY_FREEZER_BINDER_ASYNC_THRESHOLD + "=" 665 + mFreezerBinderAsyncThreshold); 666 synchronized (mProcLock) { 667 int size = mFrozenProcesses.size(); 668 pw.println(" Apps frozen: " + size); 669 for (int i = 0; i < size; i++) { 670 ProcessRecord app = mFrozenProcesses.valueAt(i); 671 pw.println(" " + app.mOptRecord.getFreezeUnfreezeTime() + ": " + app.getPid() 672 + " " + app.processName 673 + (app.mOptRecord.isFreezeSticky() ? " (sticky)" : "")); 674 } 675 } 676 } 677 } 678 679 @GuardedBy("mProcLock") compactApp( ProcessRecord app, CompactProfile compactProfile, CompactSource source, boolean force)680 boolean compactApp( 681 ProcessRecord app, CompactProfile compactProfile, CompactSource source, boolean force) { 682 app.mOptRecord.setReqCompactSource(source); 683 app.mOptRecord.setReqCompactProfile(compactProfile); 684 685 if(compactProfile == null || compactProfile.equals(CompactProfile.NONE)) { 686 return false; 687 } 688 final String processName = (app.processName != null ? app.processName : ""); 689 mCompactStatsManager.logCompactionRequested(source, compactProfile, processName); 690 691 if (!app.mOptRecord.hasPendingCompact()) { 692 if (DEBUG_COMPACTION) { 693 Slog.d(TAG_AM, 694 "compactApp " + app.mOptRecord.getReqCompactSource().name() + " " 695 + app.mOptRecord.getReqCompactProfile().name() + " " + processName); 696 } 697 app.mOptRecord.setHasPendingCompact(true); 698 app.mOptRecord.setForceCompact(force); 699 mPendingCompactionProcesses.add(app); 700 mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( 701 COMPACT_PROCESS_MSG, app.mState.getCurAdj(), app.mState.getSetProcState())); 702 return true; 703 } 704 705 if (DEBUG_COMPACTION) { 706 Slog.d(TAG_AM, 707 " compactApp Skipped for " + app.processName + " pendingCompact= " 708 + app.mOptRecord.hasPendingCompact() + ". Requested compact profile: " 709 + app.mOptRecord.getReqCompactProfile().name() + ". Compact source " 710 + app.mOptRecord.getReqCompactSource().name()); 711 } 712 return false; 713 } 714 compactNative(CompactProfile compactProfile, int pid)715 void compactNative(CompactProfile compactProfile, int pid) { 716 mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( 717 COMPACT_NATIVE_MSG, pid, compactProfile.ordinal())); 718 } 719 compactAllSystem()720 void compactAllSystem() { 721 if (useCompaction()) { 722 if (DEBUG_COMPACTION) { 723 Slog.d(TAG_AM, "compactAllSystem"); 724 } 725 Trace.instantForTrack( 726 Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_COMPACTION_TRACK, "compactAllSystem"); 727 mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( 728 COMPACT_SYSTEM_MSG)); 729 } 730 } 731 compactSystem()732 private native void compactSystem(); 733 734 /** 735 * Compacts a process or app 736 * @param pid pid of process to compact 737 * @param compactionFlags selects the compaction type as defined by COMPACT_ACTION_{TYPE}_FLAG 738 * constants 739 */ compactProcess(int pid, int compactionFlags)740 static private native void compactProcess(int pid, int compactionFlags); 741 cancelCompaction()742 static private native void cancelCompaction(); 743 744 /** 745 * Returns the cpu time for the current thread 746 */ threadCpuTimeNs()747 static private native long threadCpuTimeNs(); 748 749 /** 750 * Retrieves the free swap percentage. 751 */ getFreeSwapPercent()752 static native double getFreeSwapPercent(); 753 754 /** 755 * Retrieves the total used physical ZRAM 756 */ getUsedZramMemory()757 static private native long getUsedZramMemory(); 758 759 /** 760 * Amount of memory that has been made free due to compaction. 761 * It represents uncompressed memory size - compressed memory size. 762 */ getMemoryFreedCompaction()763 static private native long getMemoryFreedCompaction(); 764 765 /** 766 * Reads the flag value from DeviceConfig to determine whether app compaction 767 * should be enabled, and starts the freeze/compaction thread if needed. 768 */ 769 @GuardedBy("mPhenotypeFlagLock") updateUseCompaction()770 private void updateUseCompaction() { 771 mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 772 KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION); 773 774 if (mUseCompaction && mCompactionHandler == null) { 775 if (!mCachedAppOptimizerThread.isAlive()) { 776 mCachedAppOptimizerThread.start(); 777 } 778 779 mCompactionHandler = new MemCompactionHandler(); 780 mCompactStatsManager = CompactionStatsManager.getInstance(); 781 782 Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(), 783 Process.THREAD_GROUP_SYSTEM); 784 } 785 } 786 787 /** 788 * Enables or disabled the app freezer. 789 * @param enable Enables the freezer if true, disables it if false. 790 * @return true if the operation completed successfully, false otherwise. 791 */ enableFreezer(boolean enable)792 public synchronized boolean enableFreezer(boolean enable) { 793 if (!mUseFreezer) { 794 return false; 795 } 796 797 if (enable) { 798 mFreezerDisableCount--; 799 800 if (mFreezerDisableCount > 0) { 801 return true; 802 } else if (mFreezerDisableCount < 0) { 803 Slog.e(TAG_AM, "unbalanced call to enableFreezer, ignoring"); 804 mFreezerDisableCount = 0; 805 return false; 806 } 807 } else { 808 mFreezerDisableCount++; 809 810 if (mFreezerDisableCount > 1) { 811 return true; 812 } 813 } 814 815 // Override is applied immediately, restore is delayed 816 synchronized (mAm) { 817 synchronized (mProcLock) { 818 mFreezerOverride = !enable; 819 Slog.d(TAG_AM, "freezer override set to " + mFreezerOverride); 820 821 mAm.mProcessList.forEachLruProcessesLOSP(true, process -> { 822 if (process == null) { 823 return; 824 } 825 826 final ProcessCachedOptimizerRecord opt = process.mOptRecord; 827 if (enable && opt.hasFreezerOverride()) { 828 freezeAppAsyncLSP(process); 829 opt.setFreezerOverride(false); 830 } 831 832 if (!enable && opt.isFrozen()) { 833 unfreezeAppLSP(process, UNFREEZE_REASON_FEATURE_FLAGS); 834 835 // Set freezerOverride *after* calling unfreezeAppLSP (it resets the flag) 836 opt.setFreezerOverride(true); 837 } 838 }); 839 } 840 } 841 842 return true; 843 } 844 845 /** 846 * Reads the flag value from DeviceConfig to determine whether app freezer 847 * should be enabled, and starts the freeze/compaction thread if needed. 848 */ 849 @GuardedBy("mPhenotypeFlagLock") updateUseFreezer()850 private void updateUseFreezer() { 851 final String configOverride = Settings.Global.getString(mAm.mContext.getContentResolver(), 852 Settings.Global.CACHED_APPS_FREEZER_ENABLED); 853 854 if ("disabled".equals(configOverride)) { 855 mUseFreezer = false; 856 } else if ("enabled".equals(configOverride) 857 || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 858 KEY_USE_FREEZER, DEFAULT_USE_FREEZER)) { 859 mUseFreezer = mFreezer.isFreezerSupported(); 860 updateFreezerDebounceTimeout(); 861 updateFreezerExemptInstPkg(); 862 } else { 863 mUseFreezer = false; 864 } 865 866 final boolean useFreezer = mUseFreezer; 867 // enableFreezer() would need the global ActivityManagerService lock, post it. 868 mAm.mHandler.post(() -> { 869 if (useFreezer) { 870 Slog.d(TAG_AM, "Freezer enabled"); 871 enableFreezer(true); 872 873 if (!mCachedAppOptimizerThread.isAlive()) { 874 mCachedAppOptimizerThread.start(); 875 } 876 877 if (mFreezeHandler == null) { 878 mFreezeHandler = new FreezeHandler(); 879 } 880 881 Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(), 882 Process.THREAD_GROUP_SYSTEM); 883 } else { 884 Slog.d(TAG_AM, "Freezer disabled"); 885 enableFreezer(false); 886 } 887 }); 888 } 889 890 @GuardedBy("mPhenotypeFlagLock") updateCompactionThrottles()891 private void updateCompactionThrottles() { 892 boolean useThrottleDefaults = false; 893 // TODO: improve efficiency by calling DeviceConfig only once for all flags. 894 String throttleSomeSomeFlag = 895 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 896 KEY_COMPACT_THROTTLE_1); 897 String throttleSomeFullFlag = 898 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 899 KEY_COMPACT_THROTTLE_2); 900 String throttleFullSomeFlag = 901 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 902 KEY_COMPACT_THROTTLE_3); 903 String throttleFullFullFlag = 904 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 905 KEY_COMPACT_THROTTLE_4); 906 String throttleBFGSFlag = 907 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 908 KEY_COMPACT_THROTTLE_5); 909 String throttlePersistentFlag = 910 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 911 KEY_COMPACT_THROTTLE_6); 912 String throttleMinOomAdjFlag = 913 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 914 KEY_COMPACT_THROTTLE_MIN_OOM_ADJ); 915 String throttleMaxOomAdjFlag = 916 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 917 KEY_COMPACT_THROTTLE_MAX_OOM_ADJ); 918 919 if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) 920 || TextUtils.isEmpty(throttleFullSomeFlag) 921 || TextUtils.isEmpty(throttleFullFullFlag) 922 || TextUtils.isEmpty(throttleBFGSFlag) 923 || TextUtils.isEmpty(throttlePersistentFlag) 924 || TextUtils.isEmpty(throttleMinOomAdjFlag) 925 || TextUtils.isEmpty(throttleMaxOomAdjFlag)) { 926 // Set defaults for all if any are not set. 927 useThrottleDefaults = true; 928 } else { 929 try { 930 mCompactThrottleSomeSome = Integer.parseInt(throttleSomeSomeFlag); 931 mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag); 932 mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag); 933 mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); 934 mCompactThrottleMinOomAdj = Long.parseLong(throttleMinOomAdjFlag); 935 mCompactThrottleMaxOomAdj = Long.parseLong(throttleMaxOomAdjFlag); 936 } catch (NumberFormatException e) { 937 useThrottleDefaults = true; 938 } 939 } 940 941 if (useThrottleDefaults) { 942 mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1; 943 mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2; 944 mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3; 945 mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; 946 mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ; 947 mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ; 948 } 949 } 950 951 @GuardedBy("mPhenotypeFlagLock") updateCompactStatsdSampleRate()952 private void updateCompactStatsdSampleRate() { 953 mCompactStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 954 KEY_COMPACT_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE); 955 mCompactStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mCompactStatsdSampleRate)); 956 } 957 958 @GuardedBy("mPhenotypeFlagLock") updateFreezerStatsdSampleRate()959 private void updateFreezerStatsdSampleRate() { 960 mFreezerStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 961 KEY_FREEZER_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE); 962 mFreezerStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mFreezerStatsdSampleRate)); 963 } 964 965 @GuardedBy("mPhenotypeFlagLock") updateFullRssThrottle()966 private void updateFullRssThrottle() { 967 mFullAnonRssThrottleKb = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 968 KEY_COMPACT_FULL_RSS_THROTTLE_KB, DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB); 969 970 // Don't allow negative values. 0 means don't apply the throttle. 971 if (mFullAnonRssThrottleKb < 0) { 972 mFullAnonRssThrottleKb = DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB; 973 } 974 } 975 976 @GuardedBy("mPhenotypeFlagLock") updateFullDeltaRssThrottle()977 private void updateFullDeltaRssThrottle() { 978 mFullDeltaRssThrottleKb = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 979 KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB); 980 981 if (mFullDeltaRssThrottleKb < 0) { 982 mFullDeltaRssThrottleKb = DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB; 983 } 984 } 985 986 @GuardedBy("mPhenotypeFlagLock") updateProcStateThrottle()987 private void updateProcStateThrottle() { 988 String procStateThrottleString = DeviceConfig.getString( 989 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_PROC_STATE_THROTTLE, 990 DEFAULT_COMPACT_PROC_STATE_THROTTLE); 991 if (!parseProcStateThrottle(procStateThrottleString)) { 992 Slog.w(TAG_AM, "Unable to parse app compact proc state throttle \"" 993 + procStateThrottleString + "\" falling back to default."); 994 if (!parseProcStateThrottle(DEFAULT_COMPACT_PROC_STATE_THROTTLE)) { 995 Slog.wtf(TAG_AM, 996 "Unable to parse default app compact proc state throttle " 997 + DEFAULT_COMPACT_PROC_STATE_THROTTLE); 998 } 999 } 1000 } 1001 1002 @GuardedBy("mPhenotypeFlagLock") updateMinOomAdjThrottle()1003 private void updateMinOomAdjThrottle() { 1004 mCompactThrottleMinOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1005 KEY_COMPACT_THROTTLE_MIN_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ); 1006 1007 // Should only compact cached processes. 1008 if (mCompactThrottleMinOomAdj < ProcessList.CACHED_APP_MIN_ADJ) { 1009 mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ; 1010 } 1011 } 1012 1013 @GuardedBy("mPhenotypeFlagLock") updateMaxOomAdjThrottle()1014 private void updateMaxOomAdjThrottle() { 1015 mCompactThrottleMaxOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1016 KEY_COMPACT_THROTTLE_MAX_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ); 1017 1018 // Should only compact cached processes. 1019 if (mCompactThrottleMaxOomAdj > ProcessList.CACHED_APP_MAX_ADJ) { 1020 mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ; 1021 } 1022 } 1023 1024 @GuardedBy("mPhenotypeFlagLock") updateFreezerDebounceTimeout()1025 private void updateFreezerDebounceTimeout() { 1026 mFreezerDebounceTimeout = DeviceConfig.getLong( 1027 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1028 KEY_FREEZER_DEBOUNCE_TIMEOUT, DEFAULT_FREEZER_DEBOUNCE_TIMEOUT); 1029 1030 if (mFreezerDebounceTimeout < 0) { 1031 mFreezerDebounceTimeout = DEFAULT_FREEZER_DEBOUNCE_TIMEOUT; 1032 } 1033 Slog.d(TAG_AM, "Freezer timeout set to " + mFreezerDebounceTimeout); 1034 } 1035 1036 @GuardedBy("mPhenotypeFlagLock") updateFreezerExemptInstPkg()1037 private void updateFreezerExemptInstPkg() { 1038 mFreezerExemptInstPkg = DeviceConfig.getBoolean( 1039 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1040 KEY_FREEZER_EXEMPT_INST_PKG, DEFAULT_FREEZER_EXEMPT_INST_PKG); 1041 Slog.d(TAG_AM, "Freezer exemption set to " + mFreezerExemptInstPkg); 1042 } 1043 1044 @GuardedBy("mPhenotypeFlagLock") updateFreezerBinderState()1045 private void updateFreezerBinderState() { 1046 mFreezerBinderEnabled = DeviceConfig.getBoolean( 1047 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1048 KEY_FREEZER_BINDER_ENABLED, DEFAULT_FREEZER_BINDER_ENABLED); 1049 mFreezerBinderDivisor = DeviceConfig.getLong( 1050 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1051 KEY_FREEZER_BINDER_DIVISOR, DEFAULT_FREEZER_BINDER_DIVISOR); 1052 mFreezerBinderOffset = DeviceConfig.getInt( 1053 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1054 KEY_FREEZER_BINDER_OFFSET, DEFAULT_FREEZER_BINDER_OFFSET); 1055 mFreezerBinderThreshold = DeviceConfig.getLong( 1056 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1057 KEY_FREEZER_BINDER_THRESHOLD, DEFAULT_FREEZER_BINDER_THRESHOLD); 1058 mFreezerBinderCallbackEnabled = DeviceConfig.getBoolean( 1059 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1060 KEY_FREEZER_BINDER_CALLBACK_ENABLED, DEFAULT_FREEZER_BINDER_CALLBACK_ENABLED); 1061 mFreezerBinderCallbackThrottle = DeviceConfig.getLong( 1062 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1063 KEY_FREEZER_BINDER_CALLBACK_THROTTLE, DEFAULT_FREEZER_BINDER_CALLBACK_THROTTLE); 1064 mFreezerBinderAsyncThreshold = DeviceConfig.getInt( 1065 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, 1066 KEY_FREEZER_BINDER_ASYNC_THRESHOLD, DEFAULT_FREEZER_BINDER_ASYNC_THRESHOLD); 1067 Slog.d(TAG_AM, "Freezer binder state set to enabled=" + mFreezerBinderEnabled 1068 + ", divisor=" + mFreezerBinderDivisor 1069 + ", offset=" + mFreezerBinderOffset 1070 + ", threshold=" + mFreezerBinderThreshold 1071 + ", callback enabled=" + mFreezerBinderCallbackEnabled 1072 + ", callback throttle=" + mFreezerBinderCallbackThrottle 1073 + ", async threshold=" + mFreezerBinderAsyncThreshold); 1074 } 1075 parseProcStateThrottle(String procStateThrottleString)1076 private boolean parseProcStateThrottle(String procStateThrottleString) { 1077 String[] procStates = TextUtils.split(procStateThrottleString, ","); 1078 mProcStateThrottle.clear(); 1079 for (String procState : procStates) { 1080 try { 1081 mProcStateThrottle.add(Integer.parseInt(procState)); 1082 } catch (NumberFormatException e) { 1083 Slog.e(TAG_AM, "Failed to parse default app compaction proc state: " 1084 + procState); 1085 return false; 1086 } 1087 } 1088 return true; 1089 } 1090 1091 /** 1092 * Returns the earliest time (relative) from now that the app can be frozen. 1093 * @param app The app to update 1094 * @param delayMillis How much to delay freezing by 1095 */ 1096 @GuardedBy("mProcLock") updateEarliestFreezableTime(ProcessRecord app, long delayMillis)1097 private long updateEarliestFreezableTime(ProcessRecord app, long delayMillis) { 1098 final long now = SystemClock.uptimeMillis(); 1099 app.mOptRecord.setEarliestFreezableTime( 1100 Math.max(app.mOptRecord.getEarliestFreezableTime(), now + delayMillis)); 1101 return app.mOptRecord.getEarliestFreezableTime() - now; 1102 } 1103 1104 // This will ensure app will be out of the freezer for at least mFreezerDebounceTimeout. 1105 @GuardedBy("mAm") unfreezeTemporarily(ProcessRecord app, @UnfreezeReason int reason)1106 void unfreezeTemporarily(ProcessRecord app, @UnfreezeReason int reason) { 1107 unfreezeTemporarily(app, reason, mFreezerDebounceTimeout); 1108 } 1109 1110 // This will ensure app will be out of the freezer for at least mFreezerDebounceTimeout. 1111 @GuardedBy("mAm") unfreezeTemporarily(ProcessRecord app, @UnfreezeReason int reason, long delayMillis)1112 void unfreezeTemporarily(ProcessRecord app, @UnfreezeReason int reason, long delayMillis) { 1113 if (mUseFreezer) { 1114 synchronized (mProcLock) { 1115 // Move the earliest freezable time further, if necessary 1116 final long delay = updateEarliestFreezableTime(app, delayMillis); 1117 if (app.mOptRecord.isFrozen() || app.mOptRecord.isPendingFreeze()) { 1118 unfreezeAppLSP(app, reason); 1119 freezeAppAsyncLSP(app, delay); 1120 } 1121 } 1122 } 1123 } 1124 1125 @GuardedBy({"mAm", "mProcLock"}) freezeAppAsyncLSP(ProcessRecord app)1126 void freezeAppAsyncLSP(ProcessRecord app) { 1127 freezeAppAsyncLSP(app, updateEarliestFreezableTime(app, mFreezerDebounceTimeout)); 1128 } 1129 1130 @GuardedBy({"mAm", "mProcLock"}) forceFreezeAppAsyncLSP(ProcessRecord app)1131 void forceFreezeAppAsyncLSP(ProcessRecord app) { 1132 freezeAppAsyncInternalLSP(app, 0 /* delayMillis */, true /* force */); 1133 } 1134 1135 @GuardedBy({"mAm", "mProcLock"}) freezeAppAsyncLSP(ProcessRecord app, @UptimeMillisLong long delayMillis)1136 private void freezeAppAsyncLSP(ProcessRecord app, @UptimeMillisLong long delayMillis) { 1137 freezeAppAsyncInternalLSP(app, delayMillis, false /* force */); 1138 } 1139 1140 @GuardedBy({"mAm", "mProcLock"}) freezeAppAsyncAtEarliestLSP(ProcessRecord app)1141 void freezeAppAsyncAtEarliestLSP(ProcessRecord app) { 1142 freezeAppAsyncLSP(app, updateEarliestFreezableTime(app, 0)); 1143 } 1144 1145 // TODO: Update freezeAppAsyncAtEarliestLSP to actually freeze the app at the earliest 1146 // and remove this method. 1147 @GuardedBy({"mAm", "mProcLock"}) freezeAppAsyncImmediateLSP(ProcessRecord app)1148 void freezeAppAsyncImmediateLSP(ProcessRecord app) { 1149 freezeAppAsyncInternalLSP(app, 0 /* delayMillis */, false /* force */); 1150 } 1151 1152 @GuardedBy({"mAm", "mProcLock"}) freezeAppAsyncInternalLSP(ProcessRecord app, @UptimeMillisLong long delayMillis, boolean force)1153 private void freezeAppAsyncInternalLSP(ProcessRecord app, @UptimeMillisLong long delayMillis, 1154 boolean force) { 1155 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 1156 if (opt.isPendingFreeze()) { 1157 if (delayMillis == 0) { 1158 // Caller is requesting to freeze the process without delay, so remove 1159 // any already posted messages which would have been handled with a delay and 1160 // post a new message without a delay. 1161 mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app); 1162 mFreezeHandler.sendMessage(mFreezeHandler.obtainMessage( 1163 SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app)); 1164 } 1165 // Skip redundant DO_FREEZE message 1166 return; 1167 } 1168 1169 if (opt.isFreezeSticky() && !force) { 1170 if (DEBUG_FREEZER) { 1171 Slog.d(TAG_AM, 1172 "Skip freezing because unfrozen state is sticky pid=" + app.getPid() + " " 1173 + app.processName); 1174 } 1175 return; 1176 } 1177 1178 if (app.mState.getSetAdj() >= ProcessList.CACHED_APP_MIN_ADJ) { 1179 final IApplicationThread thread = app.getThread(); 1180 if (thread != null) { 1181 try { 1182 thread.scheduleTrimMemory(TRIM_MEMORY_BACKGROUND); 1183 } catch (RemoteException e) { 1184 // do nothing 1185 } 1186 } 1187 } 1188 reportProcessFreezableChangedLocked(app); 1189 app.mOptRecord.setLastUsedTimeout(delayMillis); 1190 mFreezeHandler.sendMessageDelayed( 1191 mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app), 1192 delayMillis); 1193 opt.setPendingFreeze(true); 1194 if (DEBUG_FREEZER) { 1195 Slog.d(TAG_AM, "Async freezing " + app.getPid() + " " + app.processName); 1196 } 1197 } 1198 1199 /** 1200 * Returns true if the app was frozen and became unfrozen, otherwise false. 1201 * 1202 * Do not call this directly. It will unfreeze a process but it will not send out any 1203 * notifications. Instead call unfreezeAppLSP(). 1204 */ 1205 @GuardedBy({"mAm", "mProcLock", "mFreezerLock"}) unfreezeAppInternalLSP(ProcessRecord app, @UnfreezeReason int reason, boolean force)1206 private boolean unfreezeAppInternalLSP(ProcessRecord app, @UnfreezeReason int reason, 1207 boolean force) { 1208 final int pid = app.getPid(); 1209 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 1210 boolean sticky = opt.isFreezeSticky(); 1211 if (sticky && !force) { 1212 // Sticky freezes will not change their state unless forced out of it. 1213 if (DEBUG_FREEZER) { 1214 Slog.d(TAG_AM, 1215 "Skip unfreezing because frozen state is sticky pid=" + pid + " " 1216 + app.processName); 1217 } 1218 return false; 1219 } 1220 boolean processFreezableChangeReported = false; 1221 if (opt.isPendingFreeze()) { 1222 // Remove pending DO_FREEZE message 1223 mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app); 1224 opt.setPendingFreeze(false); 1225 reportProcessFreezableChangedLocked(app); 1226 processFreezableChangeReported = true; 1227 if (DEBUG_FREEZER) { 1228 Slog.d(TAG_AM, "Cancel freezing " + pid + " " + app.processName); 1229 } 1230 } 1231 1232 UidRecord uidRec = app.getUidRecord(); 1233 if (uidRec != null && uidRec.isFrozen()) { 1234 uidRec.setFrozen(false); 1235 postUidFrozenMessage(uidRec.getUid(), false); 1236 } 1237 1238 opt.setFreezerOverride(false); 1239 if (pid == 0 || !opt.isFrozen()) { 1240 return false; 1241 } 1242 1243 // Unfreeze the binder interface first, to avoid transactions triggered by timers fired 1244 // right after unfreezing the process to fail 1245 boolean processKilled = false; 1246 1247 try { 1248 int freezeInfo = mFreezer.getBinderFreezeInfo(pid); 1249 1250 if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) { 1251 Slog.d(TAG_AM, "pid " + pid + " " + app.processName 1252 + " received sync transactions while frozen, killing"); 1253 app.killLocked("Sync transaction while in frozen state", 1254 ApplicationExitInfo.REASON_FREEZER, 1255 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_TRANSACTION, true); 1256 processKilled = true; 1257 } 1258 1259 if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0 && DEBUG_FREEZER) { 1260 Slog.d(TAG_AM, "pid " + pid + " " + app.processName 1261 + " received async transactions while frozen"); 1262 } 1263 } catch (Exception e) { 1264 Slog.d(TAG_AM, "Unable to query binder frozen info for pid " + pid + " " 1265 + app.processName + ". Killing it. Exception: " + e); 1266 app.killLocked("Unable to query binder frozen stats", 1267 ApplicationExitInfo.REASON_FREEZER, 1268 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true); 1269 processKilled = true; 1270 } 1271 1272 if (processKilled) { 1273 return false; 1274 } 1275 if (!processFreezableChangeReported) { 1276 reportProcessFreezableChangedLocked(app); 1277 } 1278 1279 long freezeTime = opt.getFreezeUnfreezeTime(); 1280 1281 try { 1282 mFreezer.freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS); 1283 } catch (RuntimeException e) { 1284 Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName 1285 + ". Killing it"); 1286 app.killLocked("Unable to unfreeze", 1287 ApplicationExitInfo.REASON_FREEZER, 1288 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true); 1289 return false; 1290 } 1291 1292 try { 1293 traceAppFreeze(app.processName, pid, reason); 1294 mFreezer.setProcessFrozen(pid, app.uid, false); 1295 1296 opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis()); 1297 opt.setFrozen(false); 1298 mFrozenProcesses.delete(pid); 1299 } catch (Exception e) { 1300 Slog.e(TAG_AM, "Unable to unfreeze " + pid + " " + app.processName 1301 + ". This might cause inconsistency or UI hangs."); 1302 } 1303 1304 if (!opt.isFrozen()) { 1305 Slog.d(TAG_AM, "sync unfroze " + pid + " " + app.processName + " for " + reason); 1306 1307 mFreezeHandler.sendMessage( 1308 mFreezeHandler.obtainMessage(REPORT_UNFREEZE_MSG, 1309 pid, 1310 (int) Math.min(opt.getFreezeUnfreezeTime() - freezeTime, Integer.MAX_VALUE), 1311 new Pair<ProcessRecord, Integer>(app, reason))); 1312 return true; 1313 } 1314 return false; 1315 } 1316 1317 @GuardedBy({"mAm", "mProcLock"}) unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason, boolean force)1318 void unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason, boolean force) { 1319 final boolean shouldDispatch; 1320 synchronized (mFreezerLock) { 1321 shouldDispatch = unfreezeAppInternalLSP(app, reason, force); 1322 } 1323 if (shouldDispatch) { 1324 app.mOptRecord.dispatchUnfrozenEvent(); 1325 } 1326 } 1327 1328 @GuardedBy({"mAm", "mProcLock"}) unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason)1329 void unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason) { 1330 unfreezeAppLSP(app, reason, false); 1331 } 1332 1333 /** 1334 * This quick function works around the race condition between WM/ATMS and AMS, allowing 1335 * the former to directly unfreeze a frozen process before the latter runs updateOomAdj. 1336 * After the race issue is solved, this workaround can be removed. (b/213288355) 1337 * The caller of this function should still trigger updateOomAdj for AMS to unfreeze the app. 1338 * @param pid pid of the process to be unfrozen 1339 */ unfreezeProcess(int pid, @OomAdjReason int reason)1340 void unfreezeProcess(int pid, @OomAdjReason int reason) { 1341 final ProcessRecord app; 1342 synchronized (mFreezerLock) { 1343 app = mFrozenProcesses.get(pid); 1344 if (app == null) { 1345 return; 1346 } 1347 Slog.d(TAG_AM, "quick sync unfreeze " + pid + " for " + reason); 1348 try { 1349 mFreezer.freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS); 1350 } catch (RuntimeException e) { 1351 Slog.e(TAG_AM, "Unable to quick unfreeze binder for " + pid); 1352 return; 1353 } 1354 1355 try { 1356 traceAppFreeze(app.processName, pid, reason); 1357 mFreezer.setProcessFrozen(pid, app.uid, false); 1358 } catch (Exception e) { 1359 Slog.e(TAG_AM, "Unable to quick unfreeze " + pid); 1360 } 1361 } 1362 app.mOptRecord.dispatchUnfrozenEvent(); 1363 } 1364 1365 /** 1366 * Trace app freeze status 1367 * @param processName The name of the target process 1368 * @param pid The pid of the target process 1369 * @param reason UNFREEZE_REASON_XXX (>=0) for unfreezing and -1 for freezing 1370 */ traceAppFreeze(String processName, int pid, int reason)1371 private static void traceAppFreeze(String processName, int pid, int reason) { 1372 Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_FREEZER_TRACK, 1373 (reason < 0 ? "Freeze " : "Unfreeze ") + processName + ":" + pid + " " + reason); 1374 } 1375 1376 /** 1377 * To be called when the given app is killed. 1378 */ 1379 @GuardedBy({"mAm", "mProcLock"}) onCleanupApplicationRecordLocked(ProcessRecord app)1380 void onCleanupApplicationRecordLocked(ProcessRecord app) { 1381 if (mUseFreezer) { 1382 final ProcessCachedOptimizerRecord opt = app.mOptRecord; 1383 if (opt.isPendingFreeze()) { 1384 // Remove pending DO_FREEZE message 1385 mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app); 1386 opt.setPendingFreeze(false); 1387 } 1388 1389 final UidRecord uidRec = app.getUidRecord(); 1390 if (uidRec != null) { 1391 final boolean isFrozen = uidRec.getNumOfProcs() > 1 1392 && uidRec.areAllProcessesFrozen(app); 1393 if (isFrozen != uidRec.isFrozen()) { 1394 uidRec.setFrozen(isFrozen); 1395 postUidFrozenMessage(uidRec.getUid(), isFrozen); 1396 } 1397 } 1398 1399 mFrozenProcesses.delete(app.getPid()); 1400 } 1401 } 1402 onWakefulnessChanged(int wakefulness)1403 void onWakefulnessChanged(int wakefulness) { 1404 if(wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) { 1405 if (useCompaction()) { 1406 // Remove any pending compaction we may have scheduled to happen while screen was 1407 // off 1408 cancelAllCompactions(CancelCompactReason.SCREEN_ON); 1409 } 1410 } 1411 } 1412 cancelAllCompactions(CancelCompactReason reason)1413 void cancelAllCompactions(CancelCompactReason reason) { 1414 synchronized (mProcLock) { 1415 while(!mPendingCompactionProcesses.isEmpty()) { 1416 if (DEBUG_COMPACTION) { 1417 Slog.e(TAG_AM, 1418 "Cancel pending compaction as system is awake for process=" 1419 + mPendingCompactionProcesses.get(0).processName); 1420 } 1421 cancelCompactionForProcess(mPendingCompactionProcesses.get(0), reason); 1422 } 1423 mPendingCompactionProcesses.clear(); 1424 } 1425 } 1426 1427 @GuardedBy("mProcLock") cancelCompactionForProcess(ProcessRecord app, CancelCompactReason cancelReason)1428 void cancelCompactionForProcess(ProcessRecord app, CancelCompactReason cancelReason) { 1429 boolean cancelled = false; 1430 if (mPendingCompactionProcesses.contains(app)) { 1431 app.mOptRecord.setHasPendingCompact(false); 1432 mPendingCompactionProcesses.remove(app); 1433 cancelled = true; 1434 } 1435 if (DefaultProcessDependencies.mPidCompacting == app.mPid) { 1436 cancelCompaction(); 1437 cancelled = true; 1438 } 1439 if (cancelled) { 1440 mCompactStatsManager.logCompactionCancelled(cancelReason); 1441 if (DEBUG_COMPACTION) { 1442 Slog.d(TAG_AM, 1443 "Cancelled pending or running compactions for process: " + 1444 app.processName != null ? app.processName : "" + 1445 " reason: " + cancelReason.name()); 1446 } 1447 } 1448 } 1449 1450 @GuardedBy({"mService", "mProcLock"}) onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app)1451 void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) { 1452 if (useCompaction()) { 1453 // Cancel any currently executing compactions 1454 // if the process moved out of cached state 1455 if (newAdj < oldAdj && newAdj < ProcessList.CACHED_APP_MIN_ADJ) { 1456 cancelCompactionForProcess(app, CancelCompactReason.OOM_IMPROVEMENT); 1457 } 1458 } 1459 } 1460 1461 /** 1462 * Callback received after a process has been frozen. 1463 */ onProcessFrozen(ProcessRecord frozenProc)1464 void onProcessFrozen(ProcessRecord frozenProc) { 1465 if (useCompaction()) { 1466 synchronized (mProcLock) { 1467 // only full-compact if process is cached 1468 if (frozenProc.mState.getSetAdj() >= mCompactThrottleMinOomAdj) { 1469 compactApp(frozenProc, CompactProfile.FULL, CompactSource.APP, false); 1470 } 1471 } 1472 } 1473 frozenProc.onProcessFrozen(); 1474 } 1475 1476 /** 1477 * Callback received when an attempt to freeze a process is cancelled (failed). 1478 */ onProcessFrozenCancelled(ProcessRecord app)1479 void onProcessFrozenCancelled(ProcessRecord app) { 1480 app.onProcessFrozenCancelled(); 1481 } 1482 1483 /** 1484 * Computes the final compaction profile to be used which depends on compaction 1485 * features enabled and swap usage. 1486 */ resolveCompactionProfile(CompactProfile profile)1487 CompactProfile resolveCompactionProfile(CompactProfile profile) { 1488 if (profile == CompactProfile.FULL) { 1489 double swapFreePercent = getFreeSwapPercent(); 1490 // Downgrade compaction under swap memory pressure 1491 if (swapFreePercent < COMPACT_DOWNGRADE_FREE_SWAP_THRESHOLD) { 1492 profile = CompactProfile.SOME; 1493 mCompactStatsManager.logCompactionDowngrade(); 1494 if (DEBUG_COMPACTION) { 1495 Slog.d(TAG_AM, 1496 "Downgraded compaction to "+ profile +" due to low swap." 1497 + " Swap Free% " + swapFreePercent); 1498 } 1499 } 1500 } 1501 1502 if (!ENABLE_SHARED_AND_CODE_COMPACT) { 1503 if (profile == CompactProfile.SOME) { 1504 profile = CompactProfile.NONE; 1505 } else if (profile == CompactProfile.FULL) { 1506 profile = CompactProfile.ANON; 1507 } 1508 if (DEBUG_COMPACTION) { 1509 Slog.d(TAG_AM, 1510 "Final compaction profile "+ profile +" due to file compact disabled"); 1511 } 1512 } 1513 1514 return profile; 1515 } 1516 isProcessFrozen(int pid)1517 boolean isProcessFrozen(int pid) { 1518 synchronized (mProcLock) { 1519 return mFrozenProcesses.contains(pid); 1520 } 1521 } 1522 1523 private final class MemCompactionHandler extends Handler { MemCompactionHandler()1524 private MemCompactionHandler() { 1525 super(mCachedAppOptimizerThread.getLooper()); 1526 } 1527 shouldOomAdjThrottleCompaction(ProcessRecord proc)1528 private boolean shouldOomAdjThrottleCompaction(ProcessRecord proc) { 1529 final String name = proc.processName; 1530 1531 // don't compact if the process has returned to perceptible 1532 // and this is only a cached/home/prev compaction 1533 if (proc.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ) { 1534 if (DEBUG_COMPACTION) { 1535 Slog.d(TAG_AM, 1536 "Skipping compaction as process " + name + " is " 1537 + "now perceptible."); 1538 } 1539 return true; 1540 } 1541 1542 return false; 1543 } 1544 shouldTimeThrottleCompaction(ProcessRecord proc, long start, CompactProfile pendingProfile, CompactSource source)1545 private boolean shouldTimeThrottleCompaction(ProcessRecord proc, long start, 1546 CompactProfile pendingProfile, CompactSource source) { 1547 final ProcessCachedOptimizerRecord opt = proc.mOptRecord; 1548 final String name = proc.processName; 1549 1550 CompactProfile lastCompactProfile = opt.getLastCompactProfile(); 1551 long lastCompactTime = opt.getLastCompactTime(); 1552 1553 // basic throttling 1554 // use the Phenotype flag knobs to determine whether current/previous 1555 // compaction combo should be throttled or not. 1556 // Note that we explicitly don't take mPhenotypeFlagLock here as the flags 1557 // should very seldom change, and taking the risk of using the wrong action is 1558 // preferable to taking the lock for every single compaction action. 1559 if (lastCompactTime != 0) { 1560 if (source == CompactSource.APP) { 1561 if (pendingProfile == CompactProfile.SOME) { 1562 if ((lastCompactProfile == CompactProfile.SOME 1563 && (start - lastCompactTime < mCompactThrottleSomeSome)) 1564 || (lastCompactProfile == CompactProfile.FULL 1565 && (start - lastCompactTime < mCompactThrottleSomeFull))) { 1566 if (DEBUG_COMPACTION) { 1567 Slog.d(TAG_AM, 1568 "Skipping some compaction for " + name 1569 + ": too soon. throttle=" + mCompactThrottleSomeSome 1570 + "/" + mCompactThrottleSomeFull 1571 + " last=" + (start - lastCompactTime) + "ms ago"); 1572 } 1573 return true; 1574 } 1575 } else if (pendingProfile == CompactProfile.FULL) { 1576 if ((lastCompactProfile == CompactProfile.SOME 1577 && (start - lastCompactTime < mCompactThrottleFullSome)) 1578 || (lastCompactProfile == CompactProfile.FULL 1579 && (start - lastCompactTime < mCompactThrottleFullFull))) { 1580 if (DEBUG_COMPACTION) { 1581 Slog.d(TAG_AM, 1582 "Skipping full compaction for " + name 1583 + ": too soon. throttle=" + mCompactThrottleFullSome 1584 + "/" + mCompactThrottleFullFull 1585 + " last=" + (start - lastCompactTime) + "ms ago"); 1586 } 1587 return true; 1588 } 1589 } 1590 } 1591 } 1592 1593 return false; 1594 } 1595 shouldThrottleMiscCompaction(ProcessRecord proc, int procState)1596 private boolean shouldThrottleMiscCompaction(ProcessRecord proc, int procState) { 1597 if (mProcStateThrottle.contains(procState)) { 1598 if (DEBUG_COMPACTION) { 1599 final String name = proc.processName; 1600 Slog.d(TAG_AM, 1601 "Skipping full compaction for process " + name + "; proc state is " 1602 + procState); 1603 } 1604 return true; 1605 } 1606 1607 return false; 1608 } 1609 shouldRssThrottleCompaction( CompactProfile profile, int pid, String name, long[] rssBefore)1610 private boolean shouldRssThrottleCompaction( 1611 CompactProfile profile, int pid, String name, long[] rssBefore) { 1612 long anonRssBefore = rssBefore[RSS_ANON_INDEX]; 1613 SingleCompactionStats lastCompactionStats = 1614 mCompactStatsManager.getLastCompactionStats(pid); 1615 1616 if (rssBefore[RSS_TOTAL_INDEX] == 0 && rssBefore[RSS_FILE_INDEX] == 0 1617 && rssBefore[RSS_ANON_INDEX] == 0 && rssBefore[RSS_SWAP_INDEX] == 0) { 1618 if (DEBUG_COMPACTION) { 1619 Slog.d(TAG_AM, 1620 "Skipping compaction for" 1621 + "process " + pid + " with no memory usage. Dead?"); 1622 } 1623 return true; 1624 } 1625 1626 if (profile == CompactProfile.FULL) { 1627 if (mFullAnonRssThrottleKb > 0L && anonRssBefore < mFullAnonRssThrottleKb) { 1628 if (DEBUG_COMPACTION) { 1629 Slog.d(TAG_AM, 1630 "Skipping full compaction for process " + name 1631 + "; anon RSS is too small: " + anonRssBefore + "KB."); 1632 } 1633 return true; 1634 } 1635 1636 if (lastCompactionStats != null && mFullDeltaRssThrottleKb > 0L) { 1637 long[] lastRss = lastCompactionStats.getRssAfterCompaction(); 1638 long absDelta = Math.abs(rssBefore[RSS_FILE_INDEX] - lastRss[RSS_FILE_INDEX]) 1639 + Math.abs(rssBefore[RSS_ANON_INDEX] - lastRss[RSS_ANON_INDEX]) 1640 + Math.abs(rssBefore[RSS_SWAP_INDEX] - lastRss[RSS_SWAP_INDEX]); 1641 if (absDelta <= mFullDeltaRssThrottleKb) { 1642 if (DEBUG_COMPACTION) { 1643 Slog.d(TAG_AM, 1644 "Skipping full compaction for process " + name 1645 + "; abs delta is too small: " + absDelta + "KB."); 1646 } 1647 return true; 1648 } 1649 } 1650 } 1651 1652 return false; 1653 } 1654 1655 @Override handleMessage(Message msg)1656 public void handleMessage(Message msg) { 1657 switch (msg.what) { 1658 case COMPACT_PROCESS_MSG: { 1659 long start = SystemClock.uptimeMillis(); 1660 ProcessRecord proc; 1661 final ProcessCachedOptimizerRecord opt; 1662 int pid; 1663 final String name; 1664 CompactProfile lastCompactProfile; 1665 long lastCompactTime; 1666 int newOomAdj = msg.arg1; 1667 int procState = msg.arg2; 1668 boolean forceCompaction; 1669 CompactSource compactSource; 1670 CompactProfile requestedProfile; 1671 int oomAdjReason; 1672 synchronized (mProcLock) { 1673 if (mPendingCompactionProcesses.isEmpty()) { 1674 if (DEBUG_COMPACTION) { 1675 Slog.d(TAG_AM, "No processes pending compaction, bail out"); 1676 } 1677 return; 1678 } 1679 proc = mPendingCompactionProcesses.remove(0); 1680 opt = proc.mOptRecord; 1681 forceCompaction = opt.isForceCompact(); 1682 opt.setForceCompact(false); // since this is a one-shot operation 1683 pid = proc.getPid(); 1684 name = proc.processName; 1685 opt.setHasPendingCompact(false); 1686 compactSource = opt.getReqCompactSource(); 1687 requestedProfile = opt.getReqCompactProfile(); 1688 lastCompactProfile = opt.getLastCompactProfile(); 1689 lastCompactTime = opt.getLastCompactTime(); 1690 oomAdjReason = opt.getLastOomAdjChangeReason(); 1691 } 1692 1693 long[] rssBefore; 1694 if (pid == 0) { 1695 // not a real process, either one being launched or one being killed 1696 if (DEBUG_COMPACTION) { 1697 Slog.d(TAG_AM, "Compaction failed, pid is 0"); 1698 } 1699 mCompactStatsManager.logCompactionThrottled( 1700 CompactionStatsManager.COMPACT_THROTTLE_REASON_NO_PID, 1701 compactSource, name); 1702 return; 1703 } 1704 1705 if (!forceCompaction) { 1706 if (shouldOomAdjThrottleCompaction(proc)) { 1707 mCompactStatsManager.logCompactionThrottled( 1708 CompactionStatsManager.COMPACT_THROTTLE_REASON_OOM_ADJ, 1709 compactSource, name); 1710 return; 1711 } 1712 if (shouldTimeThrottleCompaction( 1713 proc, start, requestedProfile, compactSource)) { 1714 mCompactStatsManager.logCompactionThrottled( 1715 CompactionStatsManager.COMPACT_THROTTLE_REASON_TIME_TOO_SOON, 1716 compactSource, name); 1717 return; 1718 } 1719 if (shouldThrottleMiscCompaction(proc, procState)) { 1720 mCompactStatsManager.logCompactionThrottled( 1721 CompactionStatsManager.COMPACT_THROTTLE_REASON_PROC_STATE, 1722 compactSource, name); 1723 return; 1724 } 1725 rssBefore = mProcessDependencies.getRss(pid); 1726 if (shouldRssThrottleCompaction(requestedProfile, pid, name, rssBefore)) { 1727 mCompactStatsManager.logCompactionThrottled( 1728 CompactionStatsManager.COMPACT_THROTTLE_REASON_DELTA_RSS, 1729 compactSource, name); 1730 return; 1731 } 1732 } else { 1733 rssBefore = mProcessDependencies.getRss(pid); 1734 if (DEBUG_COMPACTION) { 1735 Slog.d(TAG_AM, "Forcing compaction for " + name); 1736 } 1737 } 1738 1739 CompactProfile resolvedProfile = 1740 resolveCompactionProfile(requestedProfile); 1741 if (resolvedProfile == CompactProfile.NONE) { 1742 // No point on issuing compaction call as we don't want to compact. 1743 if (DEBUG_COMPACTION) { 1744 Slog.d(TAG_AM, "Resolved no compaction for "+ name + 1745 " requested profile="+requestedProfile); 1746 } 1747 return; 1748 } 1749 1750 try { 1751 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 1752 "Compact " + resolvedProfile.name() + ": " + name 1753 + " lastOomAdjReason: " + oomAdjReason 1754 + " source: " + compactSource.name()); 1755 long zramUsedKbBefore = getUsedZramMemory(); 1756 long startCpuTime = threadCpuTimeNs(); 1757 mProcessDependencies.performCompaction(resolvedProfile, pid); 1758 long endCpuTime = threadCpuTimeNs(); 1759 long[] rssAfter = mProcessDependencies.getRss(pid); 1760 long end = SystemClock.uptimeMillis(); 1761 long time = end - start; 1762 long deltaCpuTimeNanos = endCpuTime - startCpuTime; 1763 long zramUsedKbAfter = getUsedZramMemory(); 1764 long deltaTotalRss = rssAfter[RSS_TOTAL_INDEX] - rssBefore[RSS_TOTAL_INDEX]; 1765 long deltaFileRss = rssAfter[RSS_FILE_INDEX] - rssBefore[RSS_FILE_INDEX]; 1766 long deltaAnonRss = rssAfter[RSS_ANON_INDEX] - rssBefore[RSS_ANON_INDEX]; 1767 long deltaSwapRss = rssAfter[RSS_SWAP_INDEX] - rssBefore[RSS_SWAP_INDEX]; 1768 switch (opt.getReqCompactProfile()) { 1769 case SOME: 1770 mCompactStatsManager.logSomeCompactionPerformed(compactSource, 1771 name); 1772 break; 1773 case FULL: 1774 long anonRssSavings = -deltaAnonRss; 1775 long zramConsumed = zramUsedKbAfter - zramUsedKbBefore; 1776 long memFreed = anonRssSavings - zramConsumed; 1777 long totalCpuTimeMillis = deltaCpuTimeNanos / 1000000; 1778 long origAnonRss = rssBefore[RSS_ANON_INDEX]; 1779 mCompactStatsManager.logFullCompactionPerformed(compactSource, name, 1780 anonRssSavings, zramConsumed, memFreed, origAnonRss, 1781 totalCpuTimeMillis, rssAfter, procState, newOomAdj, 1782 oomAdjReason, proc.uid, pid, !forceCompaction); 1783 break; 1784 default: 1785 // We likely missed adding this category, it needs to be added 1786 // if we end up here. In the meantime, gracefully fallback to 1787 // attribute to app. 1788 Slog.wtf(TAG_AM, "Compaction: Unknown requested action"); 1789 return; 1790 } 1791 EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, 1792 resolvedProfile.name(), rssBefore[RSS_TOTAL_INDEX], 1793 rssBefore[RSS_FILE_INDEX], rssBefore[RSS_ANON_INDEX], 1794 rssBefore[RSS_SWAP_INDEX], deltaTotalRss, deltaFileRss, 1795 deltaAnonRss, deltaSwapRss, time, lastCompactProfile.name(), 1796 lastCompactTime, newOomAdj, procState, zramUsedKbBefore, 1797 zramUsedKbBefore - zramUsedKbAfter); 1798 synchronized (mProcLock) { 1799 opt.setLastCompactTime(end); 1800 opt.setLastCompactProfile(requestedProfile); 1801 } 1802 } catch (Exception e) { 1803 // nothing to do, presumably the process died 1804 Slog.d(TAG_AM, 1805 "Exception occurred while compacting pid: " + name 1806 + ". Exception:" + e.getMessage()); 1807 } finally { 1808 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1809 } 1810 break; 1811 } 1812 case COMPACT_SYSTEM_MSG: { 1813 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem"); 1814 long memFreedBefore = getMemoryFreedCompaction(); 1815 compactSystem(); 1816 long memFreedAfter = getMemoryFreedCompaction(); 1817 long memFreed = memFreedAfter - memFreedBefore; 1818 mCompactStatsManager.logSystemCompactionPerformed(memFreed); 1819 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1820 break; 1821 } 1822 case COMPACT_NATIVE_MSG: { 1823 int pid = msg.arg1; 1824 CompactProfile compactProfile = CompactProfile.values()[msg.arg2]; 1825 Slog.d(TAG_AM, 1826 "Performing native compaction for pid=" + pid 1827 + " type=" + compactProfile.name()); 1828 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactNative"); 1829 try { 1830 mProcessDependencies.performCompaction(compactProfile, pid); 1831 } catch (Exception e) { 1832 Slog.d(TAG_AM, "Failed compacting native pid= " + pid); 1833 } 1834 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1835 break; 1836 } 1837 } 1838 } 1839 } 1840 reportOneUidFrozenStateChanged(int uid, boolean frozen)1841 private void reportOneUidFrozenStateChanged(int uid, boolean frozen) { 1842 final int[] uids = new int[1]; 1843 final int[] frozenStates = new int[1]; 1844 1845 uids[0] = uid; 1846 frozenStates[0] = frozen ? UID_FROZEN_STATE_FROZEN : UID_FROZEN_STATE_UNFROZEN; 1847 1848 if (DEBUG_FREEZER) { 1849 Slog.d(TAG_AM, "reportOneUidFrozenStateChanged uid " + uid + " frozen = " + frozen); 1850 } 1851 1852 mAm.reportUidFrozenStateChanged(uids, frozenStates); 1853 } 1854 postUidFrozenMessage(int uid, boolean frozen)1855 private void postUidFrozenMessage(int uid, boolean frozen) { 1856 final Integer uidObj = Integer.valueOf(uid); 1857 mFreezeHandler.removeEqualMessages(UID_FROZEN_STATE_CHANGED_MSG, uidObj); 1858 1859 final int op = frozen ? 1 : 0; 1860 mFreezeHandler.sendMessage(mFreezeHandler.obtainMessage(UID_FROZEN_STATE_CHANGED_MSG, op, 1861 0, uidObj)); 1862 } 1863 1864 @GuardedBy("mAm") reportProcessFreezableChangedLocked(ProcessRecord app)1865 private void reportProcessFreezableChangedLocked(ProcessRecord app) { 1866 mAm.onProcessFreezableChangedLocked(app); 1867 } 1868 1869 private final class FreezeHandler extends Handler implements 1870 ProcLocksReader.ProcLocksReaderCallback { FreezeHandler()1871 private FreezeHandler() { 1872 super(mCachedAppOptimizerThread.getLooper()); 1873 } 1874 1875 @Override handleMessage(Message msg)1876 public void handleMessage(Message msg) { 1877 switch (msg.what) { 1878 case SET_FROZEN_PROCESS_MSG: { 1879 ProcessRecord proc = (ProcessRecord) msg.obj; 1880 synchronized (mAm) { 1881 if (!proc.mOptRecord.isPendingFreeze()) { 1882 return; 1883 } 1884 freezeProcess(proc); 1885 } 1886 if (proc.mOptRecord.isFrozen()) { 1887 onProcessFrozen(proc); 1888 removeMessages(DEADLOCK_WATCHDOG_MSG); 1889 sendEmptyMessageDelayed(DEADLOCK_WATCHDOG_MSG, FREEZE_DEADLOCK_TIMEOUT_MS); 1890 } else { 1891 onProcessFrozenCancelled(proc); 1892 } 1893 } break; 1894 case REPORT_UNFREEZE_MSG: { 1895 int pid = msg.arg1; 1896 int frozenDuration = msg.arg2; 1897 Pair<ProcessRecord, Integer> obj = (Pair<ProcessRecord, Integer>) msg.obj; 1898 ProcessRecord app = obj.first; 1899 String processName = app.processName; 1900 int reason = obj.second; 1901 1902 reportUnfreeze(app, pid, frozenDuration, processName, reason); 1903 } break; 1904 case UID_FROZEN_STATE_CHANGED_MSG: { 1905 final boolean frozen = (msg.arg1 == 1); 1906 final int uid = (int) msg.obj; 1907 reportOneUidFrozenStateChanged(uid, frozen); 1908 } break; 1909 case DEADLOCK_WATCHDOG_MSG: { 1910 try { 1911 // post-check to prevent deadlock 1912 if (DEBUG_FREEZER) { 1913 Slog.d(TAG_AM, "Freezer deadlock watchdog"); 1914 } 1915 mProcLocksReader.handleBlockingFileLocks(this); 1916 } catch (IOException e) { 1917 Slog.w(TAG_AM, "Unable to check file locks"); 1918 } 1919 } break; 1920 case BINDER_ERROR_MSG: { 1921 IntArray pids = new IntArray(); 1922 // Copy the frozen pids to a local array to release mProcLock ASAP 1923 synchronized (mProcLock) { 1924 int size = mFrozenProcesses.size(); 1925 for (int i = 0; i < size; i++) { 1926 pids.add(mFrozenProcesses.keyAt(i)); 1927 } 1928 } 1929 1930 // Check binder errors to frozen processes 1931 // Freezer lock is not required as we don't perform (un)freeze operations here 1932 binderErrorInternal(pids); 1933 } break; 1934 default: 1935 return; 1936 } 1937 } 1938 1939 @GuardedBy({"mAm", "mProcLock"}) handleBinderFreezerFailure(final ProcessRecord proc, final String reason)1940 private void handleBinderFreezerFailure(final ProcessRecord proc, final String reason) { 1941 if (!mFreezerBinderEnabled) { 1942 // Just reschedule indefinitely. 1943 unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS); 1944 freezeAppAsyncLSP(proc); 1945 return; 1946 } 1947 /* 1948 * This handles the case where a process couldn't be frozen due to pending binder 1949 * transactions. In order to prevent apps from avoiding the freezer by spamming binder 1950 * transactions, there is an exponential decrease in freezer retry times plus a random 1951 * offset per attempt to avoid phase issues. Once the last-attempted timeout is below a 1952 * threshold, we assume that the app is spamming binder calls and can never be frozen, 1953 * and we will then crash the app. 1954 */ 1955 if (proc.mOptRecord.getLastUsedTimeout() <= mFreezerBinderThreshold) { 1956 // We've given the app plenty of chances, assume broken. Time to die. 1957 Slog.d(TAG_AM, "Kill app due to repeated failure to freeze binder: " 1958 + proc.getPid() + " " + proc.processName); 1959 mAm.mHandler.post(() -> { 1960 synchronized (mAm) { 1961 // Crash regardless of procstate in case the app has found another way 1962 // to abuse oom_adj 1963 if (proc.getThread() == null) { 1964 return; 1965 } 1966 proc.killLocked("excessive binder traffic during cached", 1967 ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE, 1968 ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU, 1969 true); 1970 } 1971 }); 1972 return; 1973 } 1974 1975 long timeout = proc.mOptRecord.getLastUsedTimeout() / mFreezerBinderDivisor; 1976 // range is [-mFreezerBinderOffset, +mFreezerBinderOffset] 1977 int offset = mRandom.nextInt(mFreezerBinderOffset * 2) - mFreezerBinderOffset; 1978 timeout = Math.max(timeout + offset, mFreezerBinderThreshold); 1979 1980 Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid() 1981 + " " + proc.processName + " (" + reason + "), timeout=" + timeout); 1982 Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_FREEZER_TRACK, 1983 "Reschedule freeze " + proc.processName + ":" + proc.getPid() 1984 + " timeout=" + timeout + ", reason=" + reason); 1985 1986 unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS); 1987 freezeAppAsyncLSP(proc, timeout); 1988 } 1989 1990 /** 1991 * Freeze a process. 1992 * @param proc process to be frozen 1993 */ 1994 @GuardedBy({"mAm"}) freezeProcess(final ProcessRecord proc)1995 private void freezeProcess(final ProcessRecord proc) { 1996 int pid = proc.getPid(); // Unlocked intentionally 1997 final String name = proc.processName; 1998 final long unfrozenDuration; 1999 final boolean frozen; 2000 final ProcessCachedOptimizerRecord opt = proc.mOptRecord; 2001 2002 synchronized (mProcLock) { 2003 // someone has canceled this freeze 2004 if (!opt.isPendingFreeze()) { 2005 return; 2006 } 2007 opt.setPendingFreeze(false); 2008 pid = proc.getPid(); 2009 2010 if (mFreezerOverride) { 2011 opt.setFreezerOverride(true); 2012 Slog.d(TAG_AM, "Skipping freeze for process " + pid 2013 + " " + name + " curAdj = " + proc.mState.getCurAdj() 2014 + "(override)"); 2015 return; 2016 } 2017 2018 if (opt.shouldNotFreeze()) { 2019 if (DEBUG_FREEZER) { 2020 Slog.d(TAG_AM, "Skipping freeze because process is marked " 2021 + "should not be frozen"); 2022 } 2023 reportProcessFreezableChangedLocked(proc); 2024 return; 2025 } 2026 2027 if (pid == 0 || opt.isFrozen()) { 2028 // Already frozen or not a real process, either one being 2029 // launched or one being killed 2030 if (DEBUG_FREEZER) { 2031 Slog.d(TAG_AM, "Skipping freeze for process " + pid 2032 + " " + name + ". Already frozen or not a real process"); 2033 } 2034 return; 2035 } 2036 2037 Slog.d(TAG_AM, "freezing " + pid + " " + name); 2038 2039 // Freeze binder interface before the process, to flush any 2040 // transactions that might be pending. 2041 try { 2042 if (mFreezer.freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) { 2043 handleBinderFreezerFailure(proc, "outstanding txns"); 2044 return; 2045 } 2046 } catch (RuntimeException e) { 2047 Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); 2048 mFreezeHandler.post(() -> { 2049 synchronized (mAm) { 2050 proc.killLocked("Unable to freeze binder interface", 2051 ApplicationExitInfo.REASON_FREEZER, 2052 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true); 2053 } 2054 }); 2055 } 2056 2057 long unfreezeTime = opt.getFreezeUnfreezeTime(); 2058 2059 try { 2060 traceAppFreeze(proc.processName, pid, -1); 2061 mFreezer.setProcessFrozen(pid, proc.uid, true); 2062 opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis()); 2063 opt.setFrozen(true); 2064 opt.setHasCollectedFrozenPSS(false); 2065 mFrozenProcesses.put(pid, proc); 2066 } catch (Exception e) { 2067 Slog.w(TAG_AM, "Unable to freeze " + pid + " " + name); 2068 } 2069 2070 unfrozenDuration = opt.getFreezeUnfreezeTime() - unfreezeTime; 2071 frozen = opt.isFrozen(); 2072 2073 final UidRecord uidRec = proc.getUidRecord(); 2074 if (frozen && uidRec != null && uidRec.areAllProcessesFrozen()) { 2075 uidRec.setFrozen(true); 2076 2077 postUidFrozenMessage(uidRec.getUid(), true); 2078 } 2079 } 2080 2081 if (!frozen) { 2082 return; 2083 } 2084 2085 EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name); 2086 2087 // See above for why we're not taking mPhenotypeFlagLock here 2088 if (mRandom.nextFloat() < mFreezerStatsdSampleRate) { 2089 FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED, 2090 FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__FREEZE_APP, 2091 pid, 2092 name, 2093 unfrozenDuration, 2094 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__NONE, 2095 UNFREEZE_REASON_NONE); 2096 } 2097 2098 try { 2099 // post-check to prevent races 2100 int freezeInfo = mFreezer.getBinderFreezeInfo(pid); 2101 2102 if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) { 2103 synchronized (mProcLock) { 2104 handleBinderFreezerFailure(proc, "new pending txns"); 2105 } 2106 return; 2107 } 2108 } catch (RuntimeException e) { 2109 Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); 2110 mFreezeHandler.post(() -> { 2111 synchronized (mAm) { 2112 proc.killLocked("Unable to freeze binder interface", 2113 ApplicationExitInfo.REASON_FREEZER, 2114 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true); 2115 } 2116 }); 2117 } 2118 opt.dispatchFrozenEvent(); 2119 } 2120 reportUnfreeze(ProcessRecord app, int pid, int frozenDuration, String processName, @UnfreezeReason int reason)2121 private void reportUnfreeze(ProcessRecord app, int pid, int frozenDuration, 2122 String processName, @UnfreezeReason int reason) { 2123 2124 EventLog.writeEvent(EventLogTags.AM_UNFREEZE, pid, processName, reason); 2125 app.onProcessUnfrozen(); 2126 2127 // See above for why we're not taking mPhenotypeFlagLock here 2128 if (mRandom.nextFloat() < mFreezerStatsdSampleRate) { 2129 FrameworkStatsLog.write( 2130 FrameworkStatsLog.APP_FREEZE_CHANGED, 2131 FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__UNFREEZE_APP, 2132 pid, 2133 processName, 2134 frozenDuration, 2135 FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__NONE, // deprecated 2136 reason); 2137 } 2138 } 2139 2140 @GuardedBy({"mAm"}) 2141 @Override onBlockingFileLock(IntArray pids)2142 public void onBlockingFileLock(IntArray pids) { 2143 if (DEBUG_FREEZER) { 2144 Slog.d(TAG_AM, "Blocking file lock found: " + pids); 2145 } 2146 synchronized (mAm) { 2147 synchronized (mProcLock) { 2148 int pid = pids.get(0); 2149 ProcessRecord app = mFrozenProcesses.get(pid); 2150 ProcessRecord pr; 2151 if (app != null) { 2152 for (int i = 1; i < pids.size(); i++) { 2153 int blocked = pids.get(i); 2154 synchronized (mAm.mPidsSelfLocked) { 2155 pr = mAm.mPidsSelfLocked.get(blocked); 2156 } 2157 if (pr != null && pr.mState.getCurAdj() 2158 < mAm.mConstants.FREEZER_CUTOFF_ADJ) { 2159 Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks " 2160 + pr.processName + " (" + blocked + ")"); 2161 // Found at least one blocked non-cached process 2162 unfreezeAppLSP(app, UNFREEZE_REASON_FILE_LOCKS); 2163 break; 2164 } 2165 } 2166 } 2167 } 2168 } 2169 } 2170 } 2171 2172 /** 2173 * Default implementation for ProcessDependencies, public vor visibility to OomAdjuster class. 2174 */ 2175 private static final class DefaultProcessDependencies implements ProcessDependencies { 2176 public static volatile int mPidCompacting = -1; 2177 2178 // Get memory RSS from process. 2179 @Override getRss(int pid)2180 public long[] getRss(int pid) { 2181 return Process.getRss(pid); 2182 } 2183 2184 // Compact process. 2185 @Override performCompaction(CompactProfile profile, int pid)2186 public void performCompaction(CompactProfile profile, int pid) throws IOException { 2187 mPidCompacting = pid; 2188 if (profile == CompactProfile.FULL) { 2189 compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG); 2190 } else if (profile == CompactProfile.SOME) { 2191 compactProcess(pid, COMPACT_ACTION_FILE_FLAG); 2192 } else if (profile == CompactProfile.ANON) { 2193 compactProcess(pid, COMPACT_ACTION_ANON_FLAG); 2194 } 2195 mPidCompacting = -1; 2196 } 2197 } 2198 getUnfreezeReasonCodeFromOomAdjReason(@omAdjReason int oomAdjReason)2199 static int getUnfreezeReasonCodeFromOomAdjReason(@OomAdjReason int oomAdjReason) { 2200 switch (oomAdjReason) { 2201 case OOM_ADJ_REASON_ACTIVITY: 2202 return UNFREEZE_REASON_ACTIVITY; 2203 case OOM_ADJ_REASON_FINISH_RECEIVER: 2204 return UNFREEZE_REASON_FINISH_RECEIVER; 2205 case OOM_ADJ_REASON_START_RECEIVER: 2206 return UNFREEZE_REASON_START_RECEIVER; 2207 case OOM_ADJ_REASON_BIND_SERVICE: 2208 return UNFREEZE_REASON_BIND_SERVICE; 2209 case OOM_ADJ_REASON_UNBIND_SERVICE: 2210 return UNFREEZE_REASON_UNBIND_SERVICE; 2211 case OOM_ADJ_REASON_START_SERVICE: 2212 return UNFREEZE_REASON_START_SERVICE; 2213 case OOM_ADJ_REASON_GET_PROVIDER: 2214 return UNFREEZE_REASON_GET_PROVIDER; 2215 case OOM_ADJ_REASON_REMOVE_PROVIDER: 2216 return UNFREEZE_REASON_REMOVE_PROVIDER; 2217 case OOM_ADJ_REASON_UI_VISIBILITY: 2218 return UNFREEZE_REASON_UI_VISIBILITY; 2219 case OOM_ADJ_REASON_ALLOWLIST: 2220 return UNFREEZE_REASON_ALLOWLIST; 2221 case OOM_ADJ_REASON_PROCESS_BEGIN: 2222 return UNFREEZE_REASON_PROCESS_BEGIN; 2223 case OOM_ADJ_REASON_PROCESS_END: 2224 return UNFREEZE_REASON_PROCESS_END; 2225 case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT: 2226 return UNFREEZE_REASON_SHORT_FGS_TIMEOUT; 2227 case OOM_ADJ_REASON_SYSTEM_INIT: 2228 return UNFREEZE_REASON_SYSTEM_INIT; 2229 case OOM_ADJ_REASON_BACKUP: 2230 return UNFREEZE_REASON_BACKUP; 2231 case OOM_ADJ_REASON_SHELL: 2232 return UNFREEZE_REASON_SHELL; 2233 case OOM_ADJ_REASON_REMOVE_TASK: 2234 return UNFREEZE_REASON_REMOVE_TASK; 2235 case OOM_ADJ_REASON_UID_IDLE: 2236 return UNFREEZE_REASON_UID_IDLE; 2237 case OOM_ADJ_REASON_STOP_SERVICE: 2238 return UNFREEZE_REASON_STOP_SERVICE; 2239 case OOM_ADJ_REASON_EXECUTING_SERVICE: 2240 return UNFREEZE_REASON_EXECUTING_SERVICE; 2241 case OOM_ADJ_REASON_RESTRICTION_CHANGE: 2242 return UNFREEZE_REASON_RESTRICTION_CHANGE; 2243 case OOM_ADJ_REASON_COMPONENT_DISABLED: 2244 return UNFREEZE_REASON_COMPONENT_DISABLED; 2245 case OOM_ADJ_REASON_FOLLOW_UP: 2246 return UNFREEZE_REASON_OOM_ADJ_FOLLOW_UP; 2247 case OOM_ADJ_REASON_RECONFIGURATION: 2248 return UNFREEZE_REASON_OOM_ADJ_RECONFIGURATION; 2249 default: 2250 return UNFREEZE_REASON_NONE; 2251 } 2252 } 2253 2254 /** 2255 * Kill a frozen process with a specified reason 2256 */ killProcess(int pid, String reason, @Reason int reasonCode, @SubReason int subReason)2257 public void killProcess(int pid, String reason, @Reason int reasonCode, 2258 @SubReason int subReason) { 2259 mAm.mHandler.post(() -> { 2260 synchronized (mAm) { 2261 synchronized (mProcLock) { 2262 ProcessRecord proc = mFrozenProcesses.get(pid); 2263 // The process might have been killed or unfrozen by others 2264 if (proc != null && proc.getThread() != null && !proc.isKilledByAm()) { 2265 proc.killLocked(reason, reasonCode, subReason, true); 2266 } 2267 } 2268 } 2269 }); 2270 } 2271 2272 /** 2273 * Freeze or unfreeze a process. This should only be used for testing. 2274 */ 2275 @VisibleForTesting forceFreezeForTest(ProcessRecord proc, boolean freeze)2276 void forceFreezeForTest(ProcessRecord proc, boolean freeze) { 2277 synchronized (mAm) { 2278 synchronized (mProcLock) { 2279 if (freeze) { 2280 forceFreezeAppAsyncLSP(proc); 2281 } else { 2282 unfreezeAppLSP(proc, UNFREEZE_REASON_NONE, true); 2283 } 2284 } 2285 } 2286 } 2287 2288 /** 2289 * Sending binder transactions to frozen apps most likely indicates there's a bug. Log it and 2290 * kill the frozen apps if they 1) receive sync binder transactions while frozen, or 2) miss 2291 * async binder transactions due to kernel binder buffer running out. 2292 * 2293 * @param debugPid The binder transaction sender 2294 * @param app The ProcessRecord of the sender 2295 * @param code The binder transaction code 2296 * @param flags The binder transaction flags 2297 * @param err The binder transaction error 2298 */ binderError(int debugPid, ProcessRecord app, int code, int flags, int err)2299 public void binderError(int debugPid, ProcessRecord app, int code, int flags, int err) { 2300 Slog.w(TAG_AM, "pid " + debugPid + " " + (app == null ? "null" : app.processName) 2301 + " sent binder code " + code + " with flags " + flags 2302 + " to frozen apps and got error " + err); 2303 2304 // Do nothing if the binder error callback is not enabled. 2305 // That means the frozen apps in a wrong state will be killed when they are unfrozen later. 2306 if (!mUseFreezer || !mFreezerBinderCallbackEnabled) { 2307 return; 2308 } 2309 2310 final long now = SystemClock.uptimeMillis(); 2311 if (now < mFreezerBinderCallbackLast + mFreezerBinderCallbackThrottle) { 2312 Slog.d(TAG_AM, "Too many transaction errors, throttling freezer binder callback."); 2313 return; 2314 } 2315 mFreezerBinderCallbackLast = now; 2316 2317 // Check all frozen processes in Freezer handler 2318 mFreezeHandler.sendEmptyMessage(BINDER_ERROR_MSG); 2319 } 2320 binderErrorInternal(IntArray pids)2321 private void binderErrorInternal(IntArray pids) { 2322 // PIDs that run out of async binder buffer when being frozen 2323 ArraySet<Integer> pidsAsync = (mFreezerBinderAsyncThreshold < 0) ? null : new ArraySet<>(); 2324 2325 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "binderErrorSync"); 2326 for (int i = 0; i < pids.size(); i++) { 2327 int current = pids.get(i); 2328 try { 2329 int freezeInfo = mFreezer.getBinderFreezeInfo(current); 2330 2331 if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) { 2332 killProcess(current, "Sync transaction while frozen", 2333 ApplicationExitInfo.REASON_FREEZER, 2334 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_TRANSACTION); 2335 2336 // No need to check async transactions in this case 2337 continue; 2338 } 2339 2340 if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0) { 2341 if (pidsAsync != null) { 2342 pidsAsync.add(current); 2343 } 2344 if (DEBUG_FREEZER) { 2345 Slog.w(TAG_AM, "pid " + current 2346 + " received async transactions while frozen"); 2347 } 2348 } 2349 } catch (Exception e) { 2350 // The process has died. No need to kill it again. 2351 Slog.w(TAG_AM, "Unable to query binder frozen stats for pid " + current); 2352 } 2353 } 2354 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 2355 2356 // TODO: when kernel binder driver supports, poll the binder status directly. 2357 // Binderfs stats, like other debugfs files, is not a reliable interface. But it's the 2358 // only true source for now. The following code checks all frozen PIDs. If any of them 2359 // is running out of async binder buffer, kill it. Otherwise it will be killed at a 2360 // later time when AMS unfreezes it, which causes race issues. 2361 if (pidsAsync == null || pidsAsync.size() == 0) { 2362 return; 2363 } 2364 2365 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "binderErrorAsync"); 2366 new BinderfsStatsReader().handleFreeAsyncSpace( 2367 // Check if the frozen process has pending async calls 2368 pidsAsync::contains, 2369 2370 // Kill the current process if it's running out of async binder space 2371 (current, free) -> { 2372 if (free < mFreezerBinderAsyncThreshold) { 2373 Slog.w(TAG_AM, "pid " + current 2374 + " has " + free + " free async space, killing"); 2375 killProcess(current, "Async binder space running out while frozen", 2376 ApplicationExitInfo.REASON_FREEZER, 2377 ApplicationExitInfo.SUBREASON_FREEZER_BINDER_ASYNC_FULL); 2378 } 2379 }, 2380 2381 // Log the error if binderfs stats can't be accesses or correctly parsed 2382 exception -> Slog.e(TAG_AM, "Unable to parse binderfs stats")); 2383 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 2384 } 2385 2386 /** 2387 * Register a callback to notify when a process's frozen state changes. 2388 */ addFrozenProcessListener(ProcessRecord app, Executor executor, FrozenProcessListener listener)2389 public void addFrozenProcessListener(ProcessRecord app, Executor executor, 2390 FrozenProcessListener listener) { 2391 app.mOptRecord.addFrozenProcessListener(executor, listener); 2392 } 2393 } 2394