4. A-B分区系统架构
A-B 无缝升级并不是简单地把系统分区复制两份,而是由 bootloader、misc 分区、slot metadata 以及各 slot 内的 system/vendor/boot 等分区共同组成的一套“可切换、可回退、可校验”的启动体系。理解这套架构的关键,是分清“谁决定启动哪个 slot”“谁记录升级意图”“谁承载真正的系统内容”以及“谁在失败时兜底”。
一、核心角色分工
在 A-B 架构中,每个分区都有明确职责,不能混用。bootloader 是启动链的第一执行者,它读取 misc 分区和 slot metadata,决定本次从 A 还是 B 启动;misc 分区是跨 slot 共享的“通信信箱”,用于传递升级命令、重试次数和启动状态;slot metadata 则记录每个 slot 是否可启动、是否已成功、是否被标记为 active。system、vendor、boot、init_boot、dtbo 等分区则按 slot 成对存在,例如 system_a/system_b、vendor_a/vendor_b、boot_a/boot_b。
二、启动决策链:bootloader 如何选择 slot
设备上电后,bootloader 首先读取 misc 分区中的启动命令。如果 misc 中写入了“切换到 B”的指令,bootloader 会检查 slot B 的 metadata 是否标记为 bootable。若满足条件,则从 boot_b 加载内核,并挂载 system_b、vendor_b 等分区。启动过程中,Android 系统会通过 HAL 层向 bootloader 回写“启动成功”标记,将当前 slot 的 successful 置为 true。如果启动失败或超时,bootloader 会根据重试计数决定是否回退到原 slot。
关键规则:bootloader 只信任 misc 和 slot metadata 中的状态,不会自行猜测哪个 slot 更“新”。因此升级工具必须在写入新 slot 后,正确更新 metadata 和 misc,否则切换不会发生。
三、各分区在 A-B 中的具体角色
| 分区/组件 | 是否分 slot | 核心职责 | 升级时是否写入 |
|---|---|---|---|
| bootloader | 否(通常单份) | 启动决策、加载 kernel、校验 slot 状态 | 一般不随 A/B 升级更新 |
| misc | 否(共享) | 传递升级命令、重试计数、启动状态 | 是,写入切换指令 |
| slot metadata | 否(共享) | 记录 slot 可启动性、成功标记、优先级 | 是,更新 bootable/successful |
| boot / init_boot | 是(_a / _b) | 承载 kernel 与 ramdisk | 是,写入非活动 slot |
| system | 是(_a / _b) | Android 框架与系统应用 | 是,写入非活动 slot |
| vendor | 是(_a / _b) | 厂商 HAL 与驱动 | 是,写入非活动 slot |
| dtbo / vbmeta | 是(_a / _b) | 设备树覆盖与验证启动元数据 | 是,写入非活动 slot |
四、典型升级场景与状态流转
假设当前运行在 slot A,系统收到 OTA 包后,升级流程如下:
- OTA 客户端将新版本镜像写入 slot B 的 system_b、vendor_b、boot_b 等分区。
- 写入完成后,更新 slot metadata,将 slot B 标记为 bootable,并设置优先级高于 A。
- 向 misc 分区写入“切换到 B”的启动命令,并设置重试次数(例如 3 次)。
- 重启设备,bootloader 读取 misc 后选择从 slot B 启动。
- 若 slot B 启动成功,Android 将 slot B 标记为 successful,并清除 misc 中的切换命令。
- 若 slot B 启动失败,bootloader 在重试次数耗尽后自动回退到 slot A,保证设备可用。
# 查看当前 slot 与 metadata 状态(示例)
$ adb shell getprop ro.boot.slot_suffix
_a
$ adb shell cmd bootcontrol get-number-of-slots
2
$ adb shell cmd bootcontrol get-slot-info 0
slot=0, bootable=true, successful=true
$ adb shell cmd bootcontrol get-slot-info 1
slot=1, bootable=true, successful=false
五、常见误区与复盘要点
误区一:认为 system 和 vendor 必须同时切换。实际上 bootloader 只负责选择 slot,system 与 vendor 的 slot 后缀由系统启动时统一决定,二者必须保持一致,否则会出现 HAL 与框架版本不匹配。
误区二:忽略 misc 分区的写入时机。如果先写 misc 再写 system_b,重启后可能从 B 启动但系统不完整,导致启动失败。正确顺序是先完成所有 slot 镜像写入,再更新 metadata,最后写 misc。
误区三:把 slot metadata 当作普通文件。它通常由 bootloader 和 Android 的 bootcontrol HAL 共同维护,不能通过简单文件拷贝修改,必须使用 fastboot 或 bootcontrol 接口操作。
复盘建议:在调试 A-B 升级问题时,优先确认三件事——misc 中的命令是否正确、slot metadata 中目标 slot 是否 bootable、目标 slot 的 boot/system/vendor 是否完整写入。这三者构成启动决策的最小闭环,任何一环缺失都会导致切换失败或回退。
总体来看,A-B 分区架构的核心思想是“用空间换可靠性”:通过成对分区承载系统内容,通过 misc 和 metadata 记录状态与意图,通过 bootloader 执行切换与回退。只有理解每个组件在启动链中的位置和职责,才能在 OTA 开发、排障和定制中做出正确判断。