非 A/B 系統更新

在沒有 A/B 分割區的舊版 Android 裝置上,快閃記憶體空間通常包含下列分割區:

啟動
包含 Linux 核心和最小根檔案系統(載入到 RAM 磁碟中)。它掛載系統和其他分割區並啟動位於系統分割區上的執行時間。
系統
包含具有 Android 開源專案 (AOSP) 上可用原始程式碼的系統應用程式和程式庫。正常運作時,該分割區以唯讀方式掛載;其內容僅在 OTA 更新期間變更。
小販
包含 Android 開源專案 (AOSP) 上沒有可用原始程式碼的系統應用程式和程式庫。正常運作時,該分割區以唯讀方式掛載;其內容僅在 OTA 更新期間變更。
使用者資料
儲存使用者安裝的應用程式所保存的資料等。OTA 更新過程通常不會觸及該分割區。
快取
一些應用程式使用的臨時保留區域(存取此分區需要特殊的應用程式權限)並用於儲存下載的 OTA 更新套件。其他程式使用此空間,期望文件可以隨時消失。某些 OTA 軟體包安裝可能會導致該分割區被完全擦除。快取還包含 OTA 更新的更新日誌。
恢復
包含第二個完整的 Linux 系統,包括核心和特殊的恢復二進位文件,該二進位檔案讀取套件並使用其內容來更新其他分割區。
雜項
恢復使用的小分割區來儲存一些有關其正在執行的操作的信息,以防裝置在應用 OTA 套件時重新啟動。

OTA 更新的生命週期

典型的 OTA 更新包含以下步驟:

  1. 裝置定期檢查 OTA 伺服器,並收到更新可用性通知,包括更新套件的 URL 和向使用者顯示的描述字串。
  2. 更新下載到快取或資料分區,並根據/system/etc/security/otacerts.zip中的憑證驗證其加密簽章。系統會提示使用者安裝更新。
  3. 設備重新啟動進入恢復模式,其中啟動恢復分區中的核心和系統,而不是啟動分區中的核心。
  4. 恢復二進位檔案由 init 啟動。它在/cache/recovery/command中找到指向下載的套件的命令列參數。
  5. 恢復根據/res/keys (恢復分割區中包含的 RAM 磁碟的一部分)中的公鑰驗證包的加密簽章。
  6. 從包中提取資料並根據需要用於更新引導、系統和/或供應商分區。系統分割區上留下的新檔案之一包含新復原分割區的內容。
  7. 設備正常重啟。
    1. 載入新更新的引導分割區,並在新更新的系統分割區中安裝並開始執行二進位檔案。
    2. 作為正常啟動的一部分,系統會根據所需內容(先前作為檔案儲存在/system中)檢查復原分區的內容。它們是不同的,因此恢復分割區會用所需的內容重新刷新。 (在後續啟動時,恢復分割區已包含新內容,因此無需重新刷新。)

系統更新完成!更新日誌可以在/cache/recovery/last_log. # .

更新套件

更新套件是一個.zip文件,其中包含可執行二進位檔案META-INF/com/google/android/update-binary 。驗證套件上的簽章後, recovery會將此二進位檔案提取到/tmp並執行該二進位文件,並傳遞以下參數:

  • 更新二進位 API 版本號。如果傳遞給更新二進位檔案的參數發生變化,則該數字會增加。
  • 命令管道的檔案描述符。更新程式可以使用此管道將命令發送回恢復二進位文件,主要用於 UI 更改,例如向使用者指示進度。
  • 更新套件.zip檔的檔名

更新包可以使用任何靜態連結的二進位檔案作為更新二進位檔案。 OTA套件建置工具使用更新程式( bootable/recovery/updater ),它提供了一種簡單的腳本語言,可以完成許多安裝任務。您可以替換設備上運行的任何其他二進位。

有關更新程式二進位檔案、edify 語法和內建函數的詳細信息,請參閱OTA 套件內部

從先前的版本遷移

從 Android 2.3/3.0/4.0 版本遷移時,主要變化是將所有特定於裝置的功能從一組具有預定義名稱的 C 函數轉換為 C++ 物件。下表列出了具有大致相同目的的舊函數和新方法:

C函數C++方法
device_recovery_start()設備::恢復開始()
device_toggle_display()
device_reboot_now()
RecoveryUI::CheckKey()
(還有 RecoveryUI::IsKeyPressed())
device_handle_key()設備::HandleMenuKey()
device_perform_action()設備::InvokeMenuItem()
device_wipe_data()設備::擦除資料()
device_ui_init() ScreenRecoveryUI::Init()

將舊函數轉換為新方法應該相當簡單。不要忘記新增新的make_device()函數來建立並傳回新 Device 子類別的實例。