第二十八章:OTA升级与Recovery模式

OTA升级,说白了就是手机系统空中升级。你想想看,手机厂商推送一个新版本,你点一下「立即更新」,过几分钟重启后系统就变了——这背后其实是一套非常精密的工程机制。

我最早接触OTA时,觉得不就是下载个包、解压、覆盖文件吗?后来踩了坑才发现,这里面的门道多着呢。尤其是AB分区和无缝升级,简直是Android系统最优雅的设计之一。

OTA包结构:payload 到底装了什么?

一个完整的OTA包,通常是一个zip文件。你把它解压开,会看到这些东西:

  • META-INF/ — 签名和证书,保证包没被篡改
  • payload.bin — 真正的升级数据,二进制格式
  • payload_properties.txt — 元信息,比如文件大小、哈希值
  • care_map.pb — 哪些分区需要校验,后面会细说

payload.bin 是核心。它里面包含了对每个分区的操作指令:是写入、是删除、还是替换某个块。我习惯把 payload 理解成「增量补丁」——它只记录新旧版本之间的差异,而不是把整个系统镜像重新发一遍。

关键点:OTA包分为全量包和增量包。全量包是完整的系统镜像,增量包只包含差异数据。增量包体积小,但依赖当前系统版本,不能跨版本升级。

举个例子,你从 Android 12 升到 12.1,增量包可能只有 200MB。但如果你从 11 直接跳到 12.1,那就必须用全量包,可能 1.5GB 起步。

AB分区与无缝升级:重启即新系统

AB分区,也叫无缝升级。它的核心思想很简单:系统有两套分区,一套是当前运行的(Slot A),另一套是备用的(Slot B)。

升级时,系统在后台把新版本写入备用分区。你该用手机还用手机,完全不受影响。等写入完成,你点一下重启,bootloader 自动切换到新分区,系统就起来了。

我曾经在项目里遇到过一个问题:用户升级到一半,手机没电了。如果是传统单分区方案,手机就变砖了。但AB分区方案下,升级失败只是备用分区没写好,当前分区还是好的,手机照样能启动。这就是AB分区最大的价值——永不砖机

特性 传统单分区 AB分区
升级时能否使用手机 不能,必须进入Recovery 可以,后台静默升级
升级失败后果 可能变砖 回退到旧系统,安全
存储空间占用 一套分区 两套分区,多占约1.5GB
重启后生效

嗯,这里要注意:AB分区虽然好,但也不是没有代价。它需要额外的存储空间。对于低端机来说,多占 1.5GB 可能是个不小的负担。所以 Google 后来推出了虚拟AB分区,用动态分区来模拟,既保留了无缝升级的优点,又节省了空间。

Recovery模式原理:一个迷你的Linux系统

Recovery模式,说白了就是一个独立的、精简的Linux系统。它运行在内存中,不依赖你手机里的主系统。所以即使主系统坏了,Recovery 还能工作。

Recovery 的核心组件包括:

  • bootloader — 负责加载 Recovery 内核
  • recovery内核 — 一个独立的 kernel,通常和主系统内核一样
  • recovery ramdisk — 包含 init 进程、recovery 二进制文件、UI 资源
  • /sdcard — 挂载用户数据分区,用于读取OTA包

Recovery 的工作流程是这样的:

  1. 用户选择「重启到Recovery」或系统检测到升级失败
  2. bootloader 读取 misc 分区,判断要进入哪个模式
  3. 加载 recovery 内核和 ramdisk
  4. init 进程启动,挂载必要的分区
  5. recovery 程序开始执行,显示菜单或自动升级

我印象很深的一次:有个设备在OTA升级后无法开机,log 显示是 system 分区校验失败。我进 Recovery 手动挂载分区,发现是升级过程中断电导致数据没写完整。最后用 adb sideload 重新推送了一次包才救回来。

注意:不要随意修改 Recovery 分区。我曾经见过有人为了刷机把 Recovery 替换成第三方版本,结果官方 OTA 升级时签名校验失败,设备直接变砖。Recovery 是最后的救命稻草,请保持它的纯净。

update_engine 与 update_verifier:升级的幕后推手

update_engine 是 Android 系统中负责执行 OTA 升级的核心守护进程。它运行在后台,负责下载 payload、解析操作指令、写入分区。

它的工作流程大致如下:

  1. 接收来自 SystemUpdateService 的升级指令
  2. 下载 payload.bin 到 /data/ota_package/
  3. 校验 payload 的签名和哈希
  4. 解析 payload,生成操作列表
  5. 逐个分区执行写入操作
  6. 写入完成后,更新 slot 标记,通知 bootloader 下次从新分区启动

update_verifier 则负责在升级完成后做校验。它会在系统首次启动时,检查关键分区(如 system、vendor)的完整性。如果发现校验失败,会触发回滚机制。

我习惯把 update_verifier 比作「质检员」——它不参与生产,但负责把关。没有它,你永远不知道升级后的系统是不是完整的。

小技巧:调试 OTA 问题时,可以查看 /data/misc/update_engine/log/ 下的日志。update_engine 的日志非常详细,会记录每一步操作和错误码。我曾经靠这个日志定位到一个分区大小不匹配的问题,省了两天排查时间。

核心知识体系

下面这张图,我把本章的核心逻辑画了出来。你可以看到 OTA 升级从下载到生效的完整链路:

OTA升级核心流程 OTA包 payload.bin + 签名 update_engine 解析payload,写入分区 AB分区写入 Slot A / Slot B 重启系统 update_verifier 校验分区完整性 校验失败 → 回滚 校验成功 → 正常启动 整个流程从下载OTA包到最终启动,环环相扣,任何一个环节出错都有对应的容错机制

从这张图你可以看到,OTA升级不是简单的「下载-安装-重启」三步走。它背后有 update_engine 做执行引擎,有 AB 分区做容错保障,有 update_verifier 做质量把关。每一层都有自己的职责,环环相扣。

我个人觉得,理解 OTA 升级的关键不在于记住每个组件的名字,而在于理解它的设计哲学——安全第一,用户体验第二。所有复杂的设计,最终都是为了让你在升级过程中不丢数据、不砖机、不影响使用。

好了,这一章的内容就到这里。如果你在实际项目中遇到 OTA 相关的问题,欢迎随时交流。记住,多看 log,多分析 payload,很多问题其实没那么复杂。


公众号:蓝海资料掘金营,微信deep3321