3. OTA 包格式解析
OTA 升级的稳定性,从第一行字节开始就已经被决定。理解 OTA 包的内部结构,是排查“升级失败、校验不过、卡在 0%、回滚异常”等问题的前提。Android 现代 OTA 包(A/B 与 Virtual A/B 设备)本质上是一个 ZIP 容器,里面既有描述性元数据,也有真正承载镜像数据的 payload,还有用于完整性校验的签名文件。本节从包结构出发,逐层拆解全量包与增量包的差异,并说明 payload.bin、payload_properties.txt、metadata 与签名机制各自承担的角色。
一、OTA 包的整体结构
一个标准 OTA 包解压后,通常能看到以下关键成员:
- payload.bin:真正包含系统镜像(boot、system、vendor、product 等)或差分补丁的数据体,是升级的主体。
- payload_properties.txt:payload 的属性描述,包含文件大小、SHA-256 哈希、元数据签名等,用于校验 payload 是否完整可信。
- metadata(或 metadata.pb):描述 OTA 类型、设备名、时间戳、postinstall 配置等,是升级前的“身份说明”。
- META-INF/com/android/metadata:传统 recovery 升级使用的元数据,包含 ota-type、pre-device 等键值。
- META-INF/CERT.RSA、CERT.SF、MANIFEST.MF:ZIP 级别的 JAR 签名,用于验证包内文件未被篡改。
- care_map.pb:记录需要校验的分区范围,用于 dm-verity 校验。
这些成员并非孤立存在,而是形成一条“先验身份、再验完整性、最后验数据”的信任链。下图展示了 OTA 包内部结构与校验关系:
二、全量包与增量包的核心差异
全量包(Full OTA)包含目标版本所有分区的完整镜像,payload.bin 中的 Install Operation 以 REPLACE 为主,直接把新镜像写入目标分区。它的优点是自包含、不依赖设备当前状态,缺点是体积大(通常 2~4 GB)。
增量包(Incremental OTA)只包含“从源版本到目标版本”的差分数据,payload.bin 中大量使用 BSDIFF、SOURCE_COPY、ZERO 等操作。它体积小(可能只有几百 MB),但对源版本极其敏感:源分区内容必须与生成差分时的基线完全一致,否则差分应用会失败。
| 对比维度 | 全量包 Full OTA | 增量包 Incremental OTA |
|---|---|---|
| payload 内容 | 完整分区镜像 | 差分补丁 + 源数据引用 |
| 主要操作类型 | REPLACE | BSDIFF / SOURCE_COPY / ZERO |
| 包体积 | 大(GB 级) | 小(百 MB 级) |
| 对源版本依赖 | 无 | 强依赖,源必须匹配 |
| 典型失败原因 | 空间不足、签名不符 | 源分区被修改、哈希不匹配 |
| 适用场景 | 跨大版本、救砖、首次升级 | 同版本线内小步快跑 |
三、payload.bin 与 payload_properties.txt 的配合
payload.bin 内部以 protobuf 描述 Manifest,Manifest 中列出每个分区的分区名、目标哈希、操作列表。升级时 update_engine 会先读取 Manifest,再按操作逐块应用。payload_properties.txt 则是 payload 的“体检报告”,典型内容如下:
FILE_HASH=Q2m8k...(payload.bin 的 SHA-256)
FILE_SIZE=2147483648
METADATA_HASH=7f3a...(Manifest 的 SHA-256)
METADATA_SIZE=123456
update_engine 在下载完成后,会先校验 FILE_SIZE 与 FILE_HASH,确认 payload.bin 完整;再校验 METADATA_HASH,确认 Manifest 未被篡改。只有这两步都通过,才会进入真正的分区写入阶段。很多“下载完成但升级失败”的案例,根因就是 payload_properties.txt 与 payload.bin 不匹配,例如 CDN 缓存了旧版本 payload 却返回了新 properties。
四、metadata 与签名机制
metadata 决定“这个包能不能装到这台设备上”。它包含 ota-type(AB/BLOCK)、pre-device、post-build 等字段。设备在开始升级前会校验 pre-device 是否与自身 ro.product.device 匹配,不匹配则直接拒绝,避免刷入错误机型的包导致变砖。
签名机制分为两层:
- ZIP 级 JAR 签名:META-INF 下的 MANIFEST.MF、CERT.SF、CERT.RSA 保证包内文件未被篡改,由 recovery 或 update_engine 校验。
- payload 元数据签名:payload.bin 的 Manifest 中带有签名,payload_properties.txt 中的 METADATA_HASH 与之呼应,确保 payload 来源可信。
五、典型排障场景与复盘
场景一:增量包升级报 “source hash mismatch”。原因是设备当前 system 分区被第三方修改(如 root、Magisk 挂载),与差分基线不一致。复盘结论:增量升级前应确保设备处于官方未修改状态,或改用全量包。
场景二:升级卡在 “Verifying payload”。通常是 payload_properties.txt 的 FILE_HASH 与实际 payload.bin 不符,常见于下载中断、CDN 缓存污染或打包脚本未同步更新 properties。排查时可直接计算 payload.bin 的 SHA-256 与 properties 中的值比对。
场景三:metadata 中 pre-device 与设备不匹配导致 “package is for device X, this is device Y”。这是保护机制生效,不是 bug。复盘时应检查构建产物是否发错机型分支。
掌握 OTA 包结构后,遇到升级异常时就能快速定位问题发生在“身份校验、完整性校验、差分应用、分区写入”中的哪一环,而不是盲目重试或反复刷机。