OTA和Recovery系统升级流程介绍
本文介紹了Android原生OTA和Recovery升級過程步驟.
進入升級
- 1.1 正常啟動和進入Recovery的區別
下面給出了升級流程的簡單示意圖。?
?
上圖中的上下兩個部分,上面一部分是正常的啟動模式,下面一部分為Recovery模式。正常的啟動模式是從boot.img啟動系統(Main System),而recovery模式則是從reovery.img啟動系統;(reovery.img只包含內核、簡單的文件管理系統和圖形系統)
Boot分區包括linux內核和Ramdisk,Recovery分區也包括Linux內核和Ramdisk,一般來說內核是一樣的,但Ramdisk區別則非常大,recovery中的ramdisk會有更多的recovery需要使用的程序和數據。
- 1.2 分區介紹
這里說到的boot.img和recovery.img,其實就對應了一個Android設備中的分區,一般來說,android設備會包含以下幾個分區
Boot:包含Linux內核和一個最小的root文件系統(裝載到RAM disk中),用于掛載系統和其他的分區,并開始Runtime?
System:包括了系統應用和庫文件(AOSP中可以獲取到源代碼),在運行的過程中,這個分區是read-only的,只有在OTA升級的時候才會發生變化?
Vendor:包括了系統應用和庫文件(AOSP中不能獲取到源代碼),和System分區一樣,只有在OTA升級的時候才會發生變化?
Userdata:用戶安裝的應用程序會把數據保存在這里,正常情況下OTA是不會清除這里的數據的,指定要刪除出具的除外?
Cache:臨時的保存應用數據(要把數據保存在這里,需要特地的app permission),OTA的升級包也可以保存在這里。OTA升級過程可能會清楚這個分區的數據。?
Recovery:包括了一個完整Linux內核和一些特殊的recovery binary,可以讀取升級文件用這些文件來更新其他的分區?
Misc:一個非常小的分區,recovery用這個分區來保存一些關于升級的信息,應對升級過程中的設備掉電重啟的狀況
這些分區是Google官方的標準,實際的情況可能不太一樣,就Find 7而言,刷機包里面的分區只有以下幾個 :芯片廠商和手機廠商會根據自己的需要加一些其他的分區,如下面的persist.img是高通的,reserve4是我們自己加的保留分區,MTK還有preloader、lk,高通的還有NON-HLOS.bin、sbl、emms_aboot等。
Bootloader
- 2.1 什么是Bootloader??
在嵌入式操作系統中,Bootloader在操作系統內核運行之前運行,可以初始化硬件設備、建立內存空間映射圖,為調用操作系統內核準備好正確的環境。Bootloader和硬件是強相關的,且廠商一般都會對bootloader加鎖,這樣就不能隨便刷機了。?
當然bootloader也是可以解鎖的,這里不得不提一下root和bootloader解鎖分別是怎么一回事:root是通過內核漏洞獲取最高的權限,也就是所謂的超級用戶(su,superuser),屬于系統層面,root之后就可以修改system分區的數據;bootloader解鎖則屬于硬件層面的解鎖boot和recovery分區,解鎖bootloader不會root手機。更多見參考文獻[1].
- 2.2 Fastboot和recovery的區別??
Bootloader過程中,先做一些初始化,然后根據組合鍵做不同的事情,這個過程內核沒有加載,機器知識在按順序執行指令。?
Fastboot:在這種模式下,可以修改手機的硬件,并且允許我們發送一些命令給Bootloader。如使用電腦刷機,則需要進入fastboot模式,通過電腦執行命令將系統鏡像刷到通過USB刷到手機中。?
Recovery:Recovery是一個小型的操作系統,并且會加載部分文件系統,這樣才能從sdcard中讀取升級包。?
Bootloader.cpp?
Bootloader(bootable/recovery/bootloader.cpp)會讀取位于MISC分區的啟動控制信息塊BCB(Bootloader Control Block),通過函數
- 1
- 2
- 1
- 2
如果command的值為“boot-recovery”時,就進入recovery模式。Recovery升級過程中掉電,下次按power鍵開機也會進入recovery模式就是因為misc分區依然存在recovery信息(掉電保護)。
Recovery模式
- 3.1 Recovery、Bootloader以及Main System通信方法?
圖1中給出模式比較簡單,實際上三個實體的交互過程并不是圖1那種單向的順序流程,而是一個雙向的流程,于是就涉及到個三個部分的通信方法的實現。?
Recovery和Main System交互?
這一部分源代碼(bootable/recovery/recovery.cpp)注釋中有詳細的介紹,這里大致總結一下:這兩個部分交互是通過/cache文件來實現的,涉及到的文件如下表。?
?
Recovery、Main System和Bootloader交互?
這個交互過程是通過BCB來完成的,BCB其實就是一個struct(在misc分區),在(bootable/recovery/bootloader.h)中定義。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Command:重啟進入recovery或者是更新radio或Bootloader硬件時,會更新這個域;?
Status:在bootloader完成“update-radio”和”update-hboot”命令之后更新;?
Recovery:用于system和recovery之間的通信;?
Stage:需要重啟多次的packages會寫入這個值,表示所處的狀態。?
上面的過程可以總結為如下的示意圖:?
cache/recovery/command中command有哪些??
下表給出一些常用的命令和其含義。?
- 3.3 Factory Reset—恢復出廠設置?
恢復出廠設置也在recovery.cpp中完成,具體的流程如下:?
1) 用戶選擇恢復出廠設置?
2) Main System會在cache/recovery/command中寫入—wipe-data的命令,然后重啟進入recovery?
3) 通過get_args在BCB中寫入boot-recovery和wipe-data命令?
4) 然后重啟進行erase_volume?
5) 擦除數據之后調用finish_recovery將BCB中的數據清除?
6) main()函數調用reboot()進入Main System;?
OTA安裝
- 4.1 OTA簡介
OTA,即Over the air,它可以實現完整的版本升級,也可以是增量升級。用戶可以選擇在SD卡中作本地升級,也可以直接采用網絡在線升級。不管是哪種方式,都有幾個過程:生成升級包、獲取升級包、執行升級包,生成升級包不做介紹,。?
實際上,所謂OTA的整個過程可以用如下示意圖表示。?
?
首先,用戶用手機的OTA檢查更新(或者是自動更新),發送查詢數據給服務器,然后服務器查詢到相應的包,并返回下載地址給OTA.apk,然后OTA.apk進行下載,把下載的數據存儲在手機的某個分區。完成之后用于選擇是否升級,升級的時候OTA會發送命令給Main System,進入recovery,recovery根據利用下載下來的升級包完成升級過程。?
從圖中,我們可以看出OTA.apk實際上只是完成了從服務下下載安裝包,以及發送升級命令,功能似乎很容易描述,但是實際上要做的事情卻是非常多的,特別是OTA 2.0將Applypatch功能移植到OTA.apk之后,復雜度進一步增加了。
4.2 OTA安裝流程
下面對Recovery的升級步驟做一個梳理:?
1) Main System下載OTA升級包,官方推薦下載到/cache分區下,但是實際上可以自己選擇存儲地方;?
2) Main System在/cache/recovery/command中寫入“—update_package=安裝包路徑”?
3) 系統重啟進入recovery,這一步是通過PowerManager的reboot(“recovery”)實現的?
4) Get_args()在BCB中寫入“boot-recovery”和”—update_package“,這樣就保證了即便是設備出故障重啟了,只有這兩個命令還在,就會嘗試重新安裝OTA升級包?
5) Install_package嘗試開始安裝OTA升級包?
6) Finish_package擦除BCB?
7) 如果升級失敗?
Prompt_and_wait顯示錯誤,并等待用戶響應?
用戶重啟?
8) 設備重啟進入MainSystem?
此外,還有個maybe_install_firmware_upadate,具體過程不做介紹了。
下面是Recovery的代碼的區別,實際上2.3/3.0/4.4和5.0的代碼差別還是非常大的,原因是5.0的recovery用C++改寫了一遍,官方文檔兩者改寫的函數進行了對比?
?
4.3 Install_package過程
安裝過程在/bootable/recovery/install.cpp中,?
install_package(const char* path, int* wipe_cache, const char* install_file, bool needs_mount)?
在recovery的main函數中傳入的參數如下:?
install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE, true);?
參數列表:?
-Path:傳入的安裝包地址?
-wipe_cache:是否擦除cache分區?
-install_file:實際上是安裝過程的臨時安裝文件的地址(/tmp/last_install),包括install_log?
-needs_mount:是否需要Mount,安裝過程傳入的是true?
在install_package函數中,其實真正調用的是really_install_package函數:?
result = really_install_package(path, wipe_cache, needs_mount);?
這里對幾個重要的流程做一些介紹:?
-Set_install_mounts:檢查安裝包所在路徑的分區是否掛載,否則返回安裝失敗?
-Set_backgroud:升級過程的UI界面顯示?
-Load_keys,加載公鑰,我們系統的簽名文件放在/build/target/product/security/目錄下。這樣做的目的是為了防止用戶使用不同的項目的升級包進行混刷,導致刷機變磚的情況;?
-verify_file():對升級包update.zip包進行簽名驗證;?
-mzOpenZipArchive():打開升級包,并將相關的信息拷貝到一個臨時的ZipArchinve變量中。這一步并未對我們的update.zip包解壓。?
-try_update_binary():在這個函數中才是對我們的update.zip升級的地方。這個函數一開始先根據我們上一步獲得的zip包信息,以及升級包的絕對路徑將update_binary文件拷貝到內存文件系統的/tmp/update_binary中?
-execv(binary,args)的作用就是去執行binary程序,這個程序的實質就是去解析update.zip包中的updater-script腳本中的命令并執行?4.4 Update-binary和Updater-script
上面,我們講到execv執行二進制文件和Updater-script腳本中的命令,這兩個文件在下面的目錄。Apply_patch過程其實是會預先在APK端提取出來這兩個文件的。?
try_update_binary運行時,會首先從安裝包中讀取出update-binary這個可執行文件。創建一個管道(作用稍后會講到),并在一個新線程中運行這個update-binary(即updater,主函數見bootable/recovery/updater/updater.c),update-binary運行的時候,先會從升級包中讀取update-script。?
bootable/recovery/updater/updater.c中會注冊函數,而這些被注冊的函數在updater-script中有使用到。
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
常用的Updater-script命令?
總結
以上是生活随笔為你收集整理的OTA和Recovery系统升级流程介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 项目管理概要记录
- 下一篇: LCD正向扫描和反向扫描