OTA untuk perangkat non-A/B dengan partisi dinamis

Android 10 mendukung partisi dinamis, sistem partisi ruang pengguna yang dapat membuat, mengubah ukuran, dan menghancurkan partisi selama update over-the-air (OTA).

Halaman ini menjelaskan cara klien OTA mengubah ukuran partisi dinamis selama update untuk perangkat non-A/B.

Untuk perangkat non-A/B, update OTA untuk partisi dinamis diterapkan menggunakan updater di dalam paket update.

Update perangkat peluncuran

Bagian ini berlaku untuk perangkat non-A/B yang diluncurkan dengan dukungan partisi dinamis; perangkat ini diupgrade dari Android 10 ke rilis yang lebih tinggi.

Membuat paket update

Paket update OTA dibuat oleh skrip ota_from_target_files, yang terletak di build/make/tools/releasetools. Secara default, skrip menghasilkan paket yang mengupdate partisi system dan vendor. Jika ada partisi dinamis tambahan, seperti product, product_services, atau odm, update harus dibuat dalam kode khusus perangkat.

Untuk membuat update, di modul Python yang diperluas, terapkan FullOTA_GetBlockDifferences() dan IncrementalOTA_GetBlockDifferences(). Kedua fungsi ini menampilkan daftar objek BlockDifference, yang masing-masing menjelaskan patch update yang akan diterapkan pada partisi. Partisi yang ditampilkan oleh kedua fungsi ini tidak boleh diubah secara manual atau diverifikasi di tempat lain, misalnya di *_InstallBegin() atau *_InstallEnd().

Contoh pembuatan update:

# device/yoyodyne/tardis/releasetools.py

import os
from common import BlockDifference, EmptyImage, GetUserImage

# The joined list of user image partitions of source and target builds.
# - Items should be added to the list if new dynamic partitions are added.
# - Items should not be removed from the list even if dynamic partitions are
#   deleted. When generating an incremental OTA package, this script needs to
#   know that an image is present in source build but not in target build.
USERIMAGE_PARTITIONS = [
    "product",
    "odm",
]

def GetUserImages(input_tmp, input_zip):
  return {partition: GetUserImage(partition, input_tmp, input_zip)
          for partition in USERIMAGE_PARTITIONS
          if os.path.exists(os.path.join(input_tmp,
                                         "IMAGES", partition + ".img"))}

def FullOTA_GetBlockDifferences(info):
  images = GetUserImages(info.input_tmp, info.input_zip)
  return [BlockDifference(partition, image)
          for partition, image in images.items()]

def IncrementalOTA_GetBlockDifferences(info):
  source_images = GetUserImages(info.source_tmp, info.source_zip)
  target_images = GetUserImages(info.target_tmp, info.target_zip)

  # Use EmptyImage() as a placeholder for partitions that will be deleted.
  for partition in source_images:
    target_images.setdefault(partition, EmptyImage())

  # Use source_images.get() because new partitions are not in source_images.
  return [BlockDifference(partition, target_image, source_images.get(partition))
          for partition, target_image in target_images.items()]

Alur pembaruan

Di balik layar, fungsi berikut ditambahkan ke skrip edify:

  • unmap_partition(name)
    • Batalkan pemetaan partisi jika dipetakan. Jika tidak dipetakan, jangan lakukan apa pun.
    • Menampilkan string t jika berhasil, atau string kosong jika gagal.
  • map_partition(name)
    • Petakan partisi jika belum dipetakan.
    • Menampilkan jalur absolut perangkat blok yang dipetakan jika berhasil, atau string kosong jika gagal.
  • update_dynamic_partitions(op_list)
    • Terapkan daftar operasi yang ditentukan pada metadata partisi dinamis, dan batalkan pemetaan partisi jika diperlukan.
    • Menampilkan t jika berhasil, atau string kosong jika gagal.

Argumen op_list ke update_dynamic_partitions mengarah ke file dalam paket update. Setiap baris dalam file menentukan operasi. Jika operasi apa pun gagal, update_dynamic_partitions akan segera menampilkan string kosong. Operasinya adalah:

  • resize partition-name size
    • Batalkan pemetaan partisi, lalu ubah ukurannya menjadi size.
  • remove partition_name
    • Batalkan pemetaan partisi, lalu hapus.
  • add partition-name group-name
    • Menambahkan partisi baru ke grup yang ditentukan.
    • Batalkan jika grup tidak ada atau jika partisi sudah ada.
  • move partition-name group-name
    • Pindahkan partisi ke grup yang ditentukan.
    • Batalkan jika grup tidak ada atau partisi tidak ada.
  • add_group group-name maximum-size
    • Tambahkan grup dengan nama dan ukuran maksimum yang diberikan.
    • Batalkan jika grup sudah ada.
    • maximum_size 0 berarti tidak ada batas ukuran pada partisi dalam grup. Pengujian tambahan diperlukan untuk memastikan bahwa partisi dalam grup tidak melebihi ruang yang tersedia di perangkat.
  • resize_group group-name maximum-size
    • Ubah ukuran grup ke ukuran maksimum yang ditentukan.
    • Batalkan jika grup tidak ada.
    • maximum_size 0 berarti tidak ada batas ukuran pada partisi dalam grup. Pengujian tambahan diperlukan untuk memastikan partisi dalam grup tidak melebihi ruang yang tersedia di perangkat.
  • remove_group group-name
    • Menghapus grup.
    • Batalkan jika ada partisi dalam grup.
  • remove_all_groups
    • Hapus pemetaan semua partisi dari pemetaan perangkat.
    • Hapus semua partisi dan grup.

OTA Inkremental

Update OTA inkremental menggunakan logika berikut:

  1. Menyingkat partisi/menghapus partisi/memindahkan partisi keluar dari grup (sehingga ada cukup ruang untuk mengurangi grup)
  2. Memperkecil grup (sehingga ada cukup ruang untuk mengembangkan grup)
  3. Memperbesar grup (sehingga kita memiliki cukup ruang untuk memperbesar/menambahkan partisi)
  4. Meningkatkan partisi/menambahkan partisi/memindahkan partisi ke grup baru

Secara mendetail, update-script dihasilkan dengan logika ini:

for each shrinking partition:
    block_image_update(map_partition(name), …)

update_dynamic_partitions(op_list)

for each growing / adding partition:
    block_image_update(map_partition(name), …)

File op_list untuk update_dynamic_partitions dibuat dengan logika ini:

for each deleting partition:
    remove
for each partition that changes groups:
    move to "default"
for each shrinking partition:
    resize
for each shrinking / removing group:
    resize_group / remove_group
for each growing / adding group:
    resize_group / add_group
for each adding partition:
    add
for each growing / adding partition:
    resize
for each partition that changes groups:
    move to target group

OTA lengkap

Update OTA lengkap menggunakan logika berikut:

  1. Menghapus semua grup dan partisi yang ada
  2. Tambahkan grup
  3. Menambahkan partisi

Secara mendetail, update-script dibuat dengan logika ini:

update_dynamic_partitions(op_list)

for each adding partition:
    block_image_update(map_partition(name), …)

File op_list untuk update_dynamic_partitions dibuat dengan logika ini:

remove_all_groups
for each adding group:
    add_group
for each adding partition:
    add
for each adding partition:
    resize