3. Android分区与镜像

制作 OTA 升级包之前,必须先弄清楚 Android 设备里到底有哪些分区、每个分区装了什么、它们被打包成什么格式的镜像,以及这些镜像在 OTA 包里是如何被组织和校验的。分区划分决定了升级包的“颗粒度”:改一个系统应用可能只需更新 system,改一个 HAL 实现可能只需更新 vendor,而涉及内核或 ramdisk 的改动则往往要动 boot。理解分区与镜像的对应关系,是判断“该打全量包还是增量包、该签哪些镜像、升级后能否正常启动”的基础。

一、核心原理:分区是逻辑容器,镜像是分区的可刷写形态

Android 采用 A/B 或 A-only 分区布局。A/B 设备有两套槽位(slot_a、slot_b),OTA 写入非当前槽位,重启后切换,实现无缝升级;A-only 设备通常配合 recovery 分区完成升级。无论哪种布局,每个分区在构建产物中都对应一个镜像文件,常见格式有 raw、ext4、sparse、erofs、boot.img、vbmeta.img 等。镜像不是简单复制文件,而是包含文件系统结构、校验信息甚至签名元数据。

从打包角度看,OTA 包本质上是一组“分区镜像 + 升级脚本 + 元数据”的集合。全量包直接携带目标镜像或镜像差分包,增量包则携带旧版本到新版本的二进制差分(patch)。因此,分区划分越细,增量升级的粒度越可控,但打包与签名的工作量也越大。

二、主要分区的作用与镜像对应关系

下面这张结构关系图展示了典型 A/B 设备中核心分区、镜像格式与 OTA 打包之间的对应关系。图中左侧是分区,中间是镜像格式,右侧是 OTA 包中的处理方式。

Android 分区 → 镜像格式 → OTA 打包关系 分区 boot / init_boot system vendor product odm vbmeta dtbo / vendor_boot 镜像格式与内容 boot.img:kernel + ramdisk + cmdline system.img:ext4 / erofs,框架与应用 vendor.img:HAL、固件、驱动 product.img:可定制系统应用 odm.img:ODM 定制 HAL 与配置 vbmeta.img:AVB 校验与签名元数据 dtbo/vendor_boot:设备树与 vendor ramdisk OTA 包中的处理 全量:整镜像;增量:bsdiff 差分 按块校验,写入 slot_b 与 system 版本匹配校验 可独立更新,减少包体 随 vendor 联动,避免碎片化 必须重新签名,否则 AVB 失败 与 boot 同版本绑定 分区越细,增量升级粒度越可控;vbmeta 与 boot 必须与目标版本严格匹配

各分区的职责可以概括为:boot 承载内核与 ramdisk,决定设备能否启动;system 是 Android 框架、系统应用与运行时的主体;vendor 存放 SoC 厂商提供的 HAL、固件与驱动,是 system 与硬件之间的桥梁;product 用于放置可定制的系统应用与配置,便于 OEM 差异化;odm 则承载 ODM 厂商的定制 HAL 与设备配置,通常与 vendor 联动;vbmeta 保存 AVB 校验与签名信息,是启动链信任的根;dtbo 与 vendor_boot 分别承载设备树覆盖和 vendor ramdisk,在 GKI 架构下尤为重要。

三、方法流程:从构建产物到 OTA 包

以 A/B 设备全量包为例,典型流程如下:

  1. 构建阶段生成各分区镜像,如 system.img、vendor.img、boot.img、vbmeta.img。
  2. 使用 avbtool 对镜像添加 AVB 元数据并签名,生成带 hashtree 的镜像。
  3. 通过 ota_from_target_files 或 build/make/tools/releasetools 生成 OTA 包,脚本会读取 target_files.zip 中的分区信息。
  4. 对每个分区计算校验和,写入 care_map 与 payload_properties.txt。
  5. 使用发布密钥对 OTA 包整体签名,生成 ota_update.zip。

下面是一段查看镜像格式与分区信息的常用命令示例:

# 查看镜像文件系统类型
file system.img
# 输出示例:system.img: Linux rev 1.0 ext4 filesystem data

# 查看 sparse 镜像信息
simg2img system.img system_raw.img

# 查看 OTA 包中的分区与校验信息
unzip -l ota_update.zip | grep -E "care_map|payload|metadata"

四、案例与场景:一次 vendor 改动引发的升级选择

假设某项目只修改了相机 HAL 的实现,代码位于 vendor/ 目录。此时最合理的做法是只更新 vendor 分区,生成仅包含 vendor 的增量包。但如果该 HAL 依赖新的内核接口,则必须同时更新 boot 与 vendor,否则新 HAL 在旧内核上无法加载。再比如,若修改了 product/etc/ 下的默认配置,只需更新 product 分区即可,无需触碰 system。反之,如果修改了 frameworks/base,则 system 必须更新,且由于 system 与 vendor 存在接口版本约束,往往需要同步检查 vendor 的兼容性。

判断升级范围的一个实用原则:先看改动落在哪个分区,再看该分区是否与其他分区存在版本绑定关系。boot 与 vendor 常绑定,system 与 vendor 通过 VINTF 兼容性矩阵约束,vbmeta 则必须随任何被修改的分区一起重新签名。

五、常见误区与复盘

  • 误区一:只更新 system 却忽略 vbmeta。 只要 system 镜像内容变化,其 AVB 哈希就变化,vbmeta 中的对应描述必须同步更新并重新签名,否则设备启动时校验失败。
  • 误区二:把 product 与 system 混为一谈。 在 Android 10 之后,product 已独立分区,若仍将定制应用放入 system,会导致增量包体积偏大且升级粒度变粗。
  • 误区三:增量包跨版本使用。 增量包依赖源版本镜像的精确哈希,源版本不匹配时 patch 会失败,必须回退到全量包。
  • 误区四:忽略 A/B 槽位。 升级写入的是非当前槽位,若未正确设置 slot_suffix 或未更新 boot_control,重启后可能仍进入旧系统。
分区主要内容常见镜像格式OTA 更新注意点
boot / init_bootkernel、ramdisk、cmdlineboot.img(raw + gzip/lz4)与 vendor 版本绑定,需同步更新
system框架、系统应用、运行时ext4 / erofs / sparse改动后必须重签 vbmeta
vendorHAL、固件、驱动ext4 / erofs受 VINTF 兼容性约束
product可定制系统应用与配置ext4 / erofs可独立增量更新
odmODM 定制 HAL 与配置ext4 / erofs通常与 vendor 联动
vbmetaAVB 校验与签名元数据vbmeta.img任何分区变更都需重新生成

掌握分区与镜像的对应关系后,制作 OTA 包时就能准确回答三个问题:这次改动涉及哪些分区、这些分区应打成全量还是增量、签名链上哪些文件必须重新生成。这是后续配置 OTA 脚本、选择签名密钥、验证升级结果的前提。