Android 11 (API level 30) or higher supports the cached apps freezer. This feature stops execution for cached processes and reduces resource usage by misbehaving apps that might attempt to operate while cached.
The cached apps freezer keeps apps in RAM while keeping them off the CPU. If Android determines that an app shouldn't be doing work but might be needed in the future, it freezes the app process rather than terminating it. This prevents a cold start when the app is needed again.
Android freezes cached apps by migrating their processes into a frozen cgroup. This reduces active and idle CPU consumption in the presence of active cached apps. You can enable the app freezer using a system configuration flag or a developer option.
In Android 14 (API level 34) and higher, the cached apps freezer includes the following robust behaviors:
- App processes in the cached state are frozen 10 seconds after entering the cached state.
- The system immediately unfreezes a frozen app process during a lifecycle event. These events include receiving an intent, starting a job service, or the user resuming an activity.
ActivityManagerService manages all app processes and makes app lifecycle
decisions. CachedAppOptimizer is responsible for freezing the app process.
When an app process is frozen, all of its threads are suspended and can't
perform CPU work until unfrozen. As a result, the app can't perform garbage
collection (GC) and can't respond to memory trim events. For details, see
ComponentCallbacks2.onTrimMemory(int). To accommodate
this, starting in Android 14:
- Apps with a visible
Activityinstance are notified ofTRIM_MEMORY_UI_HIDDENas soon as they move to the background. Apps that stay in a lifecycle without a UI, such as apps with a foreground service, might receiveTRIM_MEMORY_BACKGROUND. Other trim events aren't delivered, because when apps are eligible for those events, they're expected to be frozen. - Shortly after entering the cached state, the system might request the app runtime to perform a GC in preparation for potentially becoming frozen.
- When an app process is frozen, additional memory compaction steps might occur, such as writing dirty pages to backing storage and swapping anonymous pages to ZRAM.
- If all processes for a particular app are frozen, the system terminates any active TCP sockets maintained by the app. This prevents the server side of the socket from sending TCP keepalive pings that would wake up the device modem.
Cached app processes are unfrozen when their process state elevates from cached
to a higher importance state. To reduce unfreeze events in Android 14 and
higher, the system queues context-registered broadcasts while the app is in the
cached state. Context-registered broadcasts are receivers that an app registers
dynamically by calling Context.registerReceiver. The
system delivers these queued broadcasts only after the app is unfrozen. In
contrast, the system does not queue manifest-declared broadcasts.
Manifest-declared broadcasts are receivers statically declared in
AndroidManifest.xml using the <receiver> element. The system immediately
unfreezes the cached app to deliver manifest-declared broadcasts.
System health impact
Android terminates the least recently used cached app process if there are more
than MAX_CACHED_PROCESSES cached app processes. On supported devices running
Android 14 or higher, MAX_CACHED_PROCESSES is significantly increased,
allowing devices to maintain substantially more cached app processes in RAM.
Maintaining more apps cached in RAM yields up to a 30% reduction in cold starts, with reductions scaling based on total device RAM. At the same time, CPU consumption by cached apps is minimized, leading to significant battery savings.
Freezer exemptions
Under certain conditions, an app process might enter the cached state but remain unfrozen. These exemptions are implementation details and might change in future Android versions:
- File locks: If a cached process holds a file lock that blocks other noncached processes, the process holding the lock isn't frozen.
BIND_WAIVE_PRIORITYbindings: App processes with incoming bindings created usingContext.BIND_WAIVE_PRIORITYcan enter the cached state but remain unfrozen until all connected client processes are also cached. This exemption supports multi-process apps, such as web browsers using Custom Tabs.
Implement the apps freezer
The cached apps freezer leverages the kernel cgroup v2 freezer. Devices shipping
with a compatible kernel can enable it. Enable the developer option Suspend
execution for cached apps or set the device config flag
activity_manager_native_boot use_freezer to true. For example:
adb shell device_config put activity_manager_native_boot use_freezer true && adb rebootThe freezer is disabled when you set the flag use_freezer to false or
disable the developer option. For example:
adb shell device_config put activity_manager_native_boot use_freezer false && adb rebootYou can toggle this setting by changing a device configuration in a software release or update.
To override MAX_CACHED_PROCESSES, for example, to set the value to 1024 for
testing:
adb shell device_config put activity_manager max_cached_processes 1024
adb shell device_config set_sync_disabled_for_tests persistentTo revert the MAX_CACHED_PROCESSES override:
adb shell device_config delete activity_manager max_cached_processes
adb shell device_config set_sync_disabled_for_tests noneThe apps freezer doesn't expose official APIs and doesn't have a reference
implementation client, but it does use the hidden system APIs setProcessFrozen
to freeze an individual process and enableFreezer to enable or disable
freezing globally.
Handle custom features
App processes aren't expected to do any work when cached, but some apps might have custom features supported by processes that are expected to run while cached. When the apps freezer is enabled on a device running such apps, the cached processes are frozen and might prevent custom features from working.
As a workaround, you can change the process status to noncached before the process needs to do any work. This change allows apps to remain active. Examples of active statuses include a bound foreground service or foreground status.
Common failure modes
When app processes are frozen, improper inter-process communication (IPC) or task scheduling can lead to app terminations or unexpected behavior.
Synchronous binder transactions to frozen processes
When a client app process sends a synchronous binder transaction to a server app
process that is frozen, the system immediately terminates the server app
process. This prevents the client thread from blocking indefinitely while
waiting for a response from the frozen server. The client thread then receives
RemoteException, and any registered listeners are
triggered. For details, see IBinder.linkToDeath.
Root cause: This failure is typically caused by a bug in the client app.
When a client binds to a service, the server process is bound to the client and
is prevented from entering the cached state before the client does. For details,
see Context.bindService. However, once the client calls
Context.unbindService, the server process can become
cached and frozen. If the client continues to use the cached
IBinder reference after unbinding, it risks communicating with
a frozen process.
To avoid this issue, ensure client apps discard IBinder
references immediately after calling
Context.unbindService.
Asynchronous binder transaction buffer overflow
When a server app process receives asynchronous (oneway) binder transactions
while frozen, the transactions are buffered in a per-process buffer. If the
server receives too many asynchronous transactions while frozen, the buffer
overflows, and the system terminates the server app process.
To prevent this buffer overflow, avoid sending excessive asynchronous binder transactions to processes that might be cached or frozen.
Repeated execution of scheduled tasks upon unfreezing
If an app executes repetitive tasks, they're suspended while the process is
frozen. For details, see
ScheduledThreadPoolExecutor.scheduleAtFixedRate
or Timer.scheduleAtFixedRate. When the
process unfreezes, the accumulated missed executions might run rapidly
back-to-back with virtually no delay.
To prevent a surge of executions when the app unfreezes, use
scheduleWithFixedDelay instead of
scheduleAtFixedRate for background
tasks. You can also use WorkManager.
Test and troubleshoot the apps freezer
To verify the app freezer is working as intended or to troubleshoot freezer-related issues, use the following diagnostic tools and commands:
Activity manager commands
You can use adb shell am commands to manually control freezing and compaction
for a specific process:
Force a process to freeze:
adb shell am freeze <process>Force a process to unfreeze:
adb shell am unfreeze <process>Force a full memory compaction on a process:
adb shell am compact full <process>
Logcat examination
View logcat to see frozen and unfrozen entries each time a process migrates in or out of the freezer:
adb logcat | grep -i "\(freezing\|froze\)"Unfreeze reason logs output enumerated values from the UnfreezeReason protocol
buffer enum.
Dumpsys inspection
Check for a list of frozen processes using dumpsys activity:
adb shell dumpsys activity | grep -A 20 "Apps frozen:"Check for the presence of the /sys/fs/cgroup/uid_0/cgroup.freeze file.
ApplicationExitInfo
To query the reason for a previous process termination, see
ActivityManager.getHistoricalProcessExitReasons.
If an app process was terminated due to a freezer-related issue, such as
receiving a synchronous binder transaction while frozen, the exit reason is set
to ApplicationExitInfo.REASON_FREEZER.
Perfetto tracing
Freezer-related events are emitted to a track named Freezer under the
system_server process in Perfetto traces:
FreezeandUnfreezeslices indicate when a process changes state.updateAppFreezeStateLSPevents show when the system server re-examines process attributes to make freezing or unfreezing decisions.
You can inspect these events directly in the Perfetto UI or analyze them using PerfettoSQL:
INCLUDE PERFETTO MODULE slices.with_context;
SELECT *
FROM process_slice
WHERE process_name = "system_server"
AND track_name = "Freezer"
AND (name LIKE "Freeze %" OR name LIKE "Unfreeze %");
In the PerfettoSQL standard library, freezer events are also summarized in the
android_freezer_events table.