之前需要處理一些應用程式用到的update相關問題, 瞭解到android build system會利用開源的bsdiff進行一些關於package的更新動作. 這篇文章就分析一下android系統的OTA update.
首先,讓我們來看看OTA的整體架構
Build System Support, 用來建立需要的OTA update image(包括全部更新及部分更新)
Releasetools (build/tools/releasetools/)
用以與build system配合,產生對應的full/incremental的update.zip包
對應的編譯指令碼在build/core/main.mk及Makefile, 搜尋target-files-package關鍵字
build/tools/releasetools
├── check_target_files_signatures -- 用來檢查cert和update包之間的關係
├── common.py -- 各種工具類,參數處理/META檔案處理/image產生/sign certification/patch file 操作等等
├── edify_generator.py -- 用來產生edify指令碼, 關於edify,參照bootable/recovery/edify/下的readme及tjworld,
主要是給manufacturer提供一個簡單的shell語言 來進行必要的recovery操作. 後面會單獨寫篇文章單獨描述一下edify的使用方法
<Android學習之edify是神馬>
├── img_from_target_files -- 由產生target zip file的製作被fastboot update命令所使用的xxx.img檔案
├── ota_from_target_files -- 產生經過各種簽名的TFP更新包
└── sign_target_files_apks -- 用來對apk或者產生測zip更新包進行簽名, 參照/development/pdk/docs/porting/release_keys.jdhttp://androidxref.com/source/xref/development/ 中的描述
方便把test-key轉換成OEM廠商的release key
使用make target-files-package來編譯update.zip, 產生的描述及image檔案在
out/target/product/generic/obj/PACKAGING/apkcerts_intermediates/full-apkcerts-eng.txt
out/target/product/generic/obj/PACKAGING/target_files_intermediates/full-target_files-eng.zip
這裡需要注意以上都是針對已經通過mkimage(system/core/mkbootimg)的工具產生了boot.img之後,來產生對應的recovery及update image.
上訴工具都不提功boot.img和update image之間的互動操作, 所以在製作update image時,要手動確保你製作的update image能夠被安裝在預先已經有boot image的device上!!!
同時, 這裡提供了給OEM的擴充介面, 可以使得OEM定義一些特有的操作, 並融合到update過程當中. 可以參照資料3的15頁的描述, 詳細的情況推薦參考CyanogenMod中nexus one中的如下實現:
CyanogenMod/device/htc/passion-common/BoardConfigCommon.mk中releasetools的擴充定義:TARGET_RELEASETOOLS_EXTENSIONS := device/htc/common
CyanogenMod/device/htc/common/updater/ -- 是OEM各自的updater實現
CyanogenMod/device/htc/common/releasetools.py -- 裡面都是一些必須要實現extension 介面, 如,FullOTA_Assertions()/FullOTA_InstallEnd()等
簡要描述了下update.zip的產生過程
這裡請注意, re-sign apks是為了apk的security, 用各個oem廠商的簽名替代Test的簽名.
簽名是使用openssl產生的帶public exponent 3 的 2048-bit RSA keys.
Related filesystem partition
談到Update,不得不提到android的分區情況(參見各個OEM的配置)
boot, 包含以下檔案:metadata, kernel image, ramdisk, optional 2nd-stage bootloader image, 由mkbooting(system/core/mkbooting)產生
關於boot.img的格式參見system/core/mkbooting/bootimg.h
[plain]
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
這個描述,在需要自己定製自己的rom,或者需要把自己編譯的kernel燒錄到手機上時,很有用. 參見<如何製作android nexus one的核心>
system, 系統程式及apk等等
data, 使用者資料, 會被factory reset clear
recovery, 為了恢複
misc, 包含Bootloader Control Block (BCB), recovery console通過它與bootloader互動
cache, 用來支援update的temp分區,及被特定apk作為temp來使
還有一個重要的檔案recovery.fstab, 用來為recovery console及releasetools提供能夠載入的檔案系統及對應的mount node
如下是nexus one的recovery.fstab
[plain]
# mount point fstype device [device2]
/boot mtd boot
/cache yaffs2 cache
/data yaffs2 userdata
/misc mtd misc
/recovery mtd recovery
/sdcard vfat /dev/block/mmcblk0p1 /dev/block/mmcblk0
/system yaffs2 system
/sd-ext ext4 /dev/block/mmcblk0p2
Device Side Support, 用來接收update image並通過recovery模式來更新
所有的代碼都在/bootable/recovery, 當然還是參照CyanogeMod中的代碼與真正的device比較接近.
因為這時,其實是一個完全獨立的小系統, 需要有自己的各種工具函數庫(不能使用linux,因為這時linux根本還沒開始運行, 這裡只是一個簡單軟硬體互動環境).
從中可以看到很多關於裁剪定製的例子.
後面會寫一篇專門分析andorid的bootloader和recovery的分析的文章,請參看<Android學習之bootloader>, <Android學習之recovery>
Recovery Console (RC)
這就是通過開機時,按住指定的鍵進入的recovery UI介面(經常刷機的,應該很熟悉)
是所有其它recovery工作的總入口, 管理所有recovery工作及與bootloader,framework中的RecoverySystem互動
這裡從nexus one中的實現與AOSP的實現可以看出, 大部分廠商都提供了自己的RC UI plugin從而作出各自的recovery UI.
參考資料5中的26頁給出了簡單更改Console UI的方法:)
bootloader
用來協助硬體初始化資源並更根據要求選擇進入RC還是Andorid系統
它除了跟RC互動,還會通過BCB接受從kenrel來的reboot notification(register_reboot_notifier()).
misc分區及其中的BCB
用來提供RC和bootloader之間的通訊環境及命令
Updater
它會包含在OTA update.zip檔案之中, 由recovery console控制執行具體的update動作(包括驗證, 解壓, 安裝)
同樣也提供了plugin的擴充機制, 允許各個廠商定製一些額外的updater動作
SW Update UI intent from Settings application
代碼在
RecoverySystem APIs
Server Side Support, 用來下發更新通知及具體需要更新的image
這裡是一塊黑地,沒有一家廠商公布了自己的push及deploy架構:(((
Update.zip OTA deploy
參考資料:
<Android學習之bootloader>
<Android學習之recovery>
<Android學習之自己動手定製bootloader+recovery>
AOSP source code
http://tjworld.net/wiki/Android/UpdaterScriptEdifyFunctions -- edify介紹
https://events.linuxfoundation.org/images/stories/pdf/lf_abs12_boie.pdf
摘自 Melody_lu123