当前位置: 首页 > article >正文

Android OTA升级

针对Android系统OTA升级,MTK平台有相关介绍文档:https://online.mediatek.com/apps/faq/detail?faqid=FAQ27117&list=SW

概念一:OTA包的构建

  •  AOSP full build:Android原生提供的全量包的构建,意思就是可以从任何一个比它老的版本通过OTA升级到此版本,因为是全量,所以通常这类包的大小和平时的镜像文件差不多大
  • MTK split build:MTK提供的增量包的构建,即针对两个固定版本之间的差异制作而成的,因此它只能在固定两个版本之间进行OTA升级,因为是差分增量,所以通常这类包的大小和两个版本的差异相关,可以小到几M,在不发达的国家因为网络条件比较差,通常采用此方式进行推送

概念二:AB系统

  • AB系统:AB系统并不是一个系统,Google官方把其描述为A/B无缝系统更新,MTK喜欢把带有此功能的软件配置称为AB系统,即当前软件支持AB系统更新。开启此功能的系统可以实现A/B无缝更新功能,即在不重启或者进入recovery模式下进行OTA更新,即你可以一边正常使用手机,后台守护进程update_engine来进行更新,所以叫做无缝更新。其原理是底层使用了两套分区,详细概念可以参考:A/B(无缝)系统更新  |  Android Open Source Project
  • No-AB系统:MTK吧不支持A/B无缝系统更新的软件版本称为No-AB系统,从Google角度,A/B无缝功能在Android 7就开始有了,但是直到Android 13要求强制支持使能,即现在的系统都是强制开启了此功能。开启此功能的系统,ro.build.ab_update属性被设置为true

概念三:OTA升级的方式

  • Recovery Mode:进入Recovery模式进行升级,此种方式在AB系统和No-AB系统上都可以使用,此方式需要进入recovery模式,因此升级过程中,用户肯定是无法使用的。

Recovery UI可以提供SD卡方式和adb sideload d:\update.zip方式进行升级

三方应用可以通过调用android.os.RecoverySystem$installPackage接口实现

  • Update Engine:它是Google为了实现A/B无缝更新新造了一个守护进程,因此只有在AB系统上才能使用此方式,此方式不需要进入recovery或者重启,升级过程中你可以继续使用手机,update_engine升级完毕之后会设置标记位,在下一次重启之后就会进入对应的分区槽启动系统

三方应用可以通过调用android.osUpdateEngine$applyPayload接口实现

注意一:AB系统通过Recovery方式升级,升级包放在/data目录无法被挂载

注意二:AB系统不建议使用Recovery方式进行升级,参考MTK案例

一、Recovery OTA流程

1、processPackage 解密升级包

如上代码逻辑,只针对/data目录下面的升级包进行处理,中间写了处理监听器progressListener传递到uncrypt方法中用来在UI界面显示进度条,其uncrypt在RecoverySystemService中实现:

如上代码在RecoverySystemService中实现,正常的recovery升级日志中将会有如下sys日志打印:

2、verifyPackage 校验升级包

3、installPackage 安装升级包

如上代码安装升级包通常以关键日志开始,但是此打印在main日志中:

接下来的流程如下

1)data目录固定block.map路径

如果processed为true表示已经对升级包进行了处理,这个时候如果block.map不存在直接报错;如果processed为false,会将升级包的路径写入到uncrypt_file文件中,并且删除block.map文件。

这里有点疑问?为什么processed为false的时候会直接删除block.map,接下来为拼接的命令路径又是/cache/recovery/block.map呢?这会导致进入recovery系统的时候根本就挂载不上此文件,从上文的注释来看升级包位于/data目录的话通过block.map来记录升级包路径,这逻辑有点前后矛盾。block.map到底有什么意义?

2)主系统向recovery系统写命令

这段代码先是拼接了command,如下为升级包放在/data目录下的命令,可以看出这个命令是给到native层的recovery进程使用,recovery进程接受擦除升级等命令,其中__update_package看起来就是升级命令,其recovery日志如下:

3)主系统的systemservice进程如何与recovery系统通信?

main系统和recovery系统实际上是两个不同的系统,他们的载体也是不同的分区,所以可以把他们当成永不相交的两个平行世界,在系统启动的时候bootloader会根据标识来选择进入哪一套系统,他们都会启动他们自己的init进程,以及其他一些服务例如adb。他们之间的通信和交互如下:

接下来看看main系统是如何把这个command和升级包传递到recovery小系统的呢?如上图,他们通过/cache/recovery为媒介进行交互,其中main系统调用的BCB就是其中的大功臣。

如上代码获取了RecoverySystemService的实例执行rs.setupBcb(command)):

通过socket的通信方式,其socket定义为/dev/socket/uncrypt,这一块详细流程参考:

https://www.cnblogs.com/liang123/p/6325225.html

4)为升级包申请元数据

最开始看这里的代码觉得很奇怪,传递的升级包绝对路径的名称,然后new ZipFile,根据提示来看这里的文件还不能超过100MB,当时想的是随便一个全量升级包都超过100M呢,最后仔细观察如上圈红代码,是从获取升级包的元数据。此段逻辑在日志中也有体现,如下main日志:

5)重启进入recovery系统

这里调用了PowerManager的reboot命令进行重启,并且重启原因为recovery升级,如下日志:

为什么需要调用reboot才能进入recovery模式,因为recovery小系统和main系统根本就是两个世界,如下reboot之后的系统启动流程图:

4、uncrypt进程解析

Native层的uncrypt进程的在rc中的定义,从其主函数可以看出来他主要具有三种功能,其触发场景分别如下:

1)uncrypt_wrapper:RecoverySystem$processPackage进行解密

前文介绍processPackage的时候已经说明了,RecoverySystem对升级包的处理,实际上就是对升级包进行加密处理,但实际实现逻辑的进程就是uncrypt进程,如下processPackage是如何调用到uncrypt解密处理:

即对升级包处理完成之后会创建写入到/cache/recovery/block.map文件中,如下日志:

为什么需要对data目录的升级包进行uncrypt解密处理呢?

随着android系统的更新,在android7.0中,recovery模式中已经不在挂载data分区,而且data分区可以设置加密,这样更促进了在recovery分区中不挂载data分区,加强了用户的安全性。但是这样就会有问题,当升级包较大时cache分区是放不下的,增大cache分区只会浪费资源,最好的办法还是把它放在data分区下。但是因为加密和不挂载的原因导致在recovery模式下是无法使用升级包的。而uncrypt机制就是解决这个问题的。它的基本原理就是,在正常模式下记录升级包所在的磁盘区块号,而且如果加密了就通过读进行解密,再绕过加密写到存储磁盘上。当记录好了磁盘区块号后,启动到recovery模式后就可以不挂载data分区,直接根据区块号读取升级包中的数据进行升级。下面记录代码的分析流程。

https://www.cnblogs.com/startkey/articles/11213034.html此篇文章对齐做了详细的说明

2)setup-bcb:RecoverySystem$installPackage设置recovery命令

如上在调用installPackage接收到RecoverySystemService发来的命令写入到bootloader的域中,最后重启后bootloader根据此命令来启动recovery小系统,并将命令传递给recovery进程。如上逻辑对应日志如下:

3)clear-bcb:RecoverySystem$installPackage状态恢复

RecoverySystem$installPackage

5、Recovery进程解析

这里的Starting recovery日志只是说明recovery进程被启动,如下日志:

1)Recovery相关功能介绍

start_recovery函数被定义在system/bootable/recovery/recovery.cpp,此文件没有单独的main,因此此部分逻辑还是属于recovery进程的,通过注释可以了解到此文件主要实现ota升级和恢复出厂设置两大功能:

如上文的recovery.log中讲解析RecoverySystemService传递过来的命令:

Command: "/system/bin/recovery" "--update_package=@/cache/recovery/block.map" "--locale=en-US"

2)update_package执行升级流程

Recovery.log对应的日志如下:

3)Recovery OTA升级的真正逻辑

6、Recovery分区挂载

1)读取分区表配置文件

2)特殊分区的检查

注意:AB系统已经不支持cache了,所以AB系统这里的日志绝对会挂载失败,但奇怪的是,我进入recovery模式还是能够进入cache目录,如下recovery.log:

3)打印分区列表

recovery.log日志如下:

4)分区表配置文件的生成

根据如上代码可以了解到分区表配置文件路径/etc/recovery.fstab,我们可以进入recovery模式执行如下命令:adb pull /etc/recovery.fstab,如下内容

连续pull了多台机器的recovery分区表,但是和代码中配置的格式完全不一样,最初以为是从代码里面直接copy过去的,结果完全搜索不到关键字

根据如下文档了解到由TARGET_RECOVERY_FSTAB拼接出来的,详情可以参考:

https://blog.csdn.net/xiaocui92/article/details/79161206

7、案例

问题描述:客户自己开发的三方应用,通过调用android.os.RecoverySystem$installPackage接口进行OTA升级,此接口传递的OTA升级包路径为/data/media/0/Download/update.zip,升级失败

以往案例:通过CSDN搜索此类问题,之前的案例基本上是AVC Selinux权限导致的block.map文件没有成功写入到recovery模式下,可以参考链接:

https://blog.csdn.net/tkwxty/article/details/106101317

最后结论:反复做了测试,在main系统的时候,/cache/recovery/block.map文件存在,但进入recovery系统的时候,/cache目录下是空的,从官方文档得来,AB系统目前并不支持把升级包放到/data目录,原文如下:

二、UpdateEngine OTA流程


http://www.kler.cn/news/327219.html

相关文章:

  • excel快速入门(二)
  • Redis缓存技术 基础第二篇(Redis的Java客户端)
  • Ingress Gateway 它负责处理进入集群的 HTTP 和 TCP 流量
  • 七星创客:重塑商业模式认知
  • 在 Linux 中,要让某一个线程或进程排他性地独占一个 CPU
  • AI芯片WT2605C赋能厨房家电,在线对话操控,引领智能烹饪新体验:尽享高效便捷生活
  • Linux:文件描述符介绍
  • 【SpringBoot详细教程】-08-MybatisPlus详细教程以及SpringBoot整合Mybatis-plus【持续更新】
  • 端点安全服务:全面的端点安全解决方案
  • 初识CyberBattleSim
  • sql语法学习 sql各种语法 sql增删改查 数据库各种操作 数据库指令
  • 自动化测试中如何精确模拟富文本编辑器中的输入与提交?
  • Pytorch-LSTM轴承故障一维信号分类(一)
  • 如何在 Amazon EMR 中运行 Flink CDC Pipeline Connector
  • 【笔记】如何将本地的.md变成不影响阅读的类pdf模式
  • COMP 6714-Info Retrieval and Web Search笔记week2
  • 解决 Android WebView 无法加载 H5 页面常见问题的实用指南
  • Another redis desktop manager使用说明
  • 在IntelliJ IDEA中设置文件自动定位
  • 劳易测ODT3CL1-2M漫反射传感器荣获 “2024 MM《现代制造》创新产品奖”
  • AWS Network Firewall - IGW方式配置只应许白名单域名出入站
  • SQL进阶技巧:影院2人相邻的座位如何预定?
  • QT将QBytearray的data()指针赋值给结构体指针变量后数据不正确的问题
  • Brave编译指南2024 MacOS篇-构建与运行(六)
  • 正则表达式的使用规则
  • Linux —— Socket编程(三)
  • 深入理解 C++11 Lambda 表达式及其捕获列表
  • Lombok同时使⽤@Data和@Builder遇到的坑
  • 0基础学习PyTorch——监控机器学习的可视化工具
  • PostgreSQL 字段使用pglz压缩测试