2、基础知识:Android系统分区布局、bootloader、recovery模式、A/B系统等核心术语

在深入Android OTA远程升级的实现细节之前,必须先建立一套统一的术语体系和底层架构认知。OTA升级并非简单的文件拷贝,而是涉及系统启动链、分区读写策略、异常恢复机制以及硬件抽象层的复杂系统工程。本章将围绕四个核心维度展开:Android系统分区布局、Bootloader的引导职责、Recovery模式的双重角色,以及A/B(无缝)系统的设计哲学。理解这些基础概念,是后续分析升级脚本、差分算法、签名校验和失败回滚的前提。

Android 启动与升级核心架构关系图 Bootloader 引导加载程序 • 初始化硬件 • 验证 boot 分区签名 • 选择启动槽位 (slot) • 传递启动参数 (受 tamper 保护) Recovery 模式 独立小系统 • 应用 OTA 包 • 执行 wipe data/factory reset • 日志输出 /cache/recovery • 从 boot 分区启动 (非 A/B 设备核心) A/B 系统 无缝升级 • 双槽位 (slot A/B) • 后台写入非活动槽 • 重启切换槽位 • 失败自动回滚 (无需 recovery 介入) Android 系统分区布局 (典型 eMMC/UFS) boot system vendor recovery cache userdata 内核+ramdisk 系统镜像 厂商驱动 恢复系统 OTA缓存 用户数据 启动引导 传统升级路径 直接写入非活动槽 boot 分区 Bootloader Recovery A/B 槽位 物理分区

2.1 Android系统分区布局:升级操作的对象

Android设备内部存储(eMMC或UFS)被划分为多个固定大小的逻辑区域,称为分区。每个分区承载特定功能,且挂载点、文件系统格式和读写权限各不相同。OTA升级的本质,就是精确地重写这些分区中的部分或全部数据块。因此,理解分区布局是分析升级包内容、判断升级影响范围的基础。

核心分区及其职责

分区名挂载点文件系统主要职责OTA升级影响
boot无(直接加载)原始镜像Linux内核 + ramdisk(含init进程)内核更新时重写
system/systemext4 / erofsAndroid框架、系统应用、核心库主要升级对象
vendor/vendorext4 / erofs硬件抽象层(HAL)、厂商专有库驱动更新时重写
recovery独立系统原始镜像恢复模式内核和ramdisk非A/B设备升级时使用
cache/cacheext4OTA包暂存、恢复日志升级前可能被清空
userdata/dataf2fs / ext4用户应用、设置、数据库通常不参与升级
misc无原始启动控制信息(如bootloader message)记录升级状态

现代Android设备还引入了system-as-root机制,即system分区直接作为根文件系统挂载,而ramdisk被合并进system分区。此外,动态分区(Dynamic Partition)技术允许system、vendor、product等逻辑分区在super物理分区内动态调整大小,这进一步增加了OTA脚本的复杂度——升级包必须处理逻辑分区的大小调整和快照操作。

实战要点:在分析OTA升级包时,首先查看updater-script中的block_image_update命令,它会明确列出需要写入的分区名和偏移量。如果升级包同时包含system和vendor的补丁,说明这是一次框架+驱动的联合升级。

2.2 Bootloader:启动链的守门人

Bootloader是设备上电后执行的第一段代码,通常存储在专用的启动ROM或分区中。它的核心职责并非“加载系统”,而是验证并引导下一个启动阶段。在OTA升级场景中,Bootloader扮演着两个关键角色:一是决定从哪个槽位启动(A/B设备),二是校验boot分区的完整性和签名。

启动流程与校验机制

  1. 硬件初始化:设置CPU、内存控制器、时钟频率,建立最小运行环境。
  2. 读取启动配置:从misc分区读取bootloader message,判断是正常启动还是进入recovery。
  3. 槽位选择(A/B设备):读取misc分区中的slot信息,根据bootctrl HAL提供的状态决定启动槽。
  4. 签名验证:使用公钥验证boot分区头部和内核镜像的签名,防止篡改。
  5. 加载并跳转:将内核和ramdisk加载到内存,设置启动参数,跳转到内核入口。

对于非A/B设备,Bootloader还会检查recovery分区是否存在且有效。如果用户通过按键组合触发恢复模式,Bootloader会直接加载recovery分区而不是boot分区。

风险提示:Bootloader本身通常不参与OTA升级(除非是bootloader分区更新)。一旦Bootloader损坏,设备将变砖且无法通过软件方式恢复。因此,OTA升级包极少包含bootloader镜像,除非是修复严重安全漏洞。

2.3 Recovery模式:传统升级的执行者

Recovery是一个独立于主系统的微型Linux环境,包含自己的内核和ramdisk。在非A/B设备上,Recovery是OTA升级的核心执行者;在A/B设备上,Recovery退化为备用工具,主要用于工厂重置和诊断。

Recovery的工作流程

  • 接收命令:通过/cache/recovery/command文件接收升级指令,内容如--update_package=/sdcard/ota.zip。
  • 挂载分区:挂载/cache和/misc分区,读取升级包和状态信息。
  • 执行升级脚本:解析META-INF/com/google/android/updater-script,逐条执行分区写入、权限设置、符号链接创建等操作。
  • 写入日志:将升级过程输出到/cache/recovery/log,供后续排障。
  • 重启:升级完成后,清除command文件并重启进入新系统。

Recovery模式的一个关键限制是无法并发读写——在升级过程中,目标分区必须处于未挂载状态。这意味着升级期间系统完全不可用,用户会看到经典的“机器人倒地”界面,且升级时间较长(通常3-10分钟)。

案例拆解:某设备升级失败,卡在recovery界面。通过adb shell进入recovery环境,查看/cache/recovery/log发现错误:E:failed to verify whole-file signature。进一步检查发现,OTA包在下载过程中被截断,导致SHA-256校验失败。重新下载完整包后升级成功。此案例说明,Recovery的签名校验是防止损坏包写入的关键防线。

2.4 A/B系统:无缝升级的工程革命

A/B(Seamless)系统将系统分区划分为A和B两个槽位,每个槽位包含完整的boot、system、vendor等分区。设备当前从活动槽启动,OTA升级则在后台将新系统写入非活动槽。升级完成后,只需重启并切换槽位即可生效。

A/B系统的核心优势与代价

维度传统模式(非A/B)A/B模式
升级过程可用性不可用(需进入recovery)完全可用(后台写入)
失败回滚困难,可能变砖自动回滚到上一个槽位
存储占用单份系统空间双份系统空间(约增加2-4GB)
升级时间感知用户等待3-10分钟后台下载+写入,重启仅需几秒
recovery依赖核心依赖仅作为备用

A/B系统的关键机制是槽位切换。Bootloader通过读取misc分区中的slot_suffix(如“_a”或“_b”)决定启动哪个槽位。升级时,update_engine服务将新系统写入非活动槽,并在misc分区标记该槽位为“可启动”。重启后,Bootloader尝试从新槽位启动;如果启动失败(如内核panic),Bootloader会自动回退到旧槽位。

工程实践:某A/B设备在升级后出现Wi-Fi无法开启的问题。系统并未自动回滚,因为内核和框架启动正常,只是HAL驱动异常。此时需要手动回滚:adb root; adb shell update_engine_client --rollback。该命令会将活动槽位切换回旧版本,并标记新槽位为不可用。此案例说明,A/B回滚机制主要针对“无法启动”级别的故障,对于功能性问题仍需人工干预。

A/B系统还引入了合并系统(Merge System)概念,即升级包可以只包含差异数据,通过update_engine的Cow(Copy-on-Write)机制在非活动槽上重建完整系统。这大大减少了OTA包的大小,但增加了升级逻辑的复杂度。

经验总结:在A/B设备上调试OTA时,务必使用adb shell update_engine_client --payload命令手动触发升级,并观察/data/misc/update_engine/log日志。该日志会详细记录每个分区的写入进度和校验结果,是定位升级失败的首选入口。

2.5 核心术语对比与选型考量

在实际项目中,选择传统模式还是A/B模式,取决于产品定位和硬件约束。对于低端设备(存储小于16GB),传统模式可节省存储成本;对于中高端设备,A/B模式带来的用户体验提升(无中断升级、自动回滚)往往更值得投入。此外,还需考虑虚拟A/B(Virtual A/B)方案,它结合了动态分区和A/B的优势,通过快照实现“逻辑双槽”,进一步减少物理存储占用。

术语定义与OTA的关系
bootloader引导加载程序,验证并加载内核决定启动槽位,校验boot签名
recovery独立恢复系统传统升级的执行环境
misc启动控制信息分区存储槽位状态和升级命令
update_engineA/B升级守护进程后台执行分区写入和校验
updater-script升级脚本(Edify语言)定义传统模式下的具体操作
payload.binA/B升级数据文件包含所有分区的差分或全量数据

理解这些术语的层次关系至关重要:Bootloader是启动链的起点,Recovery是传统升级的执行者,A/B系统是升级架构的演进方向,而分区布局则是所有升级操作的物质基础。在后续章节中,我们将基于这些概念,深入剖析OTA包的生成、签名、差分算法和客户端执行流程。

常见误区:不要将“Recovery模式”与“Fastboot模式”混淆。Fastboot是Bootloader提供的一种协议,用于通过USB直接刷写分区,通常用于工程开发;而Recovery是独立的操作系统,用于执行OTA包和用户数据擦除。在OTA升级中,Fastboot模式不参与任何环节。