分析Recovery流程,可從分析升級包入手。
升級包可由 make otapackage命令產生,由Makefile和打包指令碼(Python)配合產生。
建置規則比較複雜,其中包含了簽名過程,細節不表,主要關注它的內容。
升級包解壓後結構如下:
/home/simba/update_zip|-- boot.img|-- Manifest.xml|-- META-INF| |-- CERT.RSA| |-- CERT.SF| |-- com| | |-- android| | | `-- metadata| | `-- google| | `-- android| | |-- update-binary| | `-- updater-script| `-- MANIFEST.MF|-- recovery| |-- etc| | `-- install-recovery.sh| `-- recovery-from-boot.p`-- system |-- app |-- bin |-- build.prop |-- etc |-- fonts |-- framework |-- lib |-- media |-- usr `-- xbin66 directories, 1025 files
以上結構圖中省略了很多條目,都是system目錄下的檔案和目錄。
其中重要的指令檔有:
- META-INF/com/google/android/updater-script
- recovery/etc/install-recovery.sh
升級來源檔案:
- boot.img
- /system
- recovery/recovery-from-boot.p
另一個很重要的檔案是/etc/recovery.fstab,內容由EMMC資料分割配置確定。
-------- /etc/recovery.fstab -----------/boot emmc/dev/block/mmcblk0p1/sdcard vfat/dev/block/mmcblk0p4/recovery emmc/dev/block/mmcblk0p2/system ext4/dev/block/mmcblk0p5/cache ext4/dev/block/mmcblk0p6/data ext4/dev/block/mmcblk0p7/misc emmc/dev/block/mmcblk0p9--------------------------------------------
otgpackage編譯指令碼會根據這個檔案填充updater-script,後面可以看到。
這個檔案存在於recovery分區中,進入recovery模式後,可以訪問到它。
進入recovery模式的方式多種多樣,但每種方式都需要bootloader的配合。
進入recovery模式後會對升級包進行驗證,過程不表,失敗退出。
進入recovery流程後,主要關心updater-script的工作。
首先是updater-script,代碼中可以很容易分析出他的工作流程,如下:
--------- updater-script ----------------....//省略若干format("ext4", "EMMC", "/dev/block/mmcblk0p5", "0");mount("ext4", "EMMC", "/dev/block/mmcblk0p5", "/system");//掛載system分區。這裡有"/dev/block/mmcblk0p5"和"/system"的對應關係,來源於前文提到的recovery.fstab。package_extract_dir("recovery", "/system");//將zip包中的recovery目錄解壓到系統/system目錄,將來升級recovery分區時使用(install-recovery.sh,recovery-from-boot.p)package_extract_dir("system", "/system");//將zip包中的system目錄解壓到系統/system目錄,完成system分區的升級......//省略若干symlink("mksh", "/system/bin/sh");symlink("toolbox", "/system/bin/cat", ....);//建立軟連結,省略若干retouch_binaries("/system/lib/libbluedroid.so", .....);//再摸一下各種動態庫,省略若干set_perm_recursive(0, 0, 0755, 0644, "/system");......//修改許可權,省略若干show_progress(0.200000, 0);//顯示升級進度......//修改許可權,省略若干package_extract_file("boot.img", "/dev/block/mmcblk0p1");//將boot.img解壓到相應block裝置,完成boot分區的升級。boot分區包含了kernel + ramdiskshow_progress(0.100000, 0);unmount("/system");//卸載system分區---------------------------------------------
system分區和boot升級完成,接下來重啟,進入正常系統。
正常啟動的系統init.rc中定義了一個用於燒寫recovery分區的服務,也就是執行install-recovery.sh,每次啟動都要執行一次。
----- /init.rc ------...service flash_recovery /system/etc/install-recovery.sh class main oneshot...--------------------
install-recovery.sh 是recovery模式中updater-script解壓出來的,內容如下:
------- /system/etc/install-recovery.sh ----#!/system/bin/sh log -t recovery "Before sha1.... Simba...."if ! applypatch -c EMMC:/dev/block/mmcblk0p2:4642816:c125924fef5a1351c9041ac9e1d6fd1f9738ff77; then log -t recovery "Installing new recovery image__From Simba..." applypatch EMMC:/dev/block/mmcblk0p1:3870720:aee24fadd281e9e2bd4883ee9962a86fc345dcab EMMC:/dev/block/mmcblk0p2 c125924fef5a1351c9041ac9e1d6fd1f9738ff77 4642816 aee24fadd281e9e2bd4883ee9962a86fc345dcab:/system/recovery-from-boot.pelse log -t recovery "Recovery image already installed__From Simba..."fi-------------------------------------------
執行 make otapackage命令時,編譯指令碼比較boot.img和recovery.img得出patch檔案recovery-from-boot.p。
recovery-from-boot.p也是在recovery模式中updater-script解壓到system目錄的。
install-recovery.sh指令碼就是使用這個patch加上boot分區,更新recovery分區。
應用patch前,install-recovery.sh會計算當前recovery分區的sha1。
若計算結果與指令碼中記錄的相同(c125924fef5a1351c9041ac9e1d6fd1f9738ff77),說明已經更新過了,不再操作。
這樣就完成了/system目錄,boot分區(kernel + ramdisk),recovery分區(kernel + ramdisk-recovery)的升級。
以上是標準的Android升級流程,我們自己添加的分區可以參考以上幾種方式實現。自訂的分區採用何種升級方式需要細細考量,關係到升級包的內容結構和簽名過程。