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 包中的处理方式。
各分区的职责可以概括为: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 设备全量包为例,典型流程如下:
- 构建阶段生成各分区镜像,如
system.img、vendor.img、boot.img、vbmeta.img。 - 使用
avbtool对镜像添加 AVB 元数据并签名,生成带 hashtree 的镜像。 - 通过
ota_from_target_files或build/make/tools/releasetools生成 OTA 包,脚本会读取target_files.zip中的分区信息。 - 对每个分区计算校验和,写入
care_map与payload_properties.txt。 - 使用发布密钥对 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 的兼容性。
五、常见误区与复盘
- 误区一:只更新 system 却忽略 vbmeta。 只要 system 镜像内容变化,其 AVB 哈希就变化,vbmeta 中的对应描述必须同步更新并重新签名,否则设备启动时校验失败。
- 误区二:把 product 与 system 混为一谈。 在 Android 10 之后,product 已独立分区,若仍将定制应用放入 system,会导致增量包体积偏大且升级粒度变粗。
- 误区三:增量包跨版本使用。 增量包依赖源版本镜像的精确哈希,源版本不匹配时 patch 会失败,必须回退到全量包。
- 误区四:忽略 A/B 槽位。 升级写入的是非当前槽位,若未正确设置
slot_suffix或未更新boot_control,重启后可能仍进入旧系统。
| 分区 | 主要内容 | 常见镜像格式 | OTA 更新注意点 |
|---|---|---|---|
| boot / init_boot | kernel、ramdisk、cmdline | boot.img(raw + gzip/lz4) | 与 vendor 版本绑定,需同步更新 |
| system | 框架、系统应用、运行时 | ext4 / erofs / sparse | 改动后必须重签 vbmeta |
| vendor | HAL、固件、驱动 | ext4 / erofs | 受 VINTF 兼容性约束 |
| product | 可定制系统应用与配置 | ext4 / erofs | 可独立增量更新 |
| odm | ODM 定制 HAL 与配置 | ext4 / erofs | 通常与 vendor 联动 |
| vbmeta | AVB 校验与签名元数据 | vbmeta.img | 任何分区变更都需重新生成 |
掌握分区与镜像的对应关系后,制作 OTA 包时就能准确回答三个问题:这次改动涉及哪些分区、这些分区应打成全量还是增量、签名链上哪些文件必须重新生成。这是后续配置 OTA 脚本、选择签名密钥、验证升级结果的前提。