Các nhà sản xuất thiết bị gốc (OEM) và nhà cung cấp hệ thống trên chip (SoC) muốn triển khai bản cập nhật hệ thống A/B phải đảm bảo rằng 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 kernel.
Triển khai HAL kiểm soát khởi động
Trình tải khởi động có khả năng 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 cách triển khai bằng tiện ích
system/extras/bootctl
và
system/extras/tests/bootloader/.
Bạn cũng phải triển khai máy trạng thái như minh hoạ bên dưới:
Thiết lập kernel
Cách triển khai bản cập nhật hệ thống A/B:
-
Chọn có chọn lọc chuỗi bản vá kernel sau đây (nếu cần):
- Nếu khởi động mà không có ramdisk và sử dụng "boot as recovery" (khởi động dưới dạng khôi phục), hãy chọn có chọn lọc android-review.googlesource.com/#/c/158491/.
- Để thiết lập dm-verity mà không có ramdisk, hãy chọn có chọn lọc android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18.
-
Đảm bảo đối số dòng lệnh kernel chứa các đối số bổ sung sau:
... trong đó giá trị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>"<public-key-id>là mã nhận dạng của khoá công khai dùng để xác minh chữ ký bảng verity (để biết thông tin chi tiết, hãy xem dm-verity). -
Thêm chứng chỉ .X509 chứa khoá công khai vào chuỗi khoá hệ thống:
-
Sao chép chứng chỉ .X509 được định dạng ở định dạng
.dervào thư mục gốc của thư mụckernel. Nếu chứng chỉ .X509 được định dạng dưới dạng tệp.pem, hãy dùng lệnhopensslsau đây để chuyển đổi từ.pemsang định dạng.der:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Tạo
zImageđể đưa chứng chỉ vào chuỗi khoá hệ thống. Để xác minh,hãy kiểm tra mụcprocfs(yêu cầuKEYS_CONFIG_DEBUG_PROC_KEYSđược bật): Việc đưa chứng chỉ .X509 vào thành công cho biết sự hiện diện của khoá công khai trong chuỗi khoá hệ thống (phần đánh dấu cho biết mã nhận dạng khoá công khai).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
-
Thay thế khoảng trắng bằng
#và chuyển nó dưới dạng<public-key-id>trong dòng lệnh kernel. Ví dụ: chuyểnAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40fthay cho<public-key-id>.
-
Sao chép chứng chỉ .X509 được định dạng ở định dạng
Đặt biến bản dựng
Trình tải khởi động có khả năng A/B phải đáp ứng các tiêu chí về biến bản dựng sau:
| Phải xác định cho mục tiêu A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk. Bạn có thể tuỳ ý thực hiện bước dex2oat sau khi cài đặt (nhưng trước khi khởi động lại) như mô tả trong
Biên dịch.
|
|---|---|
| Rất nên dùng cho mục tiêu A/B |
|
| Không thể xác định cho mục tiêu A/B |
|
| Không bắt buộc đối với bản dựng gỡ lỗi | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Đặt phân vùng (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 nữa. 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. Tất cả các phân vùng được A/B-ed phải được đặt tên
như sau (các vùng 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à để tạm thời lưu trữ các khối trong khi áp dụng bản cập nhật. Chưa từng có cách nào hay để định kích thước phân vùng bộ nhớ đệm: kích thước cần thiết phụ thuộc vào những bản cập nhật mà bạn muốn áp dụng. Trường hợp xấu nhất là phân vùng bộ nhớ đệm lớn bằng hình ảnh hệ thống. Với các bản 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 dùng) và với A/B phát trực tuyến, bạn không cần tải toàn bộ gói OTA xuống trước khi áp dụng.
Khôi phục
Đĩa RAM khôi phục hiện có trong tệp boot.img. Khi chuyển sang chế độ
khôi phục, trình tải khởi động không thể đặt tuỳ chọn skip_initramfs trên
dòng lệnh kernel.
Đối với các bản cập nhật không phải A/B, phân vùng khôi phục chứa mã dùng để áp dụng bản cập nhật. Các bản cập nhật A/B
được áp dụng bởi update_engine chạy trong hình ảnh hệ thống đã khởi động thông thường.
Vẫn có 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à tải gói cập nhật
lên (đó 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 sẽ yêu cầu kernel bỏ qua ramdisk (nếu không, thiết bị sẽ khởi động vào chế độ khôi phục
Chế độ khôi phục có kích thước nhỏ (và phần lớn đã nằm trên phân vùng khởi động), vì vậy, phân vùng khởi động không tăng kích thước.
Fstab
Đối số slotselect phải nằm trên dòng cho các phân vùng được A/B-ed. Ví dụ:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Không phân vùng nào được đặt tên là vendor. Thay vào đó, phân vùng vendor_a hoặc
vendor_b sẽ được chọn và gắn vào điểm gắn kết /vendor
Đối số vùng kernel
Hậu tố vùng hiện tại phải được chuyển qua một nút cây thiết bị (DT) cụ thể
(/firmware/android/slot_suffix) hoặc qua
androidboot.slot_suffix dòng lệnh kernel hoặc đối số bootconfig.
Theo mặc định, fastboot sẽ flash vùng 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ùng khác không phải vùng hiện tại, thì fastboot cũng sẽ flash 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à nhắc fastboot flash vùng được chuyển vào dưới dạng đối số. -
--set-active [SLOT]. Đặt khung giờ là khung giờ đang hoạt động. Nếu không chỉ định đối số không bắt buộc nào thì vùng hiện tại sẽ được đặt là vùng đ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 fastboot, thì trình tải khởi động đó phải hỗ trợ lệnh
set_active <slot> đặt vùng đang hoạt động hiện tại thành vùng đã cho (lệnh này
cũng phải xoá cờ không khởi động được cho vùng đó và đặt lại số lần thử lại về giá trị mặc định
). 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" (có) nếu phân vùng đã cho hỗ trợ các vùng, "no" (không) nếu không. current-slot. Trả về hậu tố vùng sẽ khởi động tiếp theo.-
slot-count. Trả về một số nguyên đại diện cho số vùng hiện có. Hiện tại, hệ thống hỗ trợ 2 vùng nên giá trị này là2. -
slot-successful:<slot-suffix>. Trả về "yes" (có) nếu vùng đã cho được đánh dấu là khởi động thành công, "no" (không) nếu không. -
slot-unbootable:<slot-suffix>. Trả về "yes" (có) nếu vùng đã cho được đánh dấu là không khởi động được, "no" (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 vùng đã cho.
Để xem tất cả các biến, hãy chạy
fastboot getvar all.
Tạo gói OTA
Các công cụ gói OTA tuân theo các lệnh giống như các
lệnh cho các thiết bị không phải A/B. Bạn phải tạo tệp target_files.zip bằng cách
xác định các biến bản dựng cho mục tiêu A/B. Các công cụ 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 OTA đầy đủ:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip -
Cách tạo 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ó tiền tố chung (chẳng hạn như system hoặc boot)
và hậu tố theo vùng (chẳng hạn như _a). Danh sách các phân vùng mà trình tạo tải trọng
xác định bản cập nhật được định cấu hình bởi biến tạo AB_OTA_PARTITIONS.
Ví dụ: nếu một cặp phân vùng bootloader_a và
booloader_b được đưa vào (_a và _b là hậu tố vùng
), bạn có thể cập nhật các phân vùng này bằng cách chỉ định nội dung sau đây trên cấu hình sản phẩm hoặc bo mạch
:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Tất cả các phân vùng được 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 delta, dữ liệu nhị phân từ vùng hiện tại được
dùng để tạo dữ liệu trong vùng mới. Mọi sửa đổi đều 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 khi cài đặt theo cách khác nhau cho từng phân vùng được cập nhật bằng một tập hợp các
cặp khoá-giá trị. Để chạy một chương trình nằm tại /system/usr/bin/postinst trong một hình ảnh mới, hãy chỉ định đường dẫn tương đối đến thư mục gốc của hệ thống tệp trong phân vùng hệ thống.
Ví dụ: usr/bin/postinst là system/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 đến lệnh gọi hệ thống
mount(2). Thêm nội dung sau vào tệp của sản phẩm hoặc thiết bị
.mk (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 ở chế độ nền, hãy thêm nội dung 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):
-
Đưa các thành phần gốc vào bản dựng để đảm bảo tập lệnh biên dịch và tệp nhị phân được
biên dịch và đưa vào hình ảnh hệ thống.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Kết nối tập lệnh biên dịch với
update_engineđể chạy dưới dạng bước 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 đã chọn trước trong phân vùng hệ thống thứ hai không dùng đến, hãy tham khảo bài viết Cài đặt tệp DEX_PREOPT trong lần khởi động đầu tiên.