Triển khai A/B ảo

Để triển khai A/B ảo trên một thiết bị mới hoặc để cải tiến một thiết bị đã ra mắt, bạn phải thực hiện thay đổi đối với mã dành riêng cho thiết bị.

Cờ dựng

Các thiết bị sử dụng A/B ảo phải được định cấu hình thành A/B thiết bị và phải chạy bằng động .

Đối với các thiết bị chạy bằng A/B ảo, hãy thiết lập để các thiết bị đó kế thừa A/B ảo cấu hình cơ sở thiết bị:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Các thiết bị chạy A/B ảo chỉ cần kích thước bảng bằng một nửa kích thước của bảng điều khiển BOARD_SUPER_PARTITION_SIZE vì các vị trí B không còn ở lớp Super. Tức là BOARD_SUPER_PARTITION_SIZE phải lớn hơn hoặc bằng tổng(kích thước của nhóm cập nhật) + mức hao tổn, do đó, phải lớn hơn lớn hơn hoặc bằng tổng(kích thước của phân vùng) + mức hao tổn.

Đối với Android 13 trở lên, để bật tính năng nén bản tổng quan nhanh bằng A/B ảo, kế thừa cấu hình cơ sở sau:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)

Thao tác này cho phép chụp nhanh không gian người dùng bằng A/B ảo trong khi sử dụng chế độ không hoạt động phương thức nén. Sau đó, bạn có thể định cấu hình phương thức nén thành một trong các phương thức được hỗ trợ, gz, zstdlz4.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4

Đối với Android 12, để bật ảnh chụp nhanh được nén bằng A/B ảo, kế thừa cấu hình cơ sở sau:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Nén bằng XOR

Đối với những thiết bị nâng cấp lên Android 13 trở lên, Tính năng nén XOR không bật theo mặc định. Để bật tính năng nén XOR, hãy thêm mã sau vào Tệp .mk.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

Tính năng nén XOR được bật theo mặc định cho các thiết bị kế thừa từ android_t_baseline.mk.

Hợp nhất không gian người dùng

Đối với những thiết bị nâng cấp lên Android 13 trở lên, quy trình hợp nhất không gian người dùng như được mô tả trong Trình lập bản đồ thiết bị bạn không bật tính năng phân lớp bằng cách mặc định. Để bật tính năng hợp nhất không gian người dùng, hãy thêm dòng sau vào .mk của thiết bị tệp:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

Tính năng hợp nhất không gian người dùng được bật theo mặc định trên các thiết bị khởi chạy bằng 13 trở lên.

HAL (Lớp trừu tượng phần cứng) cho chế độ kiểm soát khởi động

Chế độ điều khiển khởi động Lớp trừu tượng phần cứng (HAL) cung cấp giao diện cho các ứng dụng OTA để kiểm soát các vị trí khởi động. A/B ảo yêu cầu nâng cấp phiên bản nhỏ của HAL điều khiển khởi động vì các API bổ sung là cần thiết để đảm bảo trình tải khởi động được bảo vệ trong quá trình cài đặt ROM hoặc đặt lại về trạng thái ban đầu. Xem IBootControl.haltypes.hal để biết phiên bản mới nhất của định nghĩa HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Thay đổi Fstab

Tính toàn vẹn của phân vùng siêu dữ liệu rất quan trọng đối với quá trình khởi động, đặc biệt là ngay sau khi áp dụng bản cập nhật OTA. Vì vậy, phân vùng siêu dữ liệu phải hãy kiểm tra trước khi first_stage_init gắn kết nối. Để đảm bảo điều này xảy ra, hãy thêm check gắn cờ fs_mgr vào mục nhập cho /metadata. Mã sau đây cung cấp ví dụ:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Yêu cầu về kernel

Để bật tính năng chụp nhanh, hãy đặt CONFIG_DM_SNAPSHOT thành true.

Đối với các thiết bị sử dụng F2FS, hãy thêm cờ f2fs: export FS_NOCOW_FL sang người dùng để khắc phục lỗi ghim tệp. Bao gồm các f2fs: hỗ trợ đã ghim được căn chỉnh tệp.

A/B ảo dựa trên các tính năng được thêm vào trong kernel phiên bản 4.3: lệnh overflow bit trạng thái trong các mục tiêu snapshotsnapshot-merge. Tất cả thiết bị đang chạy với Android 9 trở lên phải có phiên bản nhân hệ điều hành 4.4 trở lên.

Để bật tính năng tổng quan nhanh được nén, phiên bản kernel tối thiểu được hỗ trợ là 4.19. Đặt CONFIG_DM_USER=m hoặc CONFIG_DM_USER=y. Nếu sử dụng mô-đun cũ (mô-đun), mô-đun phải được tải vào ổ đĩa ram ở giai đoạn đầu tiên. Có thể thực hiện điều này bằng cách thêm dòng sau vào tệp Makefile của thiết bị:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Retrofit trên những thiết bị nâng cấp lên Android 11

Khi nâng cấp lên Android 11, những thiết bị chạy phân vùng động có thể cải thiện A/B ảo (không bắt buộc). Quá trình cập nhật hầu hết giống như thiết bị chạy A/B ảo, với một số điểm khác biệt nhỏ:

  • Vị trí của các tệp COW – Đối với các thiết bị chạy, ứng dụng OTA sử dụng tất cả không gian trống có sẵn trong phân vùng cấp cao trước khi sử dụng không gian trong /data. Đối với các thiết bị được cải tiến, luôn có đủ không gian trong lớp siêu dữ liệu để tệp COW không bao giờ được tạo trên /data.

  • Cờ tính năng trong thời gian xây dựng – Đối với những thiết bị có hỗ trợ A/B ảo, cả PRODUCT_VIRTUAL_AB_OTAPRODUCT_VIRTUAL_AB_OTA_RETROFIT đều đã được đặt vào true, như minh hoạ sau đây:

    (call inherit-product, \
      (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • Kích thước phân vùng siêu cao – Thiết bị chạy A/B ảo có thể cắt giảm BOARD_SUPER_PARTITION_SIZE 1/2 vì các vị trí B không ở phần trên phân vùng. Các thiết bị đang cải tiến A/B ảo vẫn giữ nguyên phân vùng cấp cao cũ nên BOARD_SUPER_PARTITION_SIZE sẽ lớn hơn hoặc bằng 2 * sum(kích thước của nhóm cập nhật) + mức hao tổn, do đó sẽ lớn hơn hoặc bằng 2 * tổng(kích thước của các phân vùng) + hao tổn.

Các thay đổi đối với trình tải khởi động

Trong bước hợp nhất của một bản cập nhật, /data lưu giữ toàn bộ thực thể duy nhất của Hệ điều hành Android. Sau khi quá trình di chuyển bắt đầu, system, vendorproduct phân vùng chưa hoàn tất cho đến khi bản sao hoàn tất. Nếu thiết bị là đặt lại về trạng thái ban đầu trong quá trình này, bằng cách khôi phục hoặc thông qua Hệ thống cài đặt thì thiết bị sẽ không khởi động được.

Trước khi xoá /data, hãy hoàn tất việc hợp nhất trong quá trình khôi phục hoặc khôi phục tuỳ thuộc trạng thái thiết bị:

  • Nếu bản dựng mới đã khởi động thành công trước đó, hãy hoàn tất quá trình di chuyển.
  • Nếu không, hãy khôi phục về vị trí cũ:
    • Đối với phân vùng động, hãy khôi phục về trạng thái trước đó.
    • Đối với các phân vùng tĩnh, hãy đặt vùng đang hoạt động thành vùng cũ.

Cả trình tải khởi động và fastbootd đều có thể xoá phân vùng /data nếu thiết bị đã được mở khoá. Mặc dù fastbootd có thể buộc quá trình di chuyển hoàn tất, nhưng trình tải khởi động thì không. Trình tải khởi động không biết liệu có quá trình hợp nhất hay không tiến trình hoặc khối nào trong /data tạo thành các phân vùng hệ điều hành. Thiết bị phải ngăn người dùng vô tình làm cho thiết bị không hoạt động (đặt gạch) bằng cách thực hiện những việc sau:

  1. Triển khai HAL điều khiển khởi động để trình t���i khởi động có thể đọc giá trị đã đặt bằng phương thức setSnapshotMergeStatus().
  2. Nếu trạng thái hợp nhất là MERGING hoặc nếu trạng thái hợp nhất là SNAPSHOTTED và vị trí đã thay đổi thành vị trí mới cập nhật, sau đó yêu cầu xoá sạch userdata, metadata hoặc phân vùng lưu trữ trạng thái hợp nhất phải là bị từ chối trong trình tải khởi động.
  3. Triển khai lệnh fastboot snapshot-update cancel để người dùng có thể báo hiệu cho trình tải khởi động rằng chúng muốn bỏ qua cơ chế bảo vệ này.
  4. Sửa đổi các công cụ hoặc tập lệnh cài đặt ROM tuỳ chỉnh để xử lý fastboot snapshot-update cancel khi cài đặt ROM toàn bộ thiết bị. Đây là mức độ an toàn để phát hành vì Việc cài đặt ROM toàn bộ thiết bị sẽ xoá OTA. Công cụ có thể phát hiện lệnh này trong thời gian chạy bằng cách triển khai fastboot getvar snapshot-update-status. Chiến dịch này giúp phân biệt giữa các điều kiện lỗi.

Ví dụ

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

Các thay đổi về công cụ khởi động nhanh

Android 11 thực hiện các thay đổi sau đối với chế độ khởi động nhanh giao thức:

  • getvar snapshot-update-status – Trả về giá trị mà trình khởi động HAL điều khiển giao tiếp với trình tải khởi động:
    • Nếu trạng thái là MERGING, trình tải khởi động phải trả về merging.
    • Nếu trạng thái là SNAPSHOTTED, trình tải khởi động phải trả về snapshotted.
    • Nếu không, trình tải khởi động phải trả về none.
  • snapshot-update merge — Hoàn tất thao tác hợp nhất, khởi động vào khôi phục/khởi động nhanh nếu cần. Lệnh này chỉ hợp lệ nếu snapshot-update-statusmerging và chỉ được hỗ trợ khi khởi động nhanh.
  • snapshot-update cancel – Thiết lập trạng thái hợp nhất của HAL điều khiển khởi động thành CANCELLED Lệnh này không hợp lệ khi thiết bị đang khoá.
  • erase hoặc wipeerase hoặc wipe trên metadata, userdata, hoặc một phân vùng giữ trạng thái hợp nhất cho HAL điều khiển khởi động sẽ kiểm tra trạng thái hợp nhất ảnh chụp nhanh. Nếu trạng thái là MERGING hoặc SNAPSHOTTED, thiết bị sẽ huỷ thao tác đó.
  • set_active – Một lệnh set_active thay đổi vị trí đang hoạt động cần kiểm tra trạng thái hợp nhất ảnh chụp nhanh. Nếu trạng thái là MERGING, thì thiết bị sẽ huỷ thao tác đó. Bạn có thể thay đổi khe cắm một cách an toàn trong Trạng thái SNAPSHOTTED.

Những thay đổi này được thiết kế để ngăn chặn việc vô tình làm cho thiết bị không khởi động được, nhưng chúng có thể gây gián đoạn cho công cụ tự động. Khi các lệnh được dùng làm là thành phần cài đặt ROM tất cả các phân vùng, chẳng hạn như chạy fastboot flashall, mã này sẽ bạn nên sử dụng quy trình sau:

  1. Cụm từ tìm kiếm getvar snapshot-update-status.
  2. Nếu là merging hoặc snapshotted, hãy phát hành snapshot-update cancel.
  3. Tiếp tục thực hiện các bước nhấp nháy.

Giảm yêu cầu về bộ nhớ

Các thiết bị chưa phân bổ hết bộ nhớ A/B nhưng đang mong đợi sử dụng /data nếu cần, bạn nên sử dụng tính năng ánh xạ khối . Công cụ liên kết khối giúp phân bổ khối một cách nhất quán giữa các bản dựng, giảm các lượt ghi không cần thiết vào bản tổng quan nhanh. Điều này được ghi trong tài liệu Giảm Kích thước OTA.

Phương thức nén OTA

Bạn có thể điều chỉnh các gói OTA để biết nhiều chỉ số hiệu suất. Android cung cấp một số phương thức nén được hỗ trợ (gz, lz4, zstdnone) có sự đánh đổi giữa thời gian cài đặt, mức sử dụng không gian COW, thời gian khởi động và ảnh chụp nhanh thời gian hợp nhất. Tuỳ chọn mặc định được bật cho ab ảo có nén là gz compression method. (Lưu ý: hiệu suất tương đối giữa các phương thức nén sẽ khác nhau tuỳ thuộc vào tốc độ CPU và thông lượng bộ nhớ. Tốc độ này có thể thay đổi tuỳ theo trên thiết bị. Tất cả các gói OTA được tạo bên dưới đều đang tắt PostInstall. Điều này sẽ làm chậm thời gian khởi động một chút. Tổng kích thước phân vùng động của một toàn bộ ota không nén là 4.81 GB).

OTA gia tăng trên Pixel 6 Pro

Thời điểm cài đặt không có giai đoạn sau cài đặt Mức sử dụng không gian COW Sau thời gian khởi động OTA Thời gian hợp nhất ảnh chụp nhanh
gz 24 phút 1,18 GB 40,2 giây 45,5 giây
lz4 13 phút 1,49 GB 37,4 giây 37,1 giây
none 13 phút 2,90 GB 37,6 giây 40,7 giây

OTA đầy đủ trên Pixel 6 Pro

Thời điểm cài đặt không có giai đoạn sau cài đặt Mức sử dụng không gian COW Sau thời gian khởi động OTA Thời gian hợp nhất ảnh chụp nhanh
gz 23 phút 2,79 GB 24,9 giây 41,7 giây
lz4 12 phút 3,46 GB 20 giây 25,3 giây
none 10 phút 4,85 GB 20,6 giây 29,8 giây