Android A/B system - update_engine
Posted Dufre.WC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android A/B system - update_engine相关的知识,希望对你有一定的参考价值。
文章目录
android A/B System系列
update_engine overview
update engine是A/B update的核心逻辑,这一部分代码在system/update_engine
这里面。
- 在后台运行
- 会调用
bootctrl
HAL接口 - 通过
update_engine.rc
执行 - 不会修改partition table
update_engine_client
- 只是为了debug,进程会获取当前升级状态
update_verifier
- 通过update_verifier.rc执行
- 标记successful_flag,在misc分区
trigger update_engine to start update
升级命令:
python update_device.py --file update.zip
update.zip
里面有以下几个内容,其中脚本需要的是:
payload.bin
payload_properties.txt
通过adb,会传入升级需要的参数:
url
:升级包的位置offset
:payload.bin
在压缩包的偏移size
:payload_properties.txt
的sizeheaderKeyValuePairs
触发升级后,update engine
会做两件事:
Init()
boot_control_
(bootctrl HAL对应的应用层对象)hardware_
certificate_checker_
update_attempter_
(最核心的升级逻辑)prefs_
(保存进度的信息,假设升级的时候突然中断,重新恢复就是从prefs获取信息)
ApplyUpdatePayload()
BuildUpdateActions()
InstallPlanAction
DownloadAction
FilesystemVerfierAction
PostinstallRunnerAction
UpdateBootFlags()
检查当前slot是否已经标记为successful状态- 已经标记,执行
CompleteUpdateBootFlags()
- 没有标记,调用
MarkBootSuccessfulAsync()
标记successful,再执行CompleteUpdateBootFlags()
- 已经标记,执行
StartProcessing()
执行Action列表的每个Action
Action
升级的每个阶段都是通过Action来组织的,ActionProcess用来管理Action,在BuildUpdateActions()已经订好了Action的执行先后顺序:
InstallAction
DownloadAction
FileSystemVerifierAction
PostinstallRunnerAction
由下面的类图可以看出DownloadAction
FileSystemVerifierAction
PostinstallRunnerAction
是继承于InstallPlanAction
,执行完一个Action,会传递给下一个Action,install_plan
。
Action和Action的消息通过ActionPipe传递,每个Action都有两个ActionPipe,一个out,一个in。
InstallAction
InstallPlanAction
比较简单,仅仅将install_plan_
设置为了输出对象,传递给下一个Action
DownloadPlanAction
首先是看PerformAction()
函数,它首先获取InstallPlan
,对resume_payload_index_
,payload_
进行恢复,之后设置target_slot
为unboot
,最后开始downloading。
然后去恢复数据,prefs_会存储next_data_offset
,找到这个地方接着transfer数据,最后执行DeltaPerformer::Write()
去写入target slot。
下面是download_action.cc的逻辑,其核心逻辑是delta_performer.cc的Write函数。Write函数做了这么几件事:
UpdateOverallProgress()
ParsePayloadMetadata()
ParseManifestPartition()
OpenCurrentPartition()
ValidateOperationHash()
PerformXXXXXOperation()
PerformReplaceOperation()
PerformZeroOrDiscardOperation()
PerformMoveOperation()
PerformBsdiffOperation()
PerformSourceCopyOperation()
PerformSourceBsdiffOperation()
PerformPuffDiffOperation()
上面的步骤就是把payload.bin
按照下面的结构分解,写到flash中。
在Android A/B System -Generate OTA Package有讲到payload.bin
中的数据被组织成一个一个的operation,operation中有Type
信息,根据Type
,做不同的处理,然后写到flash中。
下面来看具体不同类型的operation是如何计算成真实的数据。
下面来看具体不同类型的operation是如何计算成真实的数据。
ZERO/DISCARD
PerformZeroOrDiscardOperation():
ZERO/DISCARD
这里比较简单,就是根据operation的每个Extent
中的start_block
和num_blocks
信息,写入zero.data()
。
REPLACE/REPLACE_BZ/REPLACE_XZ
PerformReplaceOperation()
:先把operation的数据取出来放进buffer
,根据类型选择不同的Writer
。
SOURCE_COPY
PerformSourceCopyOperation()
:
- 获取
block_num
和start_address
放进buffer
(既有source
的信息,也有target
的信息) - 从
source_partition
读block
到buffer
- 将
buffer
的内容写入target_partition
- 验证
operation
的source hash
SOURCE_BSDIFF/BROTLI_BSDIFF
PerformSourceBsdiffOperation()
:
- 获取
operation
的patch
到buffer
- 读取
source block
- 验证
source hash
- 打入
bspatch
并写入target partition
还有一点,在实际操作中,可以看到log中有执行进度的更新,这些操作数更新进度是怎么计算的呢?如下图所示:
For example:
- Partition A: 2 operations
- Partition B: 4 operations
- Partition C: 6 operations
那么num_total_operations_ = 2 + 4 + 6,acc_num_operations_ = 2, 6, 12
假设此时执行到了第2个操作,next_operation_num_
= 2,而2是等于acc_num_operations_[0]
的,而存放操作的数组是从0开始的,也就是说,当next_operation_num_
等于acc_num_operations_
时也就是说当前分区的操作已经执行完了,应该切换到下一个分区了,最后根据next_operation_num_
和acc_num_operations_
计算出操作类型的索引,获取对应的操作类型。
FilesystemVerifierAction
FilesystemVerifierAction
的作用有:
- 对target的所有partition做hash
- 计算出来的hash会和InstallPlan(也就是payload.bin)中的hash做验证(这个hash值也不是一次算出来,是每次读取一部分,就计算并更新一部分)
- 如果计算出来的hash,和升级包中的hash不匹配,会重新计算source partition的hash,会返回error。
PostinstallRunnerAction
PostinstallRunnerAction
运行download update的postinstall
脚本,并且调用bootctrl HAL
的SetActiveBootSlot()
去将slot切换为target,那下次就是从target启动了。
以上是关于Android A/B system - update_engine的主要内容,如果未能解决你的问题,请参考以下文章
Android A/B System - Generate OTA Package
Android A/B system - update_engine
Android A/B system - update_engine