導入 A/B 更新

有意導入 A/B 系統更新的原始設備製造商 (OEM) 和 SoC 供應商,必須確保系統啟動載入程式 會實作 boot_control HAL,並將正確的參數傳送給 核心。

實作啟動控制項 HAL

支援 A/B 功能的系統啟動載入程式必須在以下位置實作 boot_control HAL hardware/libhardware/include/hardware/boot_control.h。您可以使用 system/extras/bootctl 公用程式和 system/extras/tests/bootloader/

您也必須實作下列的狀態機器:

圖 1.系統啟動載入程式狀態機器

設定核心

如何實作 A/B 系統更新:

  1. 視需要選擇下列核心修補程式系列:
  2. 確保核心指令列引數包含以下額外引數:
    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> 值是用來存取的公開金鑰 ID 驗證 verity 資料表簽章 (詳情請參閱 dm-verity)。
  3. 將包含公開金鑰的 .X509 憑證新增至系統金鑰環:
    1. 將格式為 .der 格式的 .X509 憑證複製到根 kernel 目錄內。如果 .X509 憑證的格式為 .pem 檔案,使用下列 openssl 指令進行轉換 .pem.der 格式:
      opensl x509 - <x509-pem-certificate>-outform der -out <x509-der-certificate>
    2. 建立 zImage,將憑證納入系統金鑰環的一部分。 如要驗證,請檢查 procfs 項目 (需要 KEYS_CONFIG_DEBUG_PROC_KEYS 才能啟用:
      angler:/# cat /proc/keys
      
      1c8a217e I------ 1/1 1f010000 0 0 非對稱式
      Android:7e4333f9bba00adfe0ede979e28ed1920492b40f:X509.RSA 0492b40f []
      2d454e3e I------ 1 分 1f030000 0 0 金鑰環
      .system_keyring:1/4
      成功加入 .X509 憑證表示存在公開金鑰 (醒目顯示代表公開金鑰 ID)。
    3. 將空格取代為 #,並做為 <public-key-id>。舉例來說,請將 Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f,取代 <public-key-id>

設定建構變數

支援 A/B 功能的系統啟動載入程式必須符合下列建構變數條件:

必須為 A/B 目標定義
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
      boot \
      system \
      vendor
    和其他分區 (透過 update_engine 更新、系統啟動載入程式、 etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
,瞭解如何調查及移除這項存取權。 範例請參照 /device/google/marlin/+/android-7.1.0_r1/device-common.mk。您可以選擇執行安裝後 (但重新啟動前) dex2oat 步驟,方法如 編譯
強烈建議用於 A/B 目標
  • 定義「TARGET_NO_RECOVERY := true
  • 定義「BOARD_USES_RECOVERY_AS_BOOT := true
  • 不要定義 BOARD_RECOVERYIMAGE_PARTITION_SIZE
無法定義 A/B 版本目標
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
偵錯版本選用項目 PRODUCT_PACKAGES_DEBUG += update_engine_client

設定分區 (運算單元)

A/B 裝置不需要復原分區或快取分區,因為 Android 不再使用 在這些分區中資料分區現已用於下載的 OTA 套件, 復原映像檔程式碼位於啟動分區。所有 A/B 版本分區都應命名 如下 (版位一律命名為 ab 等):boot_a, boot_bsystem_asystem_bvendor_avendor_b

快取

如果是非 A/B 版本更新,系統會使用快取分區儲存下載的 OTA 套件,並 在套用更新時暫時隱藏區塊。沒有任何一種方式可以調整快取大小 分區:資源需要的大小取決於您要套用的更新。最差 原因在於快取分區和系統映像檔一樣大。不需要使用 A/B 更新 才能隱藏區塊 (因為您總是寫入目前未使用的分區) 在進行 A/B 串流時,您不需要下載整個 OTA 套件即可套用。

搶球

復原 RAM 磁碟已納入 boot.img 檔案中。想進入 復原,系統啟動載入程式無法skip_initramfs 選項設為開啟 核心指令列

如果是非 A/B 更新,復原分區含有用來套用更新的程式碼。A 到 B 罩杯 更新項目是由在一般啟動系統映像檔中執行的 update_engine 所套用。 你仍使用復原模式執行恢復原廠設定和側載更新 套件 (「recovery」的名稱來自於此)。復原模式的程式碼和資料 儲存於 ramdisk 的一般開機分區中;啟動進入系統映像檔 系統啟動載入程式會要求核心略過 ramdisk (否則裝置開機時就會進入復原程序) 模式。復原模式很小 (大多數功能均位於開機分區中),因此啟動 分區就不會增加

Fstab

slotselect 引數必須位於 A/B 版本的程式碼行上 多個分區例如:

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

沒有任何分區的名稱為 vendor。請改為將 vendor_a 或 會選取 vendor_b,並掛接在 /vendor 掛接點。

核心運算單元引數

目前的運算單元後置字串應透過特定裝置樹狀結構 (DT) 節點傳遞 (/firmware/android/slot_suffix) 或透過 androidboot.slot_suffix 核心指令列或 bootconfig 引數。

根據預設,Fastboot 會在 A/B 裝置上刷新目前的插槽。如果更新套件 包含其他非現行運算單元的映像檔,且 Fastboot 也會閃爍這些映像檔。 可用選項包括:

  • --slot SLOT。覆寫預設行為,並提示 Quickboot 刷新傳入的 引數。
  • --set-active [SLOT]。將版位設為有效。如果沒有選用引數 ,則目前版位會設為有效。
  • fastboot --help。進一步瞭解指令。

如果系統啟動載入程式實作了 Fastboot,則應支援以下指令: set_active <slot>,將目前的有效運算單元設為指定版位 (此 必須一併清除該運算單元無法啟動的標記,並將重試次數重設為預設值 )。系統啟動載入程式也支援下列變數:

  • has-slot:<partition-base-name-without-suffix>。如果有指定值,則傳回「yes」 分區支援運算單元,否則「否」。
  • current-slot。傳回要從下個啟動的運算單元尾碼。
  • slot-count。傳回代表可用運算單元數量的整數。 目前支援兩個版位,因此這個值是 2
  • slot-successful:<slot-suffix>。傳回「yes」如果指定的版位 標示為已成功啟動,「否」反之。
  • slot-unbootable:<slot-suffix>。如果指定版位標有「yes」,則傳回「yes」。 無法啟動,「否」反之。
  • slot-retry-count:<slot-suffix>。要嘗試的剩餘重試次數 啟動指定版位

如要查看所有變數,請執行 fastboot getvar all

產生 OTA 套件

OTA 套件工具遵循與 指令。target_files.zip 檔案必須由 定義 A/B 目標的建構變數。OTA 套件工具會自動找出 並以 A/B 更新工具的格式產生套件

例如:

  • 如何產生完整的 OTA:
    ./build/make/tools/releasetools/ota_from_target_files \
        Dist_output/tardis-target_files.zip\
        ota_update.zip
    
  • 如何產生漸進式 OTA:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        Dist_output/tardis-target_files.zip\
        Flex_ota_update.zip
    

設定分區

update_engine 可以更新同一個磁碟中定義的任何 A/B 分區組合。 一組分區含有相同的前置字元 (例如 systemboot) 和每個時段的後置字串 (例如 _a)酬載的分區清單 產生器會定義更新項目,由 AB_OTA_PARTITIONS make 變數設定。

舉例來說,假設有一組分區 bootloader_a 和 包含 booloader_b (_a_b 是版位) 後置字串),只要在產品或開發板中指定以下項目,即可更新這些分區 設定:

AB_OTA_PARTITIONS := \
  啟動 \
  系統 \
  系統啟動載入程式

update_engine 更新的所有分區均不得由其餘節點修改 有些人會將 Cloud Storage 視為檔案系統 但實際上不是在增量或差異更新期間,目前運算單元的二進位資料會 以便在新運算單元中產生資料任何修改都可能會讓系統將新的運算單元資料傳送至 更新失敗,導致更新失敗。

設定安裝後

您可以使用一組 鍵/值組合若要執行位於 /system/usr/bin/postinst 的 映像檔,請指定相對於系統分區中檔案系統根目錄的路徑。

例如,usr/bin/postinstsystem/usr/bin/postinst (如果不是的話) RAM 磁碟)。此外,指定要傳遞給 mount(2) 系統呼叫。將以下內容新增至產品或裝置 .mk 檔案 (如適用):

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

編譯應用程式

應用程式可以在使用新的系統映像檔重新啟動之前,在背景編譯。編譯 ,請將下列程式碼新增到產品的裝置設定 (位於 product's device.mk):

  1. 在建構作業中加入原生元件,確保編譯指令碼和二進位檔均 將這個模型編譯並納入系統映像檔中
      # A/B OTA dexopt 套件
      PRODUCT_PACKAGES += otapreopt_script
    
  2. 將編譯指令碼連結至 update_engine,以便以 安裝後的步驟
      # A/B OTA dexopt update_engine 連結
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=system/bin/otapreopt_script \
        filesYSTEM_TYPE_system=ext4
        POSTINSTALL_OPTIONAL_system=true
    

如要瞭解如何在未使用的第二個系統分區中安裝預先選擇的檔案,請參閱 首次啟動 DEX_PREOPT 檔案