Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Pembaruan Sistem A/B (Seamless)

Pembaruan sistem A/B, juga dikenal sebagai pembaruan mulus, memastikan sistem boot yang dapat diterapkan tetap berada di disk selama pembaruan over-the-air (OTA) . Pendekatan ini mengurangi kemungkinan perangkat tidak aktif setelah pembaruan, yang berarti lebih sedikit penggantian perangkat dan reflash perangkat di pusat perbaikan dan garansi. Sistem operasi tingkat komersial lainnya seperti ChromeOS juga berhasil menggunakan pembaruan A/B.

Untuk informasi selengkapnya tentang pembaruan sistem A/B dan cara kerjanya, lihat Pemilihan partisi (slot) .

Pembaruan sistem A/B memberikan manfaat berikut:

  • Pembaruan OTA dapat terjadi saat sistem sedang berjalan, tanpa mengganggu pengguna. Pengguna dapat terus menggunakan perangkat mereka selama OTA—satu-satunya waktu henti selama pembaruan adalah saat perangkat melakukan boot ulang ke partisi disk yang diperbarui.
  • Setelah pembaruan, boot ulang tidak lebih lama dari reboot 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 memperbarui kembali.
  • Jika pembaruan OTA diterapkan tetapi gagal melakukan booting, perangkat akan melakukan reboot kembali ke partisi lama dan tetap dapat digunakan. Klien bebas untuk mencoba kembali pembaruan.
  • Kesalahan apa pun (seperti kesalahan I/O) hanya memengaruhi set partisi yang tidak digunakan dan dapat dicoba lagi. Kesalahan seperti itu juga menjadi lebih kecil kemungkinannya karena beban I/O sengaja dibuat rendah untuk menghindari penurunan pengalaman pengguna.
  • Pembaruan dapat dialirkan ke perangkat A/B, menghilangkan kebutuhan untuk mengunduh paket sebelum menginstalnya. Streaming berarti pengguna tidak perlu memiliki ruang kosong yang cukup untuk menyimpan paket pembaruan di /data atau /cache .
  • Partisi cache tidak lagi digunakan untuk menyimpan paket pembaruan OTA, jadi tidak perlu memastikan bahwa partisi cache cukup besar untuk pembaruan di masa mendatang.
  • dm-verity menjamin perangkat akan mem-boot gambar yang tidak rusak. Jika perangkat tidak bisa boot karena masalah OTA atau dm-verity yang buruk, perangkat dapat melakukan boot ulang ke image lama. ( Boot Terverifikasi Android tidak memerlukan pembaruan A/B.)

Tentang pembaruan sistem A/B

Pembaruan A/B memerlukan perubahan pada klien dan sistem. Namun, server paket OTA seharusnya tidak memerlukan perubahan: paket pembaruan masih dilayani 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 memasok klien mereka sendiri, klien perlu:

  • Putuskan kapan akan mengambil pembaruan. Karena pembaruan A/B terjadi di latar belakang, pembaruan tersebut tidak lagi dimulai oleh pengguna. Untuk menghindari gangguan pada pengguna, sebaiknya pembaruan dijadwalkan saat perangkat dalam mode pemeliharaan tidak aktif, seperti semalaman, dan pada Wi-Fi. Namun, klien Anda dapat menggunakan heuristik apa pun yang Anda inginkan.
  • Periksa dengan server paket OTA Anda dan tentukan apakah pembaruan tersedia. Ini sebagian besar harus sama dengan kode klien Anda yang ada, kecuali bahwa Anda ingin memberi sinyal bahwa perangkat mendukung A/B. (Klien Google juga menyertakan tombol Periksa sekarang bagi pengguna untuk memeriksa pembaruan terkini.)
  • Panggil update_engine dengan URL HTTPS untuk paket pembaruan Anda, dengan asumsi tersedia. update_engine akan memperbarui blok mentah pada partisi yang saat ini tidak digunakan saat mengalirkan paket pembaruan.
  • Laporkan keberhasilan atau kegagalan pemasangan ke server Anda, berdasarkan kode hasil update_engine . Jika pembaruan berhasil diterapkan, update_engine akan memberi tahu bootloader untuk boot ke OS baru pada reboot berikutnya. Bootloader akan mundur ke OS lama jika OS baru gagal melakukan booting, jadi klien tidak perlu bekerja. Jika pembaruan gagal, klien harus memutuskan kapan (dan apakah) akan mencoba lagi, berdasarkan kode kesalahan terperinci. Misalnya, klien yang baik dapat mengenali bahwa paket OTA parsial ("berbeda") gagal dan mencoba paket OTA lengkap sebagai gantinya.

Secara opsional, klien dapat:

  • Tampilkan notifikasi yang meminta pengguna untuk reboot. Jika Anda ingin menerapkan kebijakan yang mendorong pengguna untuk memperbarui secara rutin, notifikasi ini dapat ditambahkan ke klien Anda. Jika klien tidak meminta pengguna, maka pengguna akan mendapatkan pembaruan saat mereka melakukan booting ulang. (Klien Google memiliki penundaan yang dapat dikonfigurasi per pembaruan.)
  • Tampilkan pemberitahuan yang memberi tahu pengguna apakah mereka melakukan boot ke versi OS baru atau apakah mereka diharapkan melakukannya tetapi kembali ke versi OS lama. (Klien Google biasanya tidak melakukan keduanya.)

Di sisi sistem, pembaruan sistem A/B memengaruhi hal-hal berikut:

  • Pemilihan partisi (slot), daemon update_engine , dan interaksi bootloader (dijelaskan di bawah)
  • Proses pembuatan dan pembuatan paket pembaruan OTA (dijelaskan dalam Menerapkan Pembaruan A/B )

Pemilihan partisi (slot)

Pembaruan sistem A/B menggunakan dua set partisi yang disebut sebagai slot (biasanya slot A dan slot B). Sistem berjalan dari slot saat ini sementara partisi di slot yang tidak digunakan tidak diakses oleh sistem yang sedang berjalan selama operasi normal. Pendekatan ini membuat pembaruan tahan terhadap kesalahan dengan mempertahankan slot yang tidak digunakan sebagai cadangan: Jika terjadi kesalahan selama atau segera setelah pembaruan, sistem dapat kembali ke slot lama dan terus memiliki sistem yang berfungsi. Untuk mencapai tujuan ini, tidak ada partisi yang digunakan oleh slot saat ini yang harus diperbarui sebagai bagian dari pembaruan OTA (termasuk partisi yang hanya memiliki satu salinan).

Setiap slot memiliki atribut yang dapat di-boot yang menyatakan apakah slot berisi sistem yang benar dari mana perangkat dapat melakukan booting. Slot saat ini dapat di-boot saat sistem sedang berjalan, tetapi slot lainnya mungkin memiliki versi sistem yang lama (masih benar), versi yang lebih baru, atau data yang tidak valid. Terlepas dari apa slot saat ini , ada satu slot yang merupakan slot aktif (yang akan di-boot oleh bootloader pada boot berikutnya) atau slot pilihan .

Setiap slot juga memiliki atribut sukses yang ditetapkan oleh ruang pengguna, yang hanya relevan jika slot tersebut juga dapat di-boot. Slot yang berhasil harus dapat mem-boot, menjalankan, dan memperbarui sendiri. Slot yang dapat di-boot yang tidak ditandai sebagai berhasil (setelah beberapa upaya dilakukan untuk mem-boot darinya) harus ditandai sebagai tidak dapat di-boot oleh bootloader, termasuk mengubah slot yang aktif ke slot yang dapat di-boot lainnya (biasanya ke slot yang berjalan segera sebelum upaya untuk mem-boot ke yang baru, yang aktif). Detail spesifik antarmuka ditentukan dalam boot_control.h .

Perbarui daemon mesin

Pembaruan sistem A/B menggunakan daemon latar belakang yang disebut update_engine untuk mempersiapkan sistem melakukan boot ke versi baru yang diperbarui. Daemon ini dapat melakukan tindakan berikut:

  • Baca dari partisi A/B slot saat ini dan tulis data apa pun ke partisi A/B slot yang tidak terpakai seperti yang diinstruksikan oleh paket OTA.
  • Panggil antarmuka boot_control dalam alur kerja yang telah ditentukan sebelumnya.
  • Jalankan program pasca-instalasi dari partisi baru setelah menulis semua slot partisi yang tidak terpakai, seperti yang diinstruksikan oleh paket OTA. (Untuk detailnya, lihat Pasca-pemasangan ).

Karena daemon update_engine tidak terlibat dalam proses booting itu sendiri, ia terbatas pada apa yang dapat dilakukannya selama pembaruan oleh kebijakan dan fitur SELinux di slot saat ini (kebijakan dan fitur tersebut tidak dapat diperbarui hingga sistem melakukan booting ke versi baru). Untuk mempertahankan sistem yang kuat, proses pembaruan tidak boleh mengubah tabel partisi, konten partisi di slot saat ini, atau konten partisi non-A/B yang tidak dapat dihapus dengan reset pabrik.

Perbarui sumber mesin

Sumber update_engine terletak di system/update_engine . File dexopt A/B OTA dibagi antara installd dan manajer paket:

Untuk contoh yang berfungsi, lihat /device/google/marlin/device-common.mk .

Perbarui log mesin

Untuk rilis Android 8.x dan sebelumnya, log update_engine dapat ditemukan di logcat dan di laporan bug. Agar log update_engine tersedia di sistem file, tambal perubahan berikut ke dalam 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 bawah /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 lain) untuk menginstruksikan bootloader dari mana boot. Skenario contoh umum dan status terkaitnya mencakup hal berikut:

  • Kasus normal : Sistem berjalan dari slotnya saat ini, baik slot A atau B. Sejauh ini belum ada pembaruan yang diterapkan. Slot sistem saat ini dapat di-boot, berhasil, dan slot aktif.
  • Pembaruan sedang berlangsung : Sistem berjalan dari slot B, jadi slot B adalah slot yang dapat di-boot, sukses, dan aktif. Slot A ditandai sebagai tidak dapat di-boot karena konten slot A sedang diperbarui tetapi belum selesai. Reboot dalam keadaan ini harus melanjutkan booting dari slot B.
  • Pembaruan diterapkan, reboot tertunda : Sistem berjalan dari slot B, slot B dapat di-boot dan berhasil, tetapi slot A ditandai sebagai aktif (dan karenanya ditandai sebagai dapat di-boot). Slot A belum ditandai sebagai berhasil dan sejumlah percobaan untuk boot dari slot A harus dilakukan oleh bootloader.
  • Sistem di-reboot ke pembaruan baru : Sistem berjalan dari slot A untuk pertama kalinya, slot B masih dapat di-boot dan berhasil sedangkan slot A hanya dapat di-boot, dan masih aktif tetapi tidak berhasil. Daemon ruang pengguna, update_verifier , harus menandai slot A sebagai berhasil setelah beberapa pemeriksaan dilakukan.

Dukungan pembaruan streaming

Perangkat pengguna tidak selalu memiliki cukup ruang di /data untuk mengunduh paket pembaruan. Karena baik OEM maupun pengguna tidak ingin membuang ruang pada partisi /cache , beberapa pengguna tidak memiliki pembaruan karena perangkat tidak memiliki tempat untuk menyimpan paket pembaruan. Untuk mengatasi masalah ini, Android 8.0 menambahkan dukungan untuk streaming pembaruan A/B yang menulis blok langsung ke partisi B saat diunduh, tanpa harus menyimpan blok di /data . Pembaruan A/B streaming hampir tidak memerlukan penyimpanan sementara dan hanya memerlukan penyimpanan yang cukup untuk sekitar 100 KiB metadata.

Untuk mengaktifkan pembaruan streaming di Android 7.1, pilih patch berikut:

Tambalan ini diperlukan untuk mendukung streaming pembaruan A/B di Android 7.1 dan yang lebih baru baik menggunakan Google Mobile Services (GMS) atau klien pembaruan lainnya.

Kehidupan pembaruan A/B

Proses pembaruan dimulai saat paket OTA (disebut dalam kode sebagai payload ) tersedia untuk diunduh. Kebijakan di perangkat dapat menunda pengunduhan muatan dan aplikasi berdasarkan level baterai, aktivitas pengguna, status pengisian daya, atau kebijakan lainnya. Selain itu, karena pembaruan berjalan di latar belakang, pengguna mungkin tidak mengetahui bahwa pembaruan sedang berlangsung. Semua ini berarti proses pembaruan dapat terganggu kapan saja karena kebijakan, reboot yang tidak terduga, atau tindakan pengguna.

Opsional, metadata dalam paket OTA itu sendiri menunjukkan pembaruan dapat dialirkan; paket yang sama juga dapat digunakan untuk instalasi non-streaming. Server dapat menggunakan metadata untuk memberi tahu klien bahwa itu streaming sehingga klien akan menyerahkan OTA ke update_engine dengan benar. Pabrikan perangkat dengan server dan klien mereka sendiri dapat mengaktifkan pembaruan streaming dengan memastikan server mengidentifikasi bahwa pembaruan sedang streaming (atau menganggap semua pembaruan sedang streaming) dan klien melakukan panggilan yang benar ke update_engine untuk streaming. Pabrikan dapat menggunakan fakta bahwa paket tersebut adalah varian streaming untuk mengirim tanda ke klien guna memicu penyerahan ke sisi kerangka kerja sebagai streaming.

Setelah payload tersedia, proses pembaruan adalah sebagai berikut:

Melangkah Kegiatan
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-boot dengan memanggil fungsi setSlotAsUnbootable() . Slot saat ini selalu ditandai sebagai berhasil di awal pembaruan untuk mencegah bootloader kembali ke slot yang tidak digunakan, yang akan segera memiliki data yang tidak valid. Jika sistem telah mencapai titik di mana ia dapat mulai menerapkan pembaruan, slot saat ini ditandai sebagai berhasil bahkan jika komponen utama lainnya rusak (seperti UI dalam crash loop) karena dimungkinkan untuk mendorong perangkat lunak baru untuk memperbaikinya. masalah.

Muatan pembaruan adalah gumpalan buram dengan petunjuk untuk memperbarui ke versi baru. Muatan pembaruan terdiri dari berikut ini:
  • Metadata . Porsi muatan pembaruan yang relatif kecil, metadata berisi daftar operasi untuk menghasilkan dan memverifikasi versi baru pada slot target. Misalnya, sebuah operasi dapat mendekompres gumpalan tertentu dan menuliskannya ke blok tertentu di partisi target, atau membaca dari partisi sumber, menerapkan tambalan biner, dan menulis ke blok tertentu di partisi target.
  • Data ekstra . Sebagai bagian terbesar dari payload update, data tambahan yang terkait dengan operasi terdiri dari blob terkompresi atau tambalan biner dalam contoh ini.
3 Metadata muatan diunduh.
4 Untuk setiap operasi yang ditentukan dalam metadata, secara berurutan, data terkait (jika ada) diunduh ke memori, operasi diterapkan, dan memori terkait dibuang.
5 Seluruh partisi dibaca ulang dan diverifikasi terhadap hash yang diharapkan.
6 Langkah pasca-instalasi (jika ada) dijalankan. Jika terjadi kesalahan selama pelaksanaan langkah apa pun, pembaruan gagal dan dicoba kembali dengan muatan yang mungkin berbeda. Jika semua langkah sejauh ini berhasil, pembaruan berhasil dan langkah terakhir dijalankan.
7 Slot yang tidak digunakan ditandai sebagai aktif dengan memanggil setActiveBootSlot() . Menandai slot yang tidak terpakai sebagai aktif tidak berarti akan menyelesaikan booting. Bootloader (atau sistem itu sendiri) dapat mengganti slot aktif kembali jika tidak membaca status sukses.
8 Pasca-instalasi (dijelaskan di bawah) melibatkan menjalankan program dari versi "pembaruan baru" sambil tetap berjalan di versi lama. Jika ditentukan dalam paket OTA, langkah ini wajib dan program harus kembali dengan kode keluar 0 ; jika tidak, pembaruan gagal.
9 Setelah sistem berhasil mem-boot cukup jauh ke slot baru dan menyelesaikan pemeriksaan pasca-reboot, slot yang sekarang aktif (sebelumnya "slot target") ditandai sebagai berhasil dengan memanggil markBootSuccessful() .

Pasca-instalasi

Untuk setiap partisi di mana langkah pasca-instalasi ditentukan, update_engine memasang partisi baru ke lokasi tertentu dan menjalankan program yang ditentukan dalam OTA relatif terhadap partisi yang terpasang. Misalnya, jika program post-install didefinisikan sebagai usr/bin/postinstall di partisi sistem, partisi ini dari slot yang tidak terpakai akan dipasang di lokasi tetap (seperti /postinstall_mount ) dan /postinstall_mount/usr/bin/postinstall perintah /postinstall_mount/usr/bin/postinstall dijalankan.

Agar pasca-instalasi berhasil, kernel lama harus dapat:

  • Pasang format sistem file baru . Jenis sistem file tidak dapat diubah kecuali ada dukungan untuk itu di kernel lama, termasuk detail seperti algoritme kompresi yang digunakan jika menggunakan sistem file terkompresi (yaitu SquashFS).
  • Pahami format program pasca-pemasangan partisi baru . Jika menggunakan biner Executable and Linkable Format (ELF), itu harus kompatibel dengan kernel lama (misalnya program baru 64-bit yang berjalan pada kernel 32-bit lama jika arsitektur beralih dari versi 32-ke 64-bit). Kecuali pemuat ( ld ) diinstruksikan untuk menggunakan jalur lain atau membangun biner statis, pustaka akan dimuat dari gambar sistem lama dan bukan yang baru.

Misalnya, Anda dapat menggunakan skrip shell sebagai program pasca-instalasi yang diinterpretasikan oleh biner shell sistem lama dengan tanda #! marker di bagian atas), lalu atur jalur pustaka dari lingkungan baru untuk menjalankan program pasca-pemasangan biner yang lebih kompleks. Alternatifnya, Anda dapat menjalankan langkah pasca-instalasi dari partisi khusus yang lebih kecil untuk mengaktifkan format sistem file di partisi sistem utama untuk diperbarui tanpa menimbulkan masalah kompatibilitas mundur atau pembaruan batu loncatan; ini akan memungkinkan pengguna untuk memperbarui langsung ke versi terbaru dari gambar pabrik.

Program pasca-pemasangan baru dibatasi oleh kebijakan SELinux yang ditentukan dalam sistem lama. Dengan demikian, langkah pasca-instalasi cocok untuk melakukan tugas yang diperlukan oleh desain pada perangkat tertentu atau tugas upaya terbaik lainnya (yaitu memperbarui firmware atau bootloader berkemampuan A/B, menyiapkan salinan database untuk versi baru, dll. ). Langkah pasca-instalasi tidak cocok untuk perbaikan bug satu kali sebelum reboot yang memerlukan izin tak terduga.

Program pasca-instalasi yang dipilih berjalan dalam konteks postinstall SELinux. Semua file di partisi yang dipasang baru akan diberi tag postinstall_file , terlepas dari apa atributnya setelah mem-boot ulang ke sistem baru itu. Perubahan pada atribut SELinux di sistem baru tidak akan memengaruhi langkah pasca pemasangan. Jika program pasca-instalasi memerlukan izin tambahan, itu harus ditambahkan ke konteks pasca-instalasi.

Setelah reboot

Setelah mem-boot ulang, update_verifier memicu pemeriksaan integritas menggunakan dm-verity. Pemeriksaan ini dimulai sebelum zygote untuk menghindari layanan Java membuat perubahan yang tidak dapat diubah yang akan mencegah rollback yang aman. Selama proses ini, bootloader dan kernel juga dapat memicu reboot jika boot yang diverifikasi atau dm-verity mendeteksi adanya kerusakan. Setelah pemeriksaan selesai, update_verifier menandai boot berhasil.

update_verifier hanya akan membaca blok yang terdaftar di /data/ota_package/care_map.txt , yang disertakan dalam paket A/B OTA saat menggunakan kode AOSP. Klien pembaruan sistem Java, seperti GmsCore, mengekstrak care_map.txt , menyiapkan izin akses sebelum mem-boot ulang perangkat, dan menghapus file yang diekstraksi setelah sistem berhasil melakukan booting ke versi baru.