版權聲明:您好,轉載請留下本人部落格的位址,謝謝 https://blog.csdn.net/hongbochen1223/article/details/49834125
Android OTA更新
Android裝置可以接受和安裝系統和應用軟體的空中下載下傳更新.裝置有一個特殊的帶有軟體的recovery分區,該分區可以解壓下載下傳的更新包并且将他們應用到系統中.
這一小節描述了這些包的結構和為了建構他們所提供的工具.主要是為了那些想要在新的Android裝置上制作OTA更新系統工作和那些為發行的的裝置建構更新包的開發者設計的.OTA更新被設計用于設計底層的作業系統和安裝在系統分區的隻讀app;這些更新不會影響來自應用市場的使用者安裝的應用程式.
這一小節描述的是Android5.x發行版的OTA系統更新.最後我會将其他版本的OTA相關的代碼附上.
Android裝置更新
Android裝置上的flash空間包含下面的幾個分區:
boot
包含Linux核心和一個小型的根檔案系統(被加載到RAM中).他挂載系統和其他分區,并且啟動位于系統分區上的運作時.
system
包含系統應用和在android開源項目(AOSP)中存在源代碼的庫檔案.在正常操作期間,這個分區是以隻讀方式被挂載的;他的内容僅僅在OTA更新期間被改變.
vendor
包含系統應用和在AOSP中不存在源代碼的庫檔案.在正常操作期間,該分區是以隻讀的方式挂載的;他的内容僅僅在OTA更新期間被改變.
userdata
儲存由使用者安裝的應用的資料.這個分區通常是不能被OTA更新改變的.
cache
暫時持有被一些應用所使用的區域(通路這個分區需要特殊的app權限),并且用于存儲下載下傳的OTA更新包.其他應用程式使用這個空間,會知道檔案會在任何時候消息.一些OTA包安裝程式可能會導緻這個分區被完全擦除.
recovery
包含一個完整的Linux系統,包括一個核心和特殊的recovery二進制檔案,這些檔案讀取一個包并且使用他的内容來更新其他分區.
misc
被recovery使用的小型分區來儲存一些資訊,以防止當OTA包正在被應用的時候裝置重新開機.
一個OTA更新的聲明周期
一個典型的OTA更新包含下面的步驟:
- 裝置使用OTA服務運作正常的檢查,并且被可用更新通知,包括更新包的URL和展示給使用者的一個描述字元串.
- 更新下載下傳到一個cache或者是data分區,并且他的加密簽名和位于/system/etc/security/otacerts.zip的證書進行驗證.使用者被推送來安裝更新
- 裝置重新開機進入recovery模式,在這個模式中,位于recovery分區的核心和系統被啟動,而不是位于boot分區核心啟動
- Recovery二進制檔案被init啟動.他尋找位于/cache/recovery/command中的指令行參數,該參數執行下載下傳的包.
- Recovery通過位于/res/keys(位于recovery分區的一部分RAM)下的公共鑰匙來驗證包的加密簽名.
- 資料從包中提取出來并且用于去更新需要的boot,system和vendor分區.位于system分區的其他新檔案之一包含新的recovery分區的内容
-
裝置正常重新開機.
a. 新更新的boot分區被加載,他挂載和開始執行位于新的更新的system分區中的二進制檔案
b. 作為正常啟動的一部分,系統檢查recovery分區的内容和需要的内容做對比(之前以檔案的形式儲存在/system中). 他們是不同的,是以recovery分區被需要的内容寫入.(在随後的啟動中,recovery分區已經包含新的内容,是以不需要重新寫入了.)
系統更新完成了.
遷移從先前的版本
當從Android2.3/3.0/4.0發行版遷移的時候,主要的改變就是所有的裝置特定的函數從一套C函數到預定義名稱的C++對象的轉換.下列的表列舉除了實作同樣目的的舊函數和新方法.
C function | C++ method |
---|---|
device_recovery_start() | Device::RecoveryStart() |
device_toggle_display() device_reboot_now() | RecoveryUI::CheckKey() (also RecoveryUI::IsKeyPressed()) |
device_handle_key() | Device::HandleMenuKey() |
device_perform_action() | Device::InvokeMenuItem() |
device_wipe_data() | Device::WipeData() |
device_ui_init() | ScreenRecoveryUI::Init() |
舊函數到新方法的轉換應該是非常合理直接的.不要忘記添加一個新的make_device()函數來建立和傳回一個新的裝置子類的執行個體.