Update sistem A/B lama, yang juga dikenal sebagai update yang lancar , memastikan sistem booting yang dapat digunakan tetap ada di disk selama update over the air (OTA). Pendekatan ini mengurangi kemungkinan perangkat tidak aktif setelah update, yang berarti lebih sedikit penggantian perangkat dan flashing ulang perangkat di pusat reparasi dan garansi. Sistem operasi kelas komersial lainnya seperti ChromeOS juga berhasil menggunakan update A/B.
Untuk informasi selengkapnya tentang update sistem A/B dan cara kerjanya, lihat Pemilihan partisi (slot).
Update sistem A/B memberikan manfaat berikut:
- Update OTA dapat terjadi saat sistem berjalan, tanpa mengganggu pengguna. Pengguna dapat terus menggunakan perangkat mereka selama OTA—satu-satunya periode nonaktif selama update adalah saat perangkat dimulai ulang ke partisi disk yang diupdate.
- Setelah update, mulai ulang tidak akan lebih lama dari mulai ulang biasa.
- Jika OTA gagal diterapkan (misalnya, karena flash yang buruk), pengguna tidak akan terpengaruh. Pengguna akan terus menjalankan OS lama, dan klien bebas untuk mencoba ulang update.
- Jika update OTA diterapkan tetapi gagal melakukan booting, perangkat akan dimulai ulang ke dalam partisi lama dan tetap dapat digunakan. Klien dapat mencoba lagi pembaruan.
- Setiap error (seperti error I/O) hanya memengaruhi set partisi yang tidak digunakan dan dapat dicoba ulang. Kesalahan tersebut juga menjadi lebih kecil kemungkinannya karena beban I/O sengaja dibuat rendah untuk menghindari penurunan pengalaman pengguna.
-
Update dapat di-streaming ke perangkat A/B, sehingga Anda tidak perlu mendownload paket sebelum
menginstalnya. Streaming berarti pengguna tidak perlu memiliki cukup ruang kosong untuk
menyimpan paket update di
/data
atau/cache
. - Partisi cache tidak lagi digunakan untuk menyimpan paket update OTA, sehingga tidak perlu memastikan bahwa partisi cache cukup besar untuk update mendatang.
- dm-verity menjamin perangkat akan mem-booting image yang tidak rusak. Jika perangkat tidak melakukan booting karena masalah OTA atau dm-verity yang buruk, perangkat dapat dimulai ulang ke image lama. ( Verifikasi Boot Android tidak memerlukan update A/B.)
Tentang update sistem A/B
Update A/B memerlukan perubahan pada klien dan sistem. Namun, server paket OTA tidak memerlukan perubahan: paket update masih ditayangkan melalui HTTPS. Untuk perangkat yang menggunakan infrastruktur OTA Google, semua perubahan sistem ada di AOSP, dan kode klien disediakan oleh layanan Google Play. OEM yang tidak menggunakan infrastruktur OTA Google akan dapat menggunakan kembali kode sistem AOSP, tetapi harus menyediakan klien mereka sendiri.
Untuk OEM yang menyediakan kliennya sendiri, klien harus:
- Tentukan kapan akan mengambil update. Karena update A/B terjadi di latar belakang, update tersebut tidak lagi dimulai oleh pengguna. Untuk menghindari gangguan bagi pengguna, sebaiknya update dijadwalkan saat perangkat dalam mode pemeliharaan tidak ada aktivitas, seperti di malam hari, dan menggunakan Wi-Fi. Namun, klien Anda dapat menggunakan heuristik apa pun yang Anda inginkan.
- Hubungi server paket OTA Anda dan tentukan apakah update tersedia. Kode ini sebagian besar akan sama dengan kode klien yang ada, kecuali Anda ingin memberikan sinyal bahwa perangkat mendukung A/B. (Klien Google juga menyertakan tombol Periksa sekarang bagi pengguna untuk memeriksa update terbaru.)
-
Panggil
update_engine
dengan URL HTTPS untuk paket update Anda, dengan asumsi URL tersebut tersedia.update_engine
akan mengupdate blok mentah di partisi yang saat ini tidak digunakan saat streaming paket update. -
Laporkan keberhasilan atau kegagalan penginstalan ke server Anda, berdasarkan
kode hasil
update_engine
. Jika update berhasil diterapkan,update_engine
akan memberi tahu bootloader untuk melakukan booting ke OS baru saat dimulai ulang berikutnya. Bootloader akan kembali ke OS lama jika OS baru gagal melakukan booting, sehingga tidak ada pekerjaan yang diperlukan dari klien. Jika update gagal, klien harus memutuskan kapan (dan apakah) akan mencoba lagi, berdasarkan kode error mendetail. Misalnya, klien yang baik dapat mengenali bahwa paket OTA parsial ("diff") gagal dan mencoba paket OTA lengkap.
Secara opsional, klien dapat:
- Tampilkan notifikasi yang meminta pengguna untuk memulai ulang. Jika Anda ingin menerapkan kebijakan yang mendorong pengguna untuk melakukan update secara rutin, notifikasi ini dapat ditambahkan ke klien Anda. Jika klien tidak meminta pengguna, pengguna akan mendapatkan update saat mereka memulai ulang perangkat lagi. (Klien Google memiliki penundaan yang dapat dikonfigurasi per update.)
- Menampilkan notifikasi yang memberi tahu pengguna apakah mereka melakukan booting ke versi OS baru atau apakah mereka diharapkan untuk melakukannya, tetapi kembali ke versi OS lama. (Klien Google biasanya tidak melakukan keduanya.)
Di sisi sistem, update sistem A/B memengaruhi hal berikut:
-
Pemilihan partisi (slot), daemon
update_engine
, dan interaksi bootloader (dijelaskan di bawah) - Proses build dan pembuatan paket update OTA (dijelaskan dalam Menerapkan Update A/B)
Pemilihan partisi (slot)
Update sistem A/B menggunakan dua kumpulan partisi yang disebut sebagai slot (biasanya slot A dan slot B). Sistem berjalan dari slot saat ini sedangkan partisi di slot yang tidak digunakan tidak diakses oleh sistem yang berjalan selama operasi normal. Pendekatan ini membuat update tahan terhadap error dengan mempertahankan slot yang tidak digunakan sebagai penggantian: Jika error terjadi selama atau segera setelah update, sistem dapat melakukan rollback ke slot lama dan terus memiliki sistem yang berfungsi. Untuk mencapai tujuan ini, tidak ada partisi yang digunakan oleh slot saat ini yang harus diupdate sebagai bagian dari update OTA (termasuk partisi yang hanya memiliki satu salinan).
Setiap slot memiliki atribut bootable yang menyatakan apakah slot berisi sistem yang benar tempat perangkat dapat melakukan booting. Slot saat ini dapat di-booting saat sistem berjalan, tetapi slot lainnya mungkin memiliki versi sistem lama (masih benar), versi yang lebih baru, atau data yang tidak valid. Terlepas dari slot saat ini, ada satu slot yang merupakan slot aktif (slot yang akan digunakan bootloader untuk melakukan booting pada booting berikutnya) atau slot pilihan.
Setiap slot juga memiliki atribut successful yang ditetapkan oleh ruang pengguna, yang hanya relevan
jika slot juga dapat di-booting. Slot yang berhasil harus dapat melakukan booting, berjalan, dan mengupdate
dirinya sendiri. Slot yang dapat di-booting yang tidak ditandai sebagai berhasil (setelah beberapa upaya dilakukan untuk
melakukan booting darinya) harus ditandai sebagai tidak dapat di-booting oleh bootloader, termasuk mengubah slot
aktif ke slot lain yang dapat di-booting (biasanya ke slot yang berjalan tepat sebelum upaya
melakukan booting ke slot baru yang aktif). Detail spesifik antarmuka ditentukan dalam
boot_control.h
.
Memperbarui daemon mesin
Update sistem A/B menggunakan daemon latar belakang yang disebut
update_engine
untuk menyiapkan sistem agar melakukan booting ke versi baru yang diupdate. Daemon
ini dapat melakukan tindakan berikut:
- Membaca dari partisi A/B slot saat ini dan menulis data apa pun ke partisi A/B slot yang tidak digunakan seperti yang diinstruksikan oleh paket OTA.
- Panggil antarmuka
boot_control
dalam alur kerja yang telah ditentukan sebelumnya. - Jalankan program pasca-penginstalan dari partisi baru setelah menulis semua partisi slot yang tidak digunakan, seperti yang diinstruksikan oleh paket OTA. (Untuk mengetahui detailnya, lihat Pasca-penginstalan).
Karena daemon update_engine
tidak terlibat dalam proses booting itu sendiri, daemon tersebut
dibatasi dalam hal yang dapat dilakukannya selama update oleh
kebijakan dan fitur SELinux di
slot saat ini (kebijakan dan fitur tersebut tidak dapat diupdate hingga sistem melakukan booting ke
versi baru). Untuk mempertahankan sistem yang andal, proses update
tidak boleh mengubah tabel partisi, konten partisi di
slot saat ini, atau konten partisi non-A/B yang tidak dapat dihapus total dengan reset pabrik.
Memperbarui sumber mesin
Sumber update_engine
terletak di
system/update_engine
. File dexopt OTA A/B dibagi antara installd
dan pengelola paket:
-
frameworks/native/cmds/installd/
ota* menyertakan skrip pasca-penginstalan, biner untuk chroot, clone installd yang memanggil dex2oat, skrip pemindahan artefak pasca-OTA, dan file rc untuk skrip pemindahan. -
frameworks/base/services/core/java/com/android/server/pm/OtaDexoptService.java
(plusOtaDexoptShellCommand
) adalah pengelola paket yang menyiapkan perintah dex2oat untuk aplikasi.
Untuk contoh penggunaan, lihat
/device/google/marlin/device-common.mk
.
Memperbarui log mesin
Untuk rilis Android 8.x dan yang lebih lama, log update_engine
dapat ditemukan di
logcat
dan dalam laporan bug. Agar log update_engine
tersedia di sistem file, terapkan patch perubahan berikut ke build Anda:
Perubahan ini menyimpan salinan log update_engine
terbaru ke
/data/misc/update_engine_log/update_engine.YEAR-TIME
. Selain log saat ini, lima log terbaru disimpan di bagian
/data/misc/update_engine_log/
. Pengguna dengan ID grup log akan
dapat mengakses log sistem file.
Interaksi bootloader
HAL boot_control
digunakan oleh update_engine
(dan mungkin daemon
lainnya) untuk memberi tahu bootloader dari mana harus melakukan booting. Contoh skenario umum dan status terkaitnya mencakup hal berikut:
- Kasus normal: Sistem berjalan dari slot saat ini, baik slot A maupun B. Sejauh ini belum ada update yang diterapkan. Slot sistem saat ini dapat di-booting, berhasil, dan slot aktif.
- Update sedang berlangsung: Sistem berjalan dari slot B, sehingga slot B adalah slot yang dapat di-booting, berhasil, dan aktif. Slot A ditandai sebagai tidak dapat di-booting karena konten slot A sedang diupdate, tetapi belum selesai. Mulai ulang dalam status ini akan terus melakukan booting dari slot B.
- Update diterapkan, mulai ulang tertunda: Sistem berjalan dari slot B, slot B dapat di-booting dan berhasil, tetapi slot A ditandai sebagai aktif (dan karenanya ditandai sebagai dapat di-booting). Slot A belum ditandai sebagai berhasil dan beberapa upaya untuk melakukan booting dari slot A harus dilakukan oleh bootloader.
-
Sistem dimulai ulang ke update baru: Sistem berjalan dari slot A untuk
pertama kalinya, slot B masih dapat di-booting dan berhasil, sedangkan slot A hanya dapat di-booting, dan masih
aktif, tetapi tidak berhasil. Daemon ruang pengguna,
update_verifier
, harus menandai slot A sebagai berhasil setelah beberapa pemeriksaan dilakukan.
Dukungan update streaming
Perangkat pengguna tidak selalu memiliki cukup ruang di /data
untuk mendownload paket
update. Karena OEM maupun pengguna tidak ingin membuang ruang di partisi /cache
,
beberapa pengguna tidak mendapatkan update karena perangkat tidak memiliki tempat untuk menyimpan paket update. Untuk
mengatasi masalah ini, Android 8.0 menambahkan dukungan untuk streaming update A/B yang menulis blok
langsung ke partisi B saat didownload, tanpa harus menyimpan blok di
/data
. Update A/B streaming hampir tidak memerlukan penyimpanan sementara dan hanya memerlukan
penyimpanan yang cukup untuk sekitar 100 KiB metadata.
Untuk mengaktifkan update streaming di Android 7.1, pilih patch berikut:
- Mengizinkan pembatalan permintaan resolusi proxy
- Memperbaiki penghentian transfer saat me-resolve proxy
- Menambahkan pengujian unit untuk TerminateTransfer di antara rentang
- Membersihkan RetryTimeoutCallback()
Patch ini diperlukan untuk mendukung update A/B streaming di Android 7.1 dan yang lebih baru, baik menggunakan Layanan Seluler Google (GMS) maupun klien update lainnya.
Durasi update A/B
Proses update dimulai saat paket OTA (disebut dalam kode sebagai payload) tersedia untuk didownload. Kebijakan di perangkat dapat menunda download dan penerapan payload berdasarkan level baterai, aktivitas pengguna, status pengisian daya, atau kebijakan lainnya. Selain itu, karena update berjalan di latar belakang, pengguna mungkin tidak mengetahui bahwa update sedang berlangsung. Semua ini berarti proses update dapat terganggu kapan saja karena kebijakan, mulai ulang yang tidak terduga, atau tindakan pengguna.
Secara opsional, metadata dalam paket OTA itu sendiri menunjukkan bahwa update dapat di-streaming; paket
yang sama juga dapat digunakan untuk penginstalan non-streaming. Server dapat menggunakan metadata untuk
memberi tahu klien bahwa server sedang melakukan streaming sehingga klien akan menyerahkan OTA ke
update_engine
dengan benar. Produsen perangkat dengan server dan klien mereka sendiri
dapat mengaktifkan update streaming dengan memastikan server mengidentifikasi update yang sedang di-streaming (atau
mengasumsikan semua update sedang di-streaming) dan klien melakukan panggilan yang benar ke
update_engine
untuk streaming. Produsen dapat menggunakan fakta bahwa paket
adalah varian streaming untuk mengirim tanda ke klien guna memicu pengalihan ke sisi
framework sebagai streaming.
Setelah payload tersedia, proses update adalah sebagai berikut:
Langkah | Aktivitas |
---|---|
1 |
Slot saat ini (atau "slot sumber") ditandai sebagai berhasil (jika belum ditandai) dengan
markBootSuccessful() .
|
2 |
Slot yang tidak digunakan (atau "slot target") ditandai sebagai tidak dapat di-booting dengan memanggil fungsi
setSlotAsUnbootable() . Slot saat ini selalu ditandai sebagai berhasil di
awal update untuk mencegah bootloader kembali ke slot yang tidak digunakan,
yang akan segera memiliki data yang tidak valid. Jika sistem telah mencapai titik saat dapat mulai
menerapkan update, slot saat ini akan ditandai sebagai berhasil meskipun komponen utama
lainnya rusak (seperti UI dalam loop error) karena software baru
dapat di-push untuk memperbaiki masalah ini. Payload update adalah blob buram dengan petunjuk untuk mengupdate ke versi baru. Payload update terdiri dari hal berikut:
|
3 | Metadata payload didownload. |
4 | Untuk setiap operasi yang ditentukan dalam metadata, secara berurutan, data terkait (jika ada) didownload ke memori, operasi diterapkan, dan memori terkait dihapus. |
5 | Seluruh partisi dibaca ulang dan diverifikasi dengan hash yang diharapkan. |
6 | Langkah pasca-penginstalan (jika ada) dijalankan. Jika terjadi error selama eksekusi langkah apa pun, update akan gagal dan dicoba lagi dengan kemungkinan payload yang berbeda. Jika semua langkah sejauh ini berhasil, update akan berhasil dan langkah terakhir akan dijalankan. |
7 |
Slot yang tidak digunakan ditandai sebagai aktif dengan memanggil setActiveBootSlot() .
Menandai slot yang tidak digunakan sebagai aktif tidak berarti slot tersebut akan selesai melakukan booting. Bootloader (atau
sistem itu sendiri) dapat mengalihkan slot aktif kembali jika tidak membaca status yang berhasil.
|
8 |
Pasca-penginstalan (dijelaskan di bawah) melibatkan pengoperasian program dari versi "update baru"
saat masih berjalan di versi lama. Jika ditentukan dalam paket OTA, langkah ini
bersifat
wajib dan program harus ditampilkan dengan kode keluar 0 ;
jika tidak, update akan gagal.
|
9 |
Setelah sistem berhasil melakukan booting cukup jauh ke slot baru dan menyelesaikan
pemeriksaan pasca-reboot, slot saat ini (sebelumnya "slot target") ditandai sebagai
berhasil dengan memanggil
markBootSuccessful() .
|
Pasca-penginstalan
Untuk setiap partisi tempat langkah pasca-penginstalan ditentukan,
update_engine
akan memasang partisi baru ke lokasi tertentu dan menjalankan
program yang ditentukan di OTA relatif terhadap partisi yang dipasang. Misalnya, jika
program pasca-penginstalan ditentukan sebagai usr/bin/postinstall
di partisi sistem,
partisi ini dari slot yang tidak digunakan akan dipasang di lokasi tetap (seperti
/postinstall_mount
) dan
perintah /postinstall_mount/usr/bin/postinstall
dieksekusi.
Agar pasca-penginstalan berhasil, kernel lama harus dapat:
- Pasang format sistem file baru. Jenis sistem file tidak dapat berubah kecuali ada dukungan untuknya di kernel lama, termasuk detail seperti algoritma kompresi yang digunakan jika menggunakan sistem file yang dikompresi (yaitu SquashFS).
-
Pahami format program pasca-penginstalan partisi baru. Jika menggunakan
biner Executable and Linkable Format (ELF), biner tersebut harus kompatibel dengan kernel lama
(misalnya, program baru 64-bit yang berjalan di kernel 32-bit lama jika arsitektur beralih dari
build 32-bit ke 64-bit). Kecuali jika loader (
ld
) diperintahkan untuk menggunakan jalur lain atau mem-build biner statis, library akan dimuat dari image sistem lama, bukan yang baru.
Misalnya, Anda dapat menggunakan skrip shell sebagai program pasca-penginstalan yang ditafsirkan oleh biner shell
sistem lama dengan penanda #!
di bagian atas), lalu menyiapkan jalur library dari lingkungan baru untuk menjalankan program pasca-penginstalan biner yang lebih
kompleks. Atau, Anda dapat menjalankan langkah pasca-penginstalan dari
partisi khusus yang lebih kecil untuk mengaktifkan format sistem file di partisi sistem utama agar
dapat diupdate tanpa menimbulkan masalah kompatibilitas mundur atau update stepping-stone; hal ini akan
memungkinkan pengguna mengupdate langsung ke versi terbaru dari image pabrik.
Program pasca-penginstalan baru dibatasi oleh kebijakan SELinux yang ditentukan dalam sistem lama. Dengan demikian, langkah pasca-penginstalan cocok untuk melakukan tugas yang diperlukan oleh desain di perangkat tertentu atau tugas upaya terbaik lainnya. Langkah pasca-penginstalan tidak cocok untuk perbaikan bug satu kali sebelum memulai ulang yang memerlukan izin yang tidak terduga.
Program pasca-penginstalan yang dipilih berjalan dalam
konteks SELinux postinstall
. Semua file di partisi yang baru dipasang akan
diberi tag postinstall_file
, terlepas dari atributnya setelah
memulai ulang ke sistem baru tersebut. Perubahan pada atribut SELinux di sistem baru tidak akan
memengaruhi langkah pasca-penginstalan. Jika program pasca-penginstalan memerlukan izin tambahan, izin tersebut harus
ditambahkan ke konteks pasca-penginstalan.
Setelah mulai ulang
Setelah memulai ulang, update_verifier
akan memicu pemeriksaan integritas menggunakan dm-verity.
Pemeriksaan ini dimulai sebelum zygote untuk menghindari layanan Java membuat perubahan yang tidak dapat dikembalikan yang
akan mencegah rollback yang aman. Selama proses ini, bootloader dan kernel juga dapat memicu
mulai ulang jika booting terverifikasi atau dm-verity mendeteksi kerusakan. Setelah pemeriksaan selesai,
update_verifier
akan menandai bahwa booting berhasil.
update_verifier
hanya akan membaca blok yang tercantum dalam
/data/ota_package/care_map.txt
, yang disertakan dalam paket OTA A/B saat
menggunakan kode AOSP. Klien update sistem Java, seperti GmsCore, mengekstrak
care_map.txt
, menyiapkan izin akses sebelum memulai ulang perangkat, dan
menghapus file yang diekstrak setelah sistem berhasil melakukan booting ke versi baru.