OTA cho các thiết bị không phải A/B có phân vùng động

Android 10 hỗ trợ phân vùng động, một hệ thống phân vùng không gian người dùng có thể tạo, đổi kích thước và huỷ các phân vùng trong quá trình cập nhật qua mạng không dây (OTA).

Trang này mô tả cách ứng dụng OTA đổi kích thước phân vùng động trong quá trình cập nhật cho các thiết bị không phải A/B.

Đối với các thiết bị không phải A/B, bản cập nhật OTA cho các phân vùng động được áp dụng bằng cách sử dụng updater bên trong gói cập nhật.

Cập nhật thiết bị phát hành

Phần này áp dụng cho các thiết bị không phải A/B khởi chạy với tính năng hỗ trợ phân vùng động; các thiết bị này nâng cấp từ Android 10 lên các bản phát hành cao hơn.

Tạo gói cập nhật

Gói cập nhật OTA được tạo bằng tập lệnh ota_from_target_files, nằm trong build/make/tools/releasetools. Theo mặc định, tập lệnh sẽ tạo một gói cập nhật các phân vùng systemvendor. Nếu có các phân vùng động bổ sung, chẳng hạn như product, product_services hoặc odm, thì các bản cập nhật của các phân vùng đó phải được tạo trong mã dành riêng cho thiết bị.

Để tạo bản cập nhật, trong mô-đun Python mở rộng, hãy triển khai FullOTA_GetBlockDifferences()IncrementalOTA_GetBlockDifferences(). Hai hàm này trả về một danh sách đối tượng BlockDifference, mỗi hàm mô tả bản vá cập nhật sẽ được áp dụng trên một phân vùng. Bạn không nên sửa đổi thủ công hoặc xác minh phân vùng do 2 hàm này trả về ở nơi khác, ví dụ như trong *_InstallBegin() hoặc *_InstallEnd().

Ví dụ về việc tạo bản cập nhật:

# 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()]

Cập nhật quy trình

Ở chế độ nền, các hàm sau đây được thêm vào tập lệnh edify:

  • unmap_partition(name)
    • Huỷ liên kết phân vùng nếu đã liên kết, nếu không, không làm gì cả.
    • Trả về chuỗi t khi thành công hoặc một chuỗi trống khi không thành công.
  • map_partition(name)
    • Liên kết phân vùng nếu chưa liên kết.
    • Trả về đường dẫn tuyệt đối của thiết bị khối được liên kết khi thành công hoặc một chuỗi trống khi không thành công.
  • update_dynamic_partitions(op_list)
    • Áp dụng danh sách thao tác đã cho trên siêu dữ liệu phân vùng động, huỷ liên kết các phân vùng nếu cần.
    • Trả về t khi thành công hoặc một chuỗi trống khi không thành công.

Đối số op_list cho update_dynamic_partitions trỏ đến một tệp trong gói cập nhật. Mỗi dòng trong tệp chỉ định một thao tác. Nếu bất kỳ thao tác nào không thành công, update_dynamic_partitions sẽ ngay lập tức trả về một chuỗi trống. Các phép toán là:

  • resize partition-name size
    • Huỷ ánh xạ phân vùng, sau đó đổi kích thước thành size.
  • remove partition_name
    • Huỷ liên kết phân vùng, sau đó xoá phân vùng đó.
  • add partition-name group-name
    • Thêm một phân vùng mới vào nhóm đã chỉ định.
    • Huỷ nếu nhóm không tồn tại hoặc nếu phân vùng đã tồn tại.
  • move partition-name group-name
    • Di chuyển phân vùng sang nhóm đã chỉ định.
    • Huỷ nếu nhóm hoặc phân vùng không tồn tại.
  • add_group group-name maximum-size
    • Thêm một nhóm có tên và kích thước tối đa đã cho.
    • Huỷ nếu nhóm đã tồn tại.
    • maximum_size bằng 0 có nghĩa là không có giới hạn về kích thước đối với các phân vùng trong nhóm. Bạn cần kiểm thử thêm để đảm bảo rằng các phân vùng trong nhóm không vượt quá dung lượng có sẵn trên thiết bị.
  • resize_group group-name maximum-size
    • Đổi kích thước nhóm thành kích thước tối đa đã cho.
    • Huỷ nếu nhóm không tồn tại.
    • maximum_size bằng 0 có nghĩa là không có giới hạn về kích thước đối với các phân vùng trong nhóm. Bạn cần kiểm thử thêm để đảm bảo rằng các phân vùng trong nhóm không vượt quá dung lượng có sẵn trên thiết bị.
  • remove_group group-name
    • Xoá nhóm.
    • Huỷ nếu có các phân vùng trong nhóm.
  • remove_all_groups
    • Huỷ liên kết tất cả các phân vùng khỏi trình liên kết thiết bị.
    • Xoá tất cả các phân vùng và nhóm.

OTA gia tăng

Bản cập nhật OTA tăng dần sử dụng logic sau:

  1. Rút gọn các phân vùng/xoá các phân vùng/chuyển các phân vùng ra khỏi nhóm (để có đủ dung lượng rút gọn các nhóm)
  2. Rút gọn nhóm (để có đủ không gian phát triển nhóm)
  3. Mở rộng nhóm (để chúng ta có đủ không gian mở rộng/thêm phân vùng)
  4. Mở rộng phân vùng/thêm phân vùng/chuyển phân vùng sang nhóm mới

Cụ thể, update-script được tạo bằng logic sau:

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), …)

Tệp op_list cho update_dynamic_partitions được tạo bằng logic sau:

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 đầy đủ

Bản cập nhật OTA đầy đủ sử dụng logic sau:

  1. Xoá tất cả các nhóm và phân vùng hiện có
  2. Thêm nhóm
  3. Thêm phân vùng

Chi tiết, update-script được tạo bằng logic sau:

update_dynamic_partitions(op_list)

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

Tệp op_list cho update_dynamic_partitions được tạo bằng logic sau:

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