Triển khai A/B cập nhật

OEM và nhà cung cấp SoC muốn triển khai bản cập nhật hệ thống A/B phải đảm bảo trình tải khởi động của họ triển khai HAL boot_control và chuyển các tham số chính xác đến hàm nhân hệ điều hành.

Triển khai HAL điều khiển khởi động

Trình tải khởi động hỗ trợ A/B phải triển khai HAL boot_control tại hardware/libhardware/include/hardware/boot_control.h Bạn có thể kiểm thử các triển khai bằng cách sử dụng system/extras/bootctl phần mềm tiện ích và system/extras/tests/bootloader/

Bạn cũng phải triển khai máy trạng thái như dưới đây:

Hình 1. Máy trạng thái trình tải khởi động

Thiết lập nhân

Cách triển khai cập nhật hệ thống A/B:

  1. Chọn loạt bản vá kernel sau đây (nếu cần):
  2. Đảm bảo các đối số dòng lệnh hạt nhân chứa các đối số bổ sung sau:
    skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
    ... trong đó giá trị <public-key-id> là mã nhận dạng của khoá công khai dùng để xác minh chữ ký bảng xác thực (để biết chi tiết, hãy xem dm-verity).
  3. Thêm chứng chỉ .X509 chứa khoá công khai vào quy trình khoá hệ thống:
    1. Sao chép chứng chỉ .X509 có định dạng .der vào thư mục gốc của Thư mục kernel. Nếu chứng chỉ .X509 được định dạng là .pem, hãy dùng lệnh openssl sau để chuyển đổi từ Định dạng từ .pem sang .der:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Tạo zImage để đưa chứng chỉ vào quá trình khoá hệ thống. Để xác minh,hãy kiểm tra mục nhập procfs (yêu cầu KEYS_CONFIG_DEBUG_PROC_KEYS sẽ được bật):
      angler:/# cat /proc/keys
      
      1c8a217e I------     1 perm 1f010000     0     0 asymmetri
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------     1 perm 1f030000     0     0 keyring
      .system_keyring: 1/4
      Khi chứng chỉ .X509 được thêm vào thành công, chứng chỉ này cho biết có khoá công khai trong quy trình khoá hệ thống (dấu đánh dấu biểu thị mã khoá công khai).
    3. Thay thế dấu cách bằng # rồi truyền dưới dạng <public-key-id> trong dòng lệnh của nhân. Ví dụ: chuyển Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f thay cho <public-key-id>

Đặt biến bản dựng

Trình tải khởi động hỗ trợ A/B phải đáp ứng các tiêu chí sau đây về biến bản dựng:

Phải xác định cho mục tiêu A/B
  • AB_OTA_UPDATER := true

  • AB_OTA_PARTITIONS := \
      boot \
      system \
      vendor và các phân vùng khác được cập nhật thông qua update_engine (radio, trình tải khởi động, etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
Ví dụ: tham khảo /device/google/marlin/+/android-7.1.0_r1/device-common.mk Bạn có thể tuỳ ý tiến hành bước dex2oat sau khi cài đặt (nhưng khởi động lại trước) theo mô tả trong Biên dịch.
Rất nên dùng cho mục tiêu A/B
  • Định nghĩa TARGET_NO_RECOVERY := true
  • Định nghĩa BOARD_USES_RECOVERY_AS_BOOT := true
  • Không xác định BOARD_RECOVERYIMAGE_PARTITION_SIZE
Không thể xác định cho mục tiêu A/B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
Không bắt buộc đối với bản gỡ lỗi PRODUCT_PACKAGES_DEBUG += update_engine_client

Đặt phân vùng (ô)

Thiết bị A/B không cần phân vùng khôi phục hoặc phân vùng bộ nhớ đệm vì Android không còn sử dụng các phân vùng này. Phân vùng dữ liệu hiện được dùng cho gói OTA đã tải xuống, và mã hình ảnh khôi phục nằm trên phân vùng khởi động. Bạn phải đặt tên cho tất cả các phân vùng là A/B-ed như sau (ô luôn được đặt tên là a, b, v.v.): boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.

Bộ nhớ đệm

Đối với các bản cập nhật không phải A/B, phân vùng bộ nhớ đệm được dùng để lưu trữ các gói OTA đã tải xuống và để lưu trữ tạm thời bị chặn trong khi áp dụng bản cập nhật. Cách tốt nhất để định kích thước bộ nhớ đệm phân vùng: kích thước cần thiết phụ thuộc vào những nội dung cập nhật bạn muốn áp dụng. Kém nhất trường hợp sẽ là phân vùng bộ nhớ đệm lớn bằng hình ảnh hệ thống. Khi áp dụng tính năng cập nhật A/B, bạn không cần để lưu trữ các khối (vì bạn luôn ghi vào một phân vùng hiện không được sử dụng) và khi phát trực tiếp A/B, bạn không cần tải toàn bộ gói OTA trước khi áp dụng.

Khôi phục

Đĩa RAM khôi phục hiện được chứa trong tệp boot.img. Khi truy cập vào khôi phục, trình tải khởi động không thể đặt tuỳ chọn skip_initramfs vào dòng lệnh kernel.

Đối với các bản cập nhật không theo A/B, phân vùng khôi phục chứa mã dùng để áp dụng các bản cập nhật. A/B các bản cập nhật được áp dụng bằng update_engine chạy trong hình ảnh hệ thống thông thường được khởi động. Vẫn còn một chế độ khôi phục dùng để triển khai việc đặt lại dữ liệu về trạng thái ban đầu và cài đặt bản cập nhật không qua cửa hàng ứng dụng (chính là nguồn gốc của tên "khôi phục"). Mã và dữ liệu cho chế độ khôi phục được lưu trữ trong phân vùng khởi động thông thường trong ramdisk; khởi động vào hình ảnh hệ thống, trình tải khởi động yêu cầu nhân hệ điều hành bỏ qua ổ đĩa ram (nếu không, thiết bị sẽ khởi động vào quy trình khôi phục . Chế độ khôi phục nhỏ (và phần lớn chế độ đã nằm trên phân vùng khởi động), vì vậy việc khởi động không tăng kích thước.

Fstab

Đối số slotselect phải nằm trên dòng cho A/B-ed phân vùng. Ví dụ:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

Không nên đặt tên cho phân vùng nào là vendor. Thay vào đó, hãy phân vùng vendor_a hoặc vendor_b sẽ được chọn và gắn trên điểm gắn /vendor.

Đối số khe nhân

Hậu tố vị trí hiện tại phải được chuyển thông qua một nút cây thiết bị (DT) cụ thể (/firmware/android/slot_suffix) hoặc thông qua dòng lệnh nhân hệ điều hành androidboot.slot_suffix hoặc đối số bootconfig.

Theo mặc định, chế độ khởi động nhanh sẽ cài đặt ROM khe hiện tại trên thiết bị A/B. Nếu gói cập nhật cũng chứa hình ảnh cho vị trí khác, không phải hiện tại, tính năng khởi động nhanh cũng sẽ nhấp nháy những hình ảnh đó. Các lựa chọn hiện có bao gồm:

  • --slot SLOT. Ghi đè hành vi mặc định và lời nhắc khởi động nhanh để cài đặt ROM khe được chuyển vào dưới dạng một đối số.
  • --set-active [SLOT]. Đặt vùng quảng cáo ở trạng thái đang hoạt động. Nếu không có đối số không bắt buộc được chỉ định, khi đó vị trí hiện tại sẽ được đặt thành đang hoạt động.
  • fastboot --help. Xem thông tin chi tiết về các lệnh.

Nếu trình tải khởi động triển khai tính năng khởi động nhanh, thì trình tải này sẽ hỗ trợ lệnh set_active <slot> đặt vùng đang hoạt động thành vùng nhất định ( cũng phải xoá cờ không thể khởi động cho vị trí đó và đặt lại số lần thử lại về mặc định giá trị). Trình tải khởi động cũng phải hỗ trợ các biến sau:

  • has-slot:<partition-base-name-without-suffix>. Trả về "yes" nếu giá trị cho trước phân vùng hỗ trợ khe cắm, nếu không thì "không".
  • current-slot. Trả về hậu tố vị trí sẽ được khởi động tiếp theo.
  • slot-count. Trả về một số nguyên đại diện cho số ô trống. Hiện có 2 vị trí được hỗ trợ nên giá trị này là 2.
  • slot-successful:<slot-suffix>. Trả về "yes" nếu vị trí nhất định đã được được đánh dấu là khởi động thành công, "no" nếu không.
  • slot-unbootable:<slot-suffix>. Trả về "yes" nếu ô đã cho được đánh dấu là không thể khởi động, "không" nếu không.
  • slot-retry-count:<slot-suffix>. Số lần thử lại còn lại để thử khởi động khe đã cho.

Để xem tất cả các biến, hãy chạy fastboot getvar all.

Tạo gói OTA

Công cụ đóng gói OTA tuân theo các lệnh tương tự như cho các thiết bị không phải A/B. Tệp target_files.zip phải được tạo bởi xác định các biến bản dựng cho mục tiêu A/B. Các công cụ đóng gói OTA tự động xác định và tạo các gói ở định dạng cho trình cập nhật A/B.

Ví dụ:

  • Cách tạo một OTA đầy đủ:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • Cách tạo một OTA gia tăng:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

Định cấu hình phân vùng

update_engine có thể cập nhật bất kỳ cặp phân vùng A/B nào được xác định trong cùng một ổ đĩa. Một cặp phân vùng có một tiền tố chung (chẳng hạn như system hoặc boot) và hậu tố mỗi ô (chẳng hạn như _a). Danh sách các phân vùng mà tải trọng trình tạo xác định bản cập nhật được định cấu hình bằng biến make AB_OTA_PARTITIONS.

Ví dụ: nếu một cặp phân vùng bootloader_abooloader_b được đưa vào (_a_b là ô trống hậu tố), bạn có thể cập nhật các phân vùng này bằng cách chỉ định thông tin sau trên sản phẩm hoặc bảng cấu hình:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Tất cả các phân vùng do update_engine cập nhật không được sửa đổi bởi phần còn lại của hệ thống. Trong quá trình cập nhật gia tăng hoặc cập nhật delta, dữ liệu nhị phân từ vị trí hiện tại là được dùng để tạo dữ liệu trong vùng mới. Bất kỳ sửa đổi nào cũng có thể khiến dữ liệu vùng mới không xác minh được trong quá trình cập nhật và do đó không cập nhật được.

Định cấu hình sau khi cài đặt

Bạn có thể định cấu hình bước sau cài đặt theo cách khác nhau cho mỗi phân vùng đã cập nhật bằng cách sử dụng tập hợp cặp khoá-giá trị. Để chạy một chương trình tại /system/usr/bin/postinst trong một image, chỉ định đường dẫn tương ứng với gốc của hệ thống tệp trong phân vùng hệ thống.

Ví dụ: usr/bin/postinstsystem/usr/bin/postinst (nếu không dùng ổ đĩa RAM). Ngoài ra, hãy chỉ định loại hệ thống tệp để chuyển vào Lệnh gọi hệ thống mount(2). Thêm thông tin sau đây vào sản phẩm hoặc thiết bị .mk tệp (nếu có):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

Biên dịch ứng dụng

Bạn có thể biên dịch ứng dụng ở chế độ nền trước khi khởi động lại bằng hình ảnh hệ thống mới. Để biên dịch ứng dụng trong nền, hãy thêm đoạn mã sau vào cấu hình thiết bị của sản phẩm (trong device.mk của sản phẩm):

  1. Đưa các thành phần gốc vào bản dựng để đảm bảo tập lệnh và tệp nhị phân biên dịch được biên dịch và đưa vào hình ảnh hệ thống.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Kết nối tập lệnh biên dịch với update_engine để chạy dưới dạng một sau khi cài đặt.
      # A/B OTA dexopt update_engine hookup
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=system/bin/otapreopt_script \
        FILESYSTEM_TYPE_system=ext4 \
        POSTINSTALL_OPTIONAL_system=true
    

Để được trợ giúp cài đặt các tệp được chọn trước trong phân vùng hệ thống thứ hai không sử dụng, hãy tham khảo Cài đặt lần khởi động đầu tiên của tệp DEX_PREOPT.