Android 11 (level API 30) atau yang lebih tinggi mendukung pembekuan aplikasi yang di-cache. Fitur ini menghentikan eksekusi untuk proses yang di-cache dan mengurangi penggunaan resource oleh aplikasi yang berperilaku tidak semestinya yang mungkin mencoba beroperasi saat di-cache.
Pembekuan aplikasi dalam cache menyimpan aplikasi di RAM sambil menjaganya agar tidak menggunakan CPU. Jika Android menentukan bahwa aplikasi tidak boleh melakukan pekerjaan, tetapi mungkin diperlukan di masa mendatang, Android akan membekukan proses aplikasi, bukan menghentikannya. Tindakan ini mencegah cold start saat aplikasi diperlukan lagi.
Android membekukan aplikasi yang di-cache dengan memigrasikan prosesnya ke cgroup yang dibekukan. Hal ini mengurangi konsumsi CPU aktif dan tidak aktif saat ada aplikasi yang di-cache aktif. Anda dapat mengaktifkan pembekuan aplikasi menggunakan tanda konfigurasi sistem atau opsi developer.
Di Android 14 (level API 34) dan yang lebih tinggi, pembekuan aplikasi yang di-cache mencakup perilaku yang kuat berikut:
- Proses aplikasi dalam status cache dibekukan 10 detik setelah memasuki status cache.
- Sistem akan segera mencairkan proses aplikasi yang dibekukan selama peristiwa siklus proses. Peristiwa ini mencakup penerimaan intent, memulai layanan tugas, atau pengguna melanjutkan aktivitas.
ActivityManagerService mengelola semua proses aplikasi dan membuat keputusan siklus proses aplikasi. CachedAppOptimizer bertanggung jawab untuk menghentikan proses aplikasi.
Saat proses aplikasi dibekukan, semua thread-nya ditangguhkan dan tidak dapat
melakukan pekerjaan CPU hingga tidak dibekukan. Akibatnya, aplikasi tidak dapat melakukan pengumpulan sampah (GC) dan tidak dapat merespons peristiwa pengurangan memori. Untuk mengetahui informasi selengkapnya,
lihat ComponentCallbacks2.onTrimMemory(int). Untuk mengakomodasi hal ini, mulai di Android 14:
- Aplikasi dengan instance
Activityyang terlihat akan diberi tahu tentangTRIM_MEMORY_UI_HIDDENsegera setelah aplikasi berpindah ke latar belakang. Aplikasi yang tetap berada dalam siklus proses tanpa UI, seperti aplikasi dengan layanan latar depan, mungkin menerimaTRIM_MEMORY_BACKGROUND. Peristiwa pemangkasan lainnya tidak dikirimkan, karena saat aplikasi memenuhi syarat untuk peristiwa tersebut, aplikasi diharapkan dibekukan. - Segera setelah memasuki status cache, sistem dapat meminta runtime aplikasi untuk melakukan GC sebagai persiapan untuk berpotensi dibekukan.
- Saat proses aplikasi dibekukan, langkah-langkah pemadatan memori tambahan dapat terjadi, seperti menulis halaman kotor ke penyimpanan pendukung dan menukar halaman anonim ke ZRAM.
- Jika semua proses untuk aplikasi tertentu dibekukan, sistem akan menghentikan semua soket TCP aktif yang dikelola oleh aplikasi. Hal ini mencegah sisi server soket mengirimkan ping keepalive TCP yang akan mengaktifkan modem perangkat.
Proses aplikasi yang di-cache akan di-unfreeze saat status prosesnya ditingkatkan dari di-cache
ke status kepentingan yang lebih tinggi. Untuk mengurangi peristiwa pembekuan di Android 14 dan yang lebih tinggi, sistem mengantrekan siaran yang terdaftar dalam konteks saat aplikasi berada dalam status cache. Siaran yang terdaftar dalam konteks adalah penerima yang didaftarkan aplikasi
secara dinamis dengan memanggil Context.registerReceiver. Sistem mengirimkan siaran yang diantrekan ini hanya setelah aplikasi tidak dibekukan. Sebaliknya, sistem tidak mengantrekan siaran yang dideklarasikan manifes.
Siaran yang dideklarasikan manifes adalah penerima yang dideklarasikan secara statis di
AndroidManifest.xml menggunakan elemen <receiver>. Sistem akan segera
membuka aplikasi yang di-cache untuk mengirimkan siaran yang dideklarasikan manifes.
Dampak kesehatan sistem
Android akan menghentikan proses aplikasi yang di-cache yang paling lama tidak digunakan jika ada lebih dari MAX_CACHED_PROCESSES proses aplikasi yang di-cache. Pada perangkat yang didukung dan menjalankan
Android 14 atau yang lebih baru, MAX_CACHED_PROCESSES meningkat secara signifikan,
sehingga perangkat dapat mempertahankan lebih banyak proses aplikasi yang di-cache dalam RAM.
Dengan mempertahankan lebih banyak aplikasi yang di-cache di RAM, cold start dapat dikurangi hingga 30%, dengan pengurangan yang diskalakan berdasarkan total RAM perangkat. Pada saat yang sama, konsumsi CPU oleh aplikasi yang di-cache diminimalkan, sehingga menghemat baterai secara signifikan.
Pengecualian freezer
Dalam kondisi tertentu, proses aplikasi dapat memasuki status cache, tetapi tetap tidak dibekukan. Pengecualian ini adalah detail implementasi dan dapat berubah di versi Android mendatang:
- Kunci file: Jika proses yang di-cache memegang kunci file yang memblokir proses lain yang tidak di-cache, proses yang memegang kunci tidak dibekukan.
- Pengikatan
BIND_WAIVE_PRIORITY: Proses aplikasi dengan pengikatan masuk yang dibuat menggunakanContext.BIND_WAIVE_PRIORITYdapat memasuki status yang di-cache, tetapi tetap tidak dibekukan hingga semua proses klien yang terhubung juga di-cache. Pengecualian ini mendukung aplikasi multi-proses, seperti browser web yang menggunakan Tab Kustom.
Menerapkan pembekuan aplikasi
Pembekuan aplikasi yang di-cache menggunakan pembekuan cgroup v2 kernel. Perangkat yang dikirim dengan kernel yang kompatibel dapat mengaktifkannya. Aktifkan opsi developer Tunda
eksekusi untuk aplikasi yang di-cache atau tetapkan flag konfigurasi perangkat
activity_manager_native_boot use_freezer ke true. Contoh:
adb shell device_config put activity_manager_native_boot use_freezer true && adb rebootPembekuan dinonaktifkan saat Anda menyetel flag use_freezer ke false atau
menonaktifkan opsi developer. Contoh:
adb shell device_config put activity_manager_native_boot use_freezer false && adb rebootAnda dapat mengaktifkan/menonaktifkan setelan ini dengan mengubah konfigurasi perangkat dalam rilis atau update software.
Untuk mengganti MAX_CACHED_PROCESSES, misalnya, untuk menetapkan nilai ke 1024 untuk
pengujian:
adb shell device_config put activity_manager max_cached_processes 1024adb shell device_config set_sync_disabled_for_tests persistent
Untuk mengembalikan penggantian MAX_CACHED_PROCESSES:
adb shell device_config delete activity_manager max_cached_processesadb shell device_config set_sync_disabled_for_tests none
Mulai Android 16 (level API 36) dan yang lebih tinggi, Android menyediakan API publik resmi, seperti
IBinder.FrozenStateChangeCallback dan
IBinder.addFrozenStateChangeCallback,
untuk mengamati kapan proses jarak jauh dibekukan atau tidak dibekukan. Komponen yang berinteraksi
dengan aplikasi yang mungkin di-cache dapat menggunakan API ini untuk melacak status dibekukan
proses jarak jauh.
Persyaratan perangkat dan kernel
Pengoptimal aplikasi yang di-cache memerlukan dukungan cgroup v2 kernel. Selain itu,
notifikasi perubahan status pembekuan menggunakan IBinder.FrozenStateChangeCallback
memerlukan dukungan driver binder kernel, yang merupakan standar di Android Common
Kernels (ACK) dan Generic Kernel Images (GKI) mulai dari
Android 14 (level API 34) dan yang lebih tinggi.
Anda dapat memverifikasi apakah perangkat mendukung kemampuan ini menggunakan perintah
adb standar, sebagai berikut:
Periksa apakah pembekuan diaktifkan di perangkat (untuk build pengguna atau debug):
adb shell device_config get activity_manager_native_boot use_freezerAtau verifikasi bahwa proses sedang dibekukan secara aktif oleh sistem:
adb shell dumpsys activity | grep -A 20 "Apps frozen:"Periksa dukungan pengontrol pembekuan cgroup v2 (untuk perangkat apa pun):
Pastikan
freezertercantum di antara pengontrol cgroup v2 yang tersedia:adb shell cat /sys/fs/cgroup/cgroup.controllersAtau, pada perangkat yang telah di-root atau build userdebug, verifikasi bahwa node freezer cgroup v2 dipasang di cgroup turunan:
adb root && adb shell ls /sys/fs/cgroup/uid_0/cgroup.freezeJika file ini ada, kernel mendukung pembekuan cgroup v2.
Periksa dukungan notifikasi perubahan status pembekuan (untuk perangkat apa pun):
Di perangkat yang menjalankan Android 14 dan yang lebih tinggi dengan driver binder Generic Kernel Image (GKI) yang kompatibel,
IBinder.addFrozenStateChangeCallbackberhasil mendaftarkan callback. Jika driver binder kernel yang mendasarinya tidak mendukung notifikasi pembekuan, metode akan menampilkanUnsupportedOperationException.
Menangani fitur kustom
Proses aplikasi tidak diharapkan melakukan pekerjaan apa pun saat di-cache, tetapi beberapa aplikasi mungkin memiliki fitur kustom yang didukung oleh proses yang diharapkan berjalan saat di-cache. Jika pembekuan aplikasi diaktifkan pada perangkat yang menjalankan aplikasi tersebut, proses yang di-cache akan dibekukan dan dapat mencegah fitur kustom berfungsi.
Sebagai solusi sementara, Anda dapat mengubah status proses menjadi non-cache sebelum proses perlu melakukan pekerjaan apa pun. Perubahan ini memungkinkan aplikasi tetap aktif. Contoh status aktif mencakup layanan latar depan terikat atau status latar depan.
Mode kegagalan umum
Saat proses aplikasi dibekukan, komunikasi antar-proses (IPC) atau penjadwalan tugas yang tidak tepat dapat menyebabkan penghentian aplikasi atau perilaku yang tidak terduga.
Transaksi binder sinkron ke proses yang dibekukan
Saat proses aplikasi klien mengirim transaksi binder sinkron ke proses aplikasi server yang dibekukan, sistem akan segera menghentikan proses aplikasi server. Hal ini mencegah thread klien diblokir tanpa batas waktu saat
menunggu respons dari server yang dibekukan. Kemudian, thread klien menerima
RemoteException, dan setiap pemroses yang terdaftar akan
dipicu. Untuk mengetahui informasi selengkapnya, lihat
IBinder.linkToDeath.
Penyebab utama: Kegagalan ini biasanya disebabkan oleh bug di aplikasi klien.
Saat klien terikat ke layanan, proses server terikat ke klien dan
dicegah memasuki status yang di-cache sebelum klien melakukannya. Untuk mengetahui
informasi selengkapnya, lihat Context.bindService. Namun, setelah
klien memanggil Context.unbindService, proses server
dapat di-cache dan dibekukan. Jika klien terus menggunakan referensi
IBinder yang di-cache setelah membatalkan pengikatan, klien berisiko berkomunikasi dengan
proses yang dibekukan.
Untuk menghindari masalah ini, pastikan aplikasi klien menghapus referensi IBinder
segera setelah memanggil
Context.unbindService.
Mengelola panggilan balik jarak jauh ke proses klien
Layanan dan komponen sistem yang mempertahankan callback binder yang berjalan lama ke proses klien dapat mencegah kegagalan sinkron dan overflow buffer asinkron dengan melacak status klien yang dibekukan:
- Mendaftarkan pemroses perubahan status: Gunakan
IBinder.addFrozenStateChangeCallbackpada token binder klien yang masuk untuk menerima notifikasi saat proses klien masuk atau keluar dari pembekuan. - Menjeda pengiriman saat dibekukan: Saat klien memasuki
STATE_FROZEN, jeda pengiriman callback atau pembaruan status ke klien tersebut. - Lanjutkan dan kirim setelah pencairan: Saat klien bertransisi ke
STATE_UNFROZEN, lanjutkan pengiriman callback dan kirim pembaruan yang diperlukan yang dikelompokkan atau digabungkan. - Menggunakan RemoteCallbackList: Layanan sistem yang menggunakan
RemoteCallbackListdapat mengonfigurasi kebijakan tujuan panggilan yang dibekukan untuk menjeda dan melanjutkan pengiriman callback secara otomatis tanpa mempertahankan logika pelacakan manual. Untuk mengetahui informasi selengkapnya, lihat Rekomendasi pembekuan Binder untuk layanan sistem.
Overflow buffer transaksi binder asinkron
Saat proses aplikasi server menerima transaksi binder asinkron (oneway) saat dibekukan, transaksi akan di-buffer dalam buffer per proses. Jika server menerima terlalu banyak transaksi asinkron saat dibekukan, buffer akan meluap, dan sistem akan menghentikan proses aplikasi server.
Untuk mencegah buffer overflow ini, hindari mengirim transaksi binder asinkron yang berlebihan ke proses yang mungkin di-cache atau dibekukan.
Eksekusi berulang tugas terjadwal setelah tidak dibekukan
Jika aplikasi menjalankan tugas berulang, tugas tersebut akan ditangguhkan saat proses
dibekukan. Untuk mengetahui informasi selengkapnya, lihat
ScheduledThreadPoolExecutor.scheduleAtFixedRate
atau Timer.scheduleAtFixedRate. Saat
proses dilanjutkan, eksekusi yang terlewatkan yang terakumulasi dapat berjalan dengan cepat
secara berurutan tanpa penundaan.
Untuk mencegah lonjakan eksekusi saat aplikasi tidak dibekukan, gunakan
scheduleWithFixedDelay, bukan
scheduleAtFixedRate untuk tugas
latar belakang. Anda juga dapat menggunakan WorkManager.
Menguji dan memecahkan masalah pembekuan aplikasi
Untuk memverifikasi bahwa pembekuan aplikasi berfungsi sebagaimana mestinya atau untuk memecahkan masalah terkait pembekuan, gunakan alat dan perintah diagnostik berikut:
Perintah pengelola aktivitas
Anda dapat menggunakan perintah adb shell am untuk mengontrol pembekuan dan pemadatan secara manual untuk proses tertentu:
Memaksa proses berhenti berfungsi:
adb shell am freeze <process>Memaksa proses untuk berhenti dibekukan:
adb shell am unfreeze <process>Memaksa pemadatan memori penuh pada suatu proses:
adb shell am compact full <process>
Pemeriksaan Logcat
Lihat logcat untuk melihat entri yang dibekukan dan tidak dibekukan setiap kali proses bermigrasi ke dalam atau keluar dari pembeku:
adb logcat | grep -i "\(freezing\|froze\)"Output log alasan pembatalan pembekuan mencantumkan nilai dari enum buffer protokol UnfreezeReason.
Pemeriksaan dumpsys
Periksa daftar proses yang dibekukan menggunakan dumpsys activity:
adb shell dumpsys activity | grep -A 20 "Apps frozen:"Periksa keberadaan file /sys/fs/cgroup/uid_0/cgroup.freeze.
ApplicationExitInfo
Untuk membuat kueri alasan penghentian proses sebelumnya, lihat
ActivityManager.getHistoricalProcessExitReasons.
Jika proses aplikasi dihentikan karena masalah terkait pembekuan, seperti
menerima transaksi binder sinkron saat dibekukan, alasan keluar ditetapkan
ke ApplicationExitInfo.REASON_FREEZER.
Pelacakan Perfetto
Peristiwa terkait Freezer dipancarkan ke jalur bernama Freezer di bawah
proses system_server dalam rekaman aktivitas Perfetto:
- Slice
FreezedanUnfreezemenunjukkan kapan status proses berubah. - Peristiwa
updateAppFreezeStateLSPmenunjukkan kapan server sistem memeriksa ulang atribut proses untuk membuat keputusan pembekuan atau pembatalan pembekuan.
Anda dapat memeriksa peristiwa ini secara langsung di UI Perfetto atau menganalisisnya menggunakan 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 %");
Di library standar PerfettoSQL, peristiwa pembekuan juga diringkas dalam tabel
android_freezer_events.