Pembaruan sistem A/B (mulus).

Pembaruan sistem A/B, juga dikenal sebagai pembaruan tanpa batas, memastikan sistem booting yang bisa diterapkan tetap ada 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 kelas 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, reboot 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 mencoba pembaruan lagi.
  • Jika pembaruan OTA diterapkan tetapi gagal melakukan booting, perangkat akan melakukan boot ulang kembali ke partisi lama dan tetap dapat digunakan. Klien bebas untuk mencoba kembali pembaruan.
  • Kesalahan apa pun (seperti kesalahan I/O) hanya memengaruhi kumpulan 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 cukup ruang kosong untuk menyimpan paket pembaruan di /data atau /cache .
  • Partisi cache tidak lagi digunakan untuk menyimpan paket pembaruan OTA, sehingga tidak perlu memastikan bahwa partisi cache cukup besar untuk pembaruan di masa mendatang.
  • dm-verity menjamin perangkat akan mem-boot image 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 tidak memerlukan perubahan: paket pembaruan masih disajikan 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 namun harus menyediakan klien mereka sendiri.

Untuk OEM yang memasok klien mereka sendiri, klien perlu:

  • Putuskan kapan harus melakukan pembaruan. Karena pembaruan A/B terjadi di latar belakang, pembaruan tersebut tidak lagi dilakukan oleh pengguna. Agar tidak mengganggu pengguna, disarankan agar pembaruan dijadwalkan saat perangkat dalam mode pemeliharaan tidak aktif, seperti semalaman, dan menggunakan Wi-Fi. Namun, klien Anda dapat menggunakan heuristik apa pun yang Anda inginkan.
  • Periksa server paket OTA Anda dan tentukan apakah pembaruan tersedia. Ini sebagian besar harus sama dengan kode klien Anda yang ada, kecuali Anda ingin memberi sinyal bahwa perangkat mendukung A/B. (Klien Google juga menyertakan tombol Periksa sekarang agar pengguna dapat 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 instalasi ke server Anda, berdasarkan kode hasil update_engine . Jika pembaruan berhasil diterapkan, update_engine akan memberitahu bootloader untuk melakukan booting ke OS baru pada reboot berikutnya. Bootloader akan kembali ke OS lama jika OS baru gagal melakukan booting, sehingga tidak ada pekerjaan yang diperlukan dari klien. Jika pembaruan gagal, klien perlu memutuskan kapan (dan apakah) akan mencoba lagi, berdasarkan kode kesalahan terperinci. Misalnya, klien yang baik dapat mengenali bahwa paket OTA parsial ("diff") gagal dan sebagai gantinya mencoba paket OTA lengkap.

Secara opsional, klien dapat:

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

Di sisi sistem, pembaruan sistem A/B memengaruhi 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 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 sedang berjalan selama pengoperasian normal. Pendekatan ini membuat pembaruan tahan terhadap kesalahan dengan mempertahankan slot yang tidak digunakan sebagai cadangan: Jika kesalahan terjadi selama atau segera setelah pembaruan, sistem dapat melakukan rollback ke slot lama dan tetap memiliki sistem yang berfungsi. Untuk mencapai tujuan ini, partisi yang digunakan oleh slot saat ini tidak boleh 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 tersebut berisi sistem yang benar untuk melakukan booting pada perangkat. Slot saat ini dapat di-boot ketika sistem sedang berjalan, namun slot lainnya mungkin memiliki versi sistem yang lama (masih benar), versi yang lebih baru, atau data yang tidak valid. Terlepas dari slot apa yang ada saat ini , ada satu slot yang merupakan slot aktif (slot yang akan digunakan 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 melakukan booting, menjalankan, dan memperbarui dirinya sendiri. Slot yang dapat di-boot yang tidak ditandai sebagai berhasil (setelah beberapa kali mencoba melakukan booting dari slot tersebut) harus ditandai sebagai tidak dapat di-boot oleh pemuat boot, termasuk mengubah slot yang aktif ke slot yang dapat di-boot lainnya (biasanya ke slot yang berjalan segera sebelum upaya untuk melakukan booting). ke dalam yang baru dan aktif). Detail spesifik antarmuka ditentukan di boot_control.h .

Perbarui daemon mesin

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

  • Baca dari slot partisi A/B saat ini dan tulis data apa pun ke partisi slot A/B yang tidak digunakan 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 partisi slot yang tidak terpakai, seperti yang diinstruksikan oleh paket OTA. (Untuk detailnya, lihat Pasca-instalasi ).

Karena daemon update_engine tidak terlibat dalam proses boot itu sendiri, apa yang dapat dilakukannya selama pembaruan dibatasi oleh kebijakan dan fitur SELinux di slot saat ini (kebijakan dan fitur tersebut tidak dapat diperbarui hingga sistem melakukan booting ke sistem versi baru). Untuk menjaga 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 yang lebih lama, log update_engine dapat ditemukan di logcat dan laporan bug. Untuk membuat log update_engine tersedia di sistem file, tempelkan 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 /data/misc/update_engine_log/ . Pengguna dengan ID grup log akan dapat mengakses log sistem file.

Interaksi bootloader

boot_control HAL digunakan oleh update_engine (dan mungkin daemon lainnya) untuk menginstruksikan bootloader untuk melakukan booting. Contoh skenario 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, berhasil, dan aktif. Slot A ditandai sebagai tidak dapat di-boot karena konten slot A sedang diperbarui namun 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, namun slot A ditandai sebagai aktif (dan oleh karena itu ditandai sebagai dapat di-boot). Slot A belum ditandai sebagai berhasil dan sejumlah upaya untuk melakukan booting dari slot A harus dilakukan oleh bootloader.
  • Sistem di-boot ulang 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 melakukan 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 streaming A/B 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:

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

Kehidupan pembaruan A/B

Proses pembaruan dimulai ketika paket OTA (dalam kode disebut sebagai payload ) tersedia untuk diunduh. Kebijakan di perangkat dapat menunda pengunduhan muatan dan aplikasi berdasarkan tingkat 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 mungkin terganggu kapan saja karena kebijakan, boot ulang yang tidak terduga, atau tindakan pengguna.

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

Setelah payload tersedia, proses update adalah sebagai berikut:

Melangkah Kegiatan
1 Slot saat ini (atau "slot sumber") ditandai 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 meskipun komponen utama lainnya rusak (seperti UI dalam loop kerusakan) karena perangkat lunak baru dapat diterapkan untuk memperbaikinya. masalah.

Payload pembaruan adalah gumpalan buram dengan instruksi untuk memperbarui ke versi baru. Payload pembaruan terdiri dari berikut ini:
  • Metadata . Sebagian kecil dari muatan pembaruan, metadata berisi daftar operasi untuk menghasilkan dan memverifikasi versi baru pada slot target. Misalnya, suatu operasi dapat mendekompresi blob tertentu dan menulisnya ke blok tertentu di partisi target, atau membaca dari partisi sumber, menerapkan patch biner, dan menulis ke blok tertentu di partisi target.
  • Data tambahan . Sebagai bagian terbesar dari muatan pembaruan, data tambahan yang terkait dengan operasi terdiri dari blob terkompresi atau patch biner dalam contoh ini.
3 Metadata payload 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 akan 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 bukan berarti booting akan selesai. Bootloader (atau sistem itu sendiri) dapat mengalihkan kembali slot aktif jika tidak membaca status berhasil.
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 akan gagal.
9 Setelah sistem berhasil melakukan booting cukup jauh ke dalam slot baru dan menyelesaikan pemeriksaan pasca-reboot, slot yang sekarang ada (sebelumnya "slot target") ditandai 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 dipasang. Misalnya, jika program pasca-instal didefinisikan sebagai usr/bin/postinstall di partisi sistem, partisi dari slot yang tidak digunakan ini 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 mampu:

  • Pasang format sistem file baru . Jenis sistem file tidak dapat diubah kecuali ada dukungan untuk itu di kernel lama, termasuk rincian seperti algoritma kompresi yang digunakan jika menggunakan sistem file terkompresi (yaitu SquashFS).
  • Pahami format program pasca instalasi partisi baru . Jika menggunakan biner Executable and Linkable Format (ELF), biner tersebut harus kompatibel dengan kernel lama (misalnya program baru 64-bit yang berjalan pada kernel 32-bit lama jika arsitekturnya beralih dari build 32-bit ke 64-bit). Kecuali jika pemuat ( ld ) diinstruksikan untuk menggunakan jalur lain atau membuat biner statis, pustaka akan dimuat dari citra 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 #! penanda di atas), lalu atur jalur perpustakaan dari lingkungan baru untuk menjalankan program pasca-instalasi biner yang lebih kompleks. Alternatifnya, Anda dapat menjalankan langkah pasca-instalasi dari partisi khusus yang lebih kecil untuk memungkinkan format sistem file di partisi sistem utama diperbarui tanpa menimbulkan masalah kompatibilitas ke belakang atau pembaruan batu loncatan; ini akan memungkinkan pengguna untuk memperbarui langsung ke versi terbaru dari image pabrik.

Program pasca-instalasi baru dibatasi oleh kebijakan SELinux yang ditentukan dalam sistem lama. Dengan demikian, langkah pasca-instalasi cocok untuk melakukan tugas-tugas yang diperlukan oleh desain pada perangkat tertentu atau tugas-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 baru yang dipasang akan ditandai dengan postinstall_file , apa pun atributnya setelah reboot ke sistem baru tersebut. Perubahan pada atribut SELinux di sistem baru tidak akan mempengaruhi langkah pasca instalasi. Jika program pasca-instal memerlukan izin tambahan, izin tersebut harus ditambahkan ke konteks pasca-instalasi.

Setelah reboot

Setelah reboot, update_verifier memicu pemeriksaan integritas menggunakan dm-verity. Pemeriksaan ini dimulai sebelum zigot 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 terverifikasi 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 me-reboot perangkat, dan menghapus file yang diekstraksi setelah sistem berhasil melakukan booting ke versi baru.