在沒有 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. #
.
更新包
更新包是包含可執行二進制META-INF/com/google/android/update-binary
的.zip
文件。驗證包上的簽名後, recovery
會將此二進製文件提取到/tmp
並運行二進製文件,並傳遞以下參數:
- 更新二進制 API 版本號。如果傳遞給更新二進製文件的參數發生變化,這個數字就會增加。
- 命令管道的文件描述符。更新程序可以使用此管道將命令發送回恢復二進製文件,主要用於 UI 更改,例如向用戶指示進度。
- 更新包
.zip
文件的文件名。
更新包可以使用任何靜態鏈接的二進製文件作為更新二進製文件。 OTA 包構建工具使用更新程序( bootable/recovery/updater
),它提供了一種簡單的腳本語言,可以完成許多安裝任務。您可以替換設備上運行的任何其他二進製文件。
有關更新程序二進製文件、edify 語法和內置函數的詳細信息,請參閱Inside OTA Packages 。
從以前的版本遷移
從 Android 2.3/3.0/4.0 版本遷移時,主要變化是將所有特定於設備的功能從一組具有預定義名稱的 C 函數轉換為 C++ 對象。下表列出了用於大致相同目的的舊函數和新方法:
C 函數 | C++ 方法 |
---|---|
device_recovery_start() | 設備::RecoveryStart() |
device_toggle_display() device_reboot_now() | RecoveryUI::CheckKey() (還有 RecoveryUI::IsKeyPressed()) |
device_handle_key() | 設備::HandleMenuKey() |
device_perform_action() | 設備::InvokeMenuItem() |
device_wipe_data() | 設備::WipeData() |
device_ui_init() | ScreenRecoveryUI::Init() |
將舊函數轉換為新方法應該相當簡單。不要忘記添加新的make_device()
函數來創建並返回新 Device 子類的實例。