在沒有 A/B 分割區的舊版 Android 裝置上,快閃記憶體空間通常包含下列分割區:
- 啟動
- 包含 Linux 核心和最小根檔案系統(載入到 RAM 磁碟中)。它掛載系統和其他分割區並啟動位於系統分割區上的執行時間。
- 系統
- 包含具有 Android 開源專案 (AOSP) 上可用原始程式碼的系統應用程式和程式庫。正常運作時,該分割區以唯讀方式掛載;其內容僅在 OTA 更新期間變更。
- 小販
- 包含 Android 開源專案 (AOSP) 上沒有可用原始程式碼的系統應用程式和程式庫。正常運作時,該分割區以唯讀方式掛載;其內容僅在 OTA 更新期間變更。
- 使用者資料
- 儲存使用者安裝的應用程式所保存的資料等。OTA 更新過程通常不會觸及該分割區。
- 快取
- 一些應用程式使用的臨時保留區域(存取此分區需要特殊的應用程式權限)並用於儲存下載的 OTA 更新套件。其他程式使用此空間,期望文件可以隨時消失。某些 OTA 軟體包安裝可能會導致該分割區被完全擦除。快取還包含 OTA 更新的更新日誌。
- 恢復
- 包含第二個完整的 Linux 系統,包括核心和特殊的恢復二進位文件,該二進位檔案讀取套件並使用其內容來更新其他分割區。
- 雜項
- 恢復使用的小分割區來儲存一些有關其正在執行的操作的信息,以防裝置在應用 OTA 套件時重新啟動。
OTA 更新的生命週期
典型的 OTA 更新包含以下步驟:
- 裝置定期檢查 OTA 伺服器,並收到更新可用性通知,包括更新套件的 URL 和向使用者顯示的描述字串。
- 更新下載到快取或資料分區,並根據
/system/etc/security/otacerts.zip
中的憑證驗證其加密簽章。系統會提示使用者安裝更新。 - 設備重新啟動進入恢復模式,其中啟動恢復分區中的核心和系統,而不是啟動分區中的核心。
- 恢復二進位檔案由 init 啟動。它在
/cache/recovery/command
中找到指向下載的套件的命令列參數。 - 恢復根據
/res/keys
(恢復分割區中包含的 RAM 磁碟的一部分)中的公鑰驗證包的加密簽章。 - 從包中提取資料並根據需要用於更新引導、系統和/或供應商分區。系統分割區上留下的新檔案之一包含新復原分割區的內容。
- 設備正常重啟。
- 載入新更新的引導分割區,並在新更新的系統分割區中安裝並開始執行二進位檔案。
- 作為正常啟動的一部分,系統會根據所需內容(先前作為檔案儲存在
/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 子類別的實例。