Android 11 (level API 30) atau yang lebih tinggi mendukung freezer 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.
Freezer aplikasi yang di-cache menyimpan aplikasi di RAM sekaligus 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. Hal 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 jika ada aplikasi yang di-cache aktif. Anda dapat mengaktifkan freezer aplikasi menggunakan flag konfigurasi sistem atau opsi developer.
Di Android 14 (level API 34) dan yang lebih tinggi, freezer aplikasi yang di-cache mencakup perilaku tangguh berikut:
- Proses aplikasi dalam status cache dibekukan 10 detik setelah memasuki status cache.
- Sistem akan segera mengaktifkan kembali proses aplikasi yang dibekukan selama peristiwa siklus proses. Peristiwa ini mencakup menerima intent, memulai layanan tugas, atau pengguna melanjutkan aktivitas.
ActivityManagerService mengelola semua proses aplikasi dan membuat keputusan siklus proses aplikasi. CachedAppOptimizer bertanggung jawab untuk membekukan proses aplikasi.
Saat proses aplikasi dibekukan, semua thread-nya akan ditangguhkan dan tidak dapat melakukan pekerjaan CPU hingga tidak dibekukan. Akibatnya, aplikasi tidak dapat melakukan pengumpulan sampah (GC) dan tidak dapat merespons peristiwa pemangkasan memori. Untuk mengetahui detailnya, lihat
ComponentCallbacks2.onTrimMemory(int). Untuk mengakomodasi hal ini, mulai Android 14:
- Aplikasi dengan instance
Activityyang terlihat akan diberi tahu tentangTRIM_MEMORY_UI_HIDDENsegera setelah 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 mungkin meminta runtime aplikasi untuk melakukan GC sebagai persiapan agar berpotensi dibekukan.
- Saat proses aplikasi dibekukan, langkah-langkah pemadatan memori tambahan mungkin 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 mengirim ping TCP keepalive yang akan mengaktifkan modem perangkat.
Proses aplikasi yang di-cache tidak dibekukan saat status prosesnya ditingkatkan dari cache ke status prioritas yang lebih tinggi. Untuk mengurangi peristiwa tidak dibekukan di Android 14 dan yang lebih tinggi, sistem akan 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 hanya mengirimkan siaran yang diantrekan ini 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 mengaktifkan kembali aplikasi yang di-cache untuk mengirimkan siaran yang dideklarasikan manifes.
Dampak kesehatan sistem
Android menghentikan proses aplikasi yang di-cache yang paling lama tidak digunakan jika ada lebih dari MAX_CACHED_PROCESSES proses aplikasi yang di-cache. Di perangkat yang didukung yang menjalankan Android 14 atau yang lebih tinggi, MAX_CACHED_PROCESSES meningkat secara signifikan, sehingga perangkat dapat mempertahankan proses aplikasi yang di-cache secara substansial lebih banyak di RAM.
Mempertahankan lebih banyak aplikasi yang di-cache di RAM menghasilkan pengurangan cold start 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 mungkin memasuki status cache tetapi tetap tidak dibekukan. Pengecualian ini adalah detail implementasi dan mungkin berubah pada versi Android mendatang:
- Kunci file: Jika proses yang di-cache memiliki kunci file yang memblokir proses non-cache lainnya, proses yang memiliki kunci tidak akan dibekukan.
BIND_WAIVE_PRIORITYbinding: Proses aplikasi dengan binding masuk yang dibuat menggunakanContext.BIND_WAIVE_PRIORITYdapat memasuki status 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.
Mengimplementasikan freezer aplikasi
Freezer aplikasi yang di-cache memanfaatkan freezer cgroup v2 kernel. Perangkat yang dikirimkan dengan kernel yang kompatibel dapat mengaktifkannya. Aktifkan opsi developer Suspend execution for cached apps 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 rebootFreezer dinonaktifkan saat Anda menetapkan 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 mengalihkan 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 1024
adb shell device_config set_sync_disabled_for_tests persistentUntuk mengembalikan penggantian MAX_CACHED_PROCESSES:
adb shell device_config delete activity_manager max_cached_processes
adb shell device_config set_sync_disabled_for_tests noneFreezer aplikasi tidak mengekspos API resmi dan tidak memiliki klien implementasi referensi, tetapi menggunakan API sistem tersembunyi setProcessFrozen untuk membekukan proses individual dan enableFreezer untuk mengaktifkan atau menonaktifkan pembekuan secara global.
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. Saat freezer aplikasi diaktifkan di perangkat yang menjalankan aplikasi tersebut, proses yang di-cache akan dibekukan dan mungkin mencegah fitur kustom berfungsi.
Sebagai solusinya, 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. Thread klien kemudian menerima
RemoteException, dan semua pemroses terdaftar akan
dipicu. Untuk mengetahui detailnya, 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 cache sebelum klien melakukannya. Untuk mengetahui detailnya,
lihat Context.bindService. Namun, setelah klien memanggil
Context.unbindService, proses server dapat menjadi
di-cache dan dibekukan. Jika klien terus menggunakan referensi yang di-cache
IBinder setelah tidak terikat, klien berisiko berkomunikasi dengan
proses yang dibekukan.
Untuk menghindari masalah ini, pastikan aplikasi klien membuang IBinder
referensi segera setelah memanggil
Context.unbindService.
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 overflow buffer ini, hindari mengirim transaksi binder asinkron yang berlebihan ke proses yang mungkin di-cache atau dibekukan.
Eksekusi berulang tugas terjadwal saat tidak dibekukan
Jika aplikasi menjalankan tugas berulang, tugas tersebut akan ditangguhkan saat proses dibekukan. Untuk mengetahui detailnya, lihat
ScheduledThreadPoolExecutor.scheduleAtFixedRate
atau Timer.scheduleAtFixedRate. Saat proses tidak dibekukan, eksekusi yang terlewat dan 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 freezer aplikasi
Untuk memverifikasi bahwa freezer aplikasi berfungsi sebagaimana mestinya atau untuk memecahkan masalah terkait freezer, 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 untuk dibekukan:
adb shell am freeze <process>Memaksa proses untuk tidak 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 masuk atau keluar dari freezer:
adb logcat | grep -i "\(freezing\|froze\)"Log alasan tidak dibekukan menampilkan nilai yang dihitung 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 mengkueri alasan penghentian proses sebelumnya, lihat
ActivityManager.getHistoricalProcessExitReasons.
Jika proses aplikasi dihentikan karena masalah terkait freezer, seperti
menerima transaksi binder sinkron saat dibekukan, alasan keluar akan ditetapkan
ke ApplicationExitInfo.REASON_FREEZER.
Pelacakan Perfetto
Peristiwa terkait freezer akan ditampilkan ke trek bernama Freezer di bawah proses system_server dalam rekaman aktivitas Perfetto:
- Slice
FreezedanUnfreezemenunjukkan kapan proses berubah status. - Peristiwa
updateAppFreezeStateLSPmenunjukkan kapan server sistem memeriksa ulang atribut proses untuk membuat keputusan pembekuan atau tidak dibekukan.
Anda dapat memeriksa peristiwa ini 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 freezer juga diringkas dalam tabel android_freezer_events.