在使用update.zip包升級時怎樣從主系統(main system)重啓進入Recovery模式,進入Recovery模式後怎樣判斷作何種操做,以及怎樣得到主系統發送給Recovery服務的命令,這一系列問題的解決是經過整個軟件平臺的不一樣部分之間的密切通訊配合來完成的。爲此,咱們必需要了解Recovery模式的工做原理,這樣才能知道咱們的update.zip包是怎樣一步步進入Recovery中升級並最後到達主系統的。架構
1、Recovery模式中的三個部分函數
Recovery的工做須要整個軟件平臺的配合,從通訊架構上來看,主要有三個部分。spa
①MainSystem:即上面提到的正常啓動模式(BCB中無命令),是用boot.img啓動的系統,Android的正常工做模式。更新時,在這種模式中咱們的上層操做就是使用OTA或則從SD卡中升級update.zip包。在重啓進入Recovery模式以前,會向BCB中寫入命令,以便在重啓後告訴bootloader進入Recovery模式。
命令行
②Recovery:系統進入Recovery模式後會裝載Recovery分區,該分區包含recovery.img(同boot.img相同,包含了標準的內核和根文件系統)。進入該模式後主要是運行Recovery服務(/sbin/recovery)來作相應的操做(重啓、升級update.zip、擦除cache分區等)。接口
③Bootloader:除了正常的加載啓動系統以外,還會經過讀取MISC分區(BCB)得到來至Main system和Recovery的消息。ip
2、Recovery模式中的兩個通訊接口字符串
在Recovery服務中上述的三個實體之間的通訊是必不可少的,他們相互之間又有如下兩個通訊接口。源碼
(一)經過CACHE分區中的三個文件:string
Recovery經過/cache/recovery/目錄下的三個文件與mian system通訊。具體以下 flash
①/cache/recovery/command:這個文件保存着Main system傳給Recovery的命令行,每一行就是一條命令,支持一下幾種的組合。
--send_intent=anystring //write the text out to recovery/intent 在Recovery結束時在finish_recovery函數中將定義的intent字符串做爲參數傳進來,並寫入到/cache/recovery/intent中
--update_package=root:path //verify install an OTA package file Main system將這條命令寫入時,表明系統須要升級,在進入Recovery模式後,將該文件中的命令讀取並寫入BCB中,而後進行相應的更新update.zip包的操做。
--wipe_data //erase user data(and cache),then reboot。擦除用戶數據。擦除data分區時必需要擦除cache分區。
--wipe_cache //wipe cache(but not user data),then reboot。擦除cache分區。
②/cache/recovery/log:Recovery模式在工做中的log打印。在recovery服務運行過程當中,stdout以及stderr會重定位到/tmp/recovery.log在recovery退出以前會將其轉存到/cache/recovery/log中,供查看。
③/cache/recovery/intent:Recovery傳遞給Main system的信息。做用不詳。
(二)經過BCB(Bootloader Control Block):
BCB是bootloader與Recovery的通訊接口,也是Bootloader與Main system之間的通訊接口。存儲在flash中的MISC分區,佔用三個page,其自己就是一個結構體,具體成員以及各成員含義以下:
struct bootloader_message{
char command[32];
char status[32];
char recovery[1024];
};
①command成員:其可能的取值咱們在上文已經分析過了,即當咱們想要在重啓進入Recovery模式時,會更新這個成員的值。另外在成功更新後結束Recovery時,會清除這個成員的值,防止重啓時再次進入Recovery模式。
②status:在完成相應的更新後,Bootloader會將執行結果寫入到這個字段。
③recovery:可被Main System寫入,也可被Recovery服務程序寫入。該文件的內容格式爲:
「recovery\n
<recovery command>\n
<recovery command>」
該文件存儲的就是一個字符串,必須以recovery\n開頭,不然這個字段的全部內容域會被忽略。「recovery\n」以後的部分,是/cache/recovery/command支持的命令。能夠將其理解爲Recovery操做過程當中對命令操做的備份。Recovery對其操做的過程爲:先讀取BCB而後讀取/cache/recovery/command,而後將兩者從新寫回BCB,這樣在進入Main system以前,確保操做被執行。在操做以後進入Main system以前,Recovery又會清空BCB的command域和recovery域,這樣確保重啓後再也不進入Recovery模式。
3、如何從Main System重啓並進入Recovery模式
咱們先看一下以上三個部分是怎樣進行通訊的,先看下圖:
咱們只看從Main System如何進入Recovery模式,其餘的通訊在後文中詳述。先從Main System開始看,當咱們在Main System使用update.zip包進行升級時,系統會重啓並進入Recovery模式。在系統重啓以前,咱們能夠看到,Main System定會向BCB中的command域寫入boot-recovery(粉紅色線),用來告知Bootloader重啓後進入recovery模式。這一步是必須的。至於Main System是否向recovery域寫入值咱們在源碼中不能確定這一點。即使如此,重啓進入Recovery模式後Bootloader會從/cache/recovery/command中讀取值並放入到BCB的recovery域。而Main System在重啓以前確定會向/cache/recovery/command中寫入Recovery將要進行的操做命令。
至此,咱們就大概知道了,在上層使用update.zip升級時,主系統是怎樣告知重啓後的系統進入Recovery模式的,以及在Recovery模式中完成什麼樣的操做。
下一篇開始分析第一個階段,即咱們在上層使用update.zip包升級時,Main System怎樣重啓並進入Recovery服務的細節流程。