26、OTA升级与fastbootd:fastbootd模式、动态分区刷写
说到OTA升级,很多同学第一反应就是“系统更新设置里点一下下载”。但真正深入到Android底层,你会发现OTA升级背后藏着两个关键角色:recovery 和 fastbootd。今天我们就来聊聊后者——fastbootd模式,以及它和动态分区刷写的关系。
为什么需要fastbootd?
传统Android设备用fastboot模式刷机,大家应该不陌生。但那是针对静态分区的。到了动态分区时代,情况变了。
动态分区的特点是:分区表不是写死的,而是由super分区动态管理。你没法像以前那样直接 fastboot flash system system.img,因为system分区可能根本不存在于物理分区表中。
那怎么办?Google的解决方案就是——fastbootd。
核心区别一句话概括:
- 传统fastboot:运行在bootloader中,只能刷写物理分区(如boot、super)。
- fastbootd:运行在recovery内核中,能识别动态分区,直接刷写system、vendor、product等逻辑分区。
我个人习惯把fastbootd理解为“带fastboot协议的recovery模式”。它本质上是一个运行在recovery环境下的fastboot守护进程。
fastbootd的进入方式
进入fastbootd有两种常见方式:
- 从系统重启进入:
adb reboot fastboot(注意不是adb reboot bootloader) - 从bootloader菜单选择:部分设备在fastboot模式下有“Enter fastbootd”选项
进入后,你可以用 fastboot devices 确认。如果设备处于fastbootd模式,你会看到类似:
$ fastboot devices
ABCD1234 fastboot
嗯,这里要注意:fastboot 这个状态既可能是传统fastboot,也可能是fastbootd。怎么区分?用 fastboot getvar is-userspace:
$ fastboot getvar is-userspace
is-userspace: yes # 这就是fastbootd
is-userspace: no # 这是传统fastboot
我曾经在项目调试时,因为没区分这两个模式,折腾了半天刷不进system分区。后来才发现自己一直在传统fastboot里打转。
动态分区刷写流程
在fastbootd模式下刷写动态分区,流程其实很清晰。我画了一张图帮你理解:
实际刷写时,你可能会遇到两种情况:
情况一:OTA升级包中的镜像刷写
OTA升级包通常包含 payload.bin,里面封装了所有分区的差分或完整镜像。在fastbootd模式下,你可以手动刷写单个分区做调试:
# 进入fastbootd
adb reboot fastboot
# 确认状态
fastboot getvar is-userspace
# 刷写system分区(动态分区)
fastboot flash system system.img
# 刷写vendor分区
fastboot flash vendor vendor.img
# 刷写product分区
fastboot flash product product.img
# 重启
fastboot reboot
小技巧:如果你不确定当前设备有哪些动态分区,可以用 fastboot getvar all 查看。输出中 partition-type:system:... 会告诉你哪些是动态分区。
情况二:完整super分区刷写
有时候你需要一次性刷写整个super分区(比如从AOSP编译出来的完整镜像)。这时候命令是:
fastboot flash super super.img
这个操作会重建所有动态分区的映射。说白了,super.img里包含了分区表信息,刷进去之后,system、vendor、product等逻辑分区的大小和位置都会被重新定义。
警告:刷写super分区会覆盖所有动态分区的内容。如果你只想更新某个分区(比如只改system),不要刷super,单独刷对应分区镜像即可。我曾经见过同事误操作,把整个super刷了,结果vendor和product的定制内容全丢了,只能重新刷全量包。
fastbootd与OTA升级的关系
你可能会问:既然OTA升级都是通过recovery完成的,为什么还要了解fastbootd?
原因有两个:
- 调试和救砖:OTA升级失败时,设备可能卡在bootloop。这时候fastbootd是你能用的最强工具之一。你可以手动刷写损坏的分区,而不需要重新刷全量包。
- 理解升级流程:OTA升级的update_engine在后台做的事情,本质上和fastbootd刷写分区是一样的——都是向动态分区写入数据。区别只是update_engine在运行时系统里操作,而fastbootd在recovery环境里操作。
我记得有一次,客户的设备OTA升级到一半断电了,重启后一直卡在开机动画。我通过fastbootd模式,单独刷写了损坏的system分区,设备就救回来了。如果当时没有fastbootd,只能重新刷全量包,用户数据全丢。
fastbootd的限制
当然,fastbootd也不是万能的。有几点需要注意:
| 限制 | 说明 |
|---|---|
| 需要recovery内核 | 如果recovery分区损坏,fastbootd也无法启动 |
| 不支持所有fastboot命令 | 比如 fastboot boot 在fastbootd下不可用 |
| 依赖动态分区驱动 | 内核必须支持dm-linear和逻辑卷管理 |
| 刷写速度 | 相比传统fastboot,fastbootd的I/O路径更长,速度略慢 |
嗯,这里要特别提醒:如果你的设备连fastbootd都进不去,那基本只能靠EDL模式(紧急下载模式)或者短接点来救砖了。所以平时做开发时,我建议你多测试一下fastbootd的可用性,别等到真出问题了才发现它坏了。
小结
fastbootd是动态分区时代的重要工具。它让开发者能在recovery环境下直接操作逻辑分区,大大简化了调试和救砖的流程。理解它的工作原理,对你深入掌握OTA升级机制非常有帮助。
说白了,fastbootd就是一把“瑞士军刀”——平时你可能用不上,但关键时刻能救命。