android系统更新原理简介
简介:
Android系统更新简而言之就是将升级包从服务器下载到本地然后对当前系统进行升级的过程,主要包括三大块:升级包、应用层、recovery层。
主要功能流程如下如所示:
- 升级包:
版本编译完成后会生成target_file,这里的名称是:ota_target,升级包就是使用源版本的target_file跟目标版本的target_file通过imgdiff/bsdiff工具完成两个img文件的对比差分,做出升级所需的.new.dat、.patch.dat、.transfer.list文件,目录结构如下:
升级包解压后目录结构如下:
升级脚本和升级执行文件位于META-INF\com\google\android中
其中updater-script记录了升级时候需要执行的命令
update-binary则负责具体执行脚本中的命令语句
META-INFO下的CERT.RSA CERT.SF MANIFEST.MF三个文件用于在recovery执行代码中的校验过程
.img.p文件为特定分区的镜像升级文件
.new.dat .patch.dat .transfer.list三个文件共同负责完成一个分区的升级,比如升级system分区的文件为:system.new.dat system.patch.dat system.transfer.list
其在升级脚本中的升级命令为:
block_image_update(map_partition("system"),package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat") ||abort("E1001: Failed to update system image.");
升级包的编译命令为:
./build/tools/releasetools/ota_from_target_files -i source.zip target.zip ota.zip
Source.zip是源版本的targetfile,target.zip是目标版本的targetfile o,out.zip是生成的升级包文件名。
编译脚本build\tools\releasetools\ota_from_target_files.py
升级包编译大体流程如下图:
主要执行文件如下:
ota_from_target_files:主要的方法入口和控制逻辑都在这里
common:其中定义了很多需要用到的方法和子类,比如Options类,承载了很多设置项,信息字典的加载,patch的生成方法都在这里
blockimgdiff:生成增量升级文件
edify_generator: 生成update_script升级脚本
以编译增量包为例,生成增量包的WriteBlockIncrementalOTAPackage详细解释如下:
升级包编译完成后用于应用层的部署、下载、进入升级。
- 应用层:
应用层主要包括三部分:服务器,OTA客户端,升级相关framework层。
服务器:主要作为升级包的远端下载仓库,处理客户端请求,下发升级包下载地址和升级包描述信息给客户端,这其中还包括一些运营策略,比如各种黑白名单,也兼有数据统计功能,一般各大厂商都会将系统更新客户端作为必备应用集成到系统分区中。
OTA客户端:客户端主要功能为定期请求服务器,检索可用更新,下载升级包后执行调用升级接口。单就OTA功能来说客户端逻辑其实非常简单,但是往往都为了确保发布版本的升级率会各大厂商都会做很多的运营策略,也就直接增加了客户端的功能与代码逻辑。
升级相关framework层:主要负责调用重启接口,将重启原因传入底层,写入misc启动命令
Framework中与升级相关的代码主要在如下类中:
RecoverySystem:包含升级相关方法
RecoverySystemService:包含读写bcb与uncrypt方法
OppoRecoverySystem:oppo封装类,功能与RecoverySystem相似
Framework层主要升级流程如下:
Framework层最终的主要操作都集中在以下几句代码中:
SystemProperties.set("ctl.start", "setup-bcb");
SystemProperties.set("ctl.start", "uncrypt");
SystemProperties.set("sys.powerctl", "reboot," + reason); 这里reason值recovery
其中setup-bcb服务会将升级命令升级包地址写入到/misc分区中,在bootloader阶段,会根据该启动命令来决定是进入recovery系统还是进入android系统。
uncrypt涉及到data分区加密,会将位于data分区下的加密后的升级包进行解密,解密后以block.map的形式呈现。
修改属性通过init进程中的property_service来实现,这里会根据属性名称来确定是单纯的修改属性内容还是拉起对应的服务或者执行操作。
三、Recovery层:
升级操作的实现层是在recovery中,recovery下代码包含了多个子模块,几个重要的子模块如下:
Recovery_ui: 负责绘制recovery过程的界面显示
applypatch: 应用升级包中的patch文件进行升级,包括.p, .img, .data文件
bootloader_message: 读写启动loader启动命令,framework中调用到的setup-bcb最终就是在该模块下实现
edify: 一种新的脚本语言主要负责解释update_script升级脚本
install: 实现升级包的安装流程
recovery_ui、miniui:负责升级过程的升级界面展示
uncrypt:提供uncrypt、setup-bcb、clear-bcb三个服务实现读写bcb,解密升级包
updater : 升级包中的META-INF\com\google\android\update-binary就是该模块编译生成,负责执行升级包升级
Recovery下的执行流程如下图:
Recovery的主要流程可以概括为:
- 解密升级包,R版本改成了decryptFile方法来解密,之前旧版本是通过uncrypt服务来执行解密
- 校验升级包签名verify_package
- try_update_binary中调用update_binary可执行文件执行升级
- update_binary中解析update-script脚本执行升级命令
- 升级完成重启
try_update_binary简略代码如下:
update_binary由updater下的文件编译生成,主要负责执行具体的升级过程,其中解析升级脚本语言使用的是edify中定义的脚本语言,主函数中代码如下:
方法注册完成后脚本中的命令都可以找到对应的函数来处理,这样一来,update-script脚本中的语句每一行都可以被执行到:
比如脚本中有如下语句:
show_progress(0.650000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat.br", "system.patch.dat") ||abort("E1001: Failed to update system image.");
对应的方法有:
对应执行的函数:ShowProgressFn,UIPrintFn,BlockImageUpdateFn
update_binary可执行文件运行完成后,会将结果返回给父进程recovery,然后recovery就会重启设备,这样一次系统更新就算是完成了。