2. Vendor分区镜像制作:使用mkuserimg_mke2fs制作vendor.img、分区大小规划与动态分区(super分区)的关系
2.1 核心工具链:mkuserimg_mke2fs 与分区镜像生成
在 Android 构建系统中,mkuserimg_mke2fs 是制作 ext4 格式 vendor 镜像的标准工具。它封装了 mke2fs 与 e2fsdroid 两个底层工具,负责将 vendor 目录树打包为可挂载的稀疏镜像(sparse image)。
关键命令示例:
# 制作 vendor.img(非稀疏格式)
mkuserimg_mke2fs -s vendor/ vendor.img ext4 vendor /tmp/vendor_size
# 参数说明:
# -s :生成稀疏镜像(sparse),减少存储占用
# vendor/ :输入目录,即编译产物中的 vendor 目录树
# vendor.img :输出镜像文件
# ext4 :文件系统类型
# vendor :文件系统标签(label)
# /tmp/vendor_size :分区大小(字节),如 1073741824(1GB)
稀疏镜像原理:稀疏镜像会跳过全零块,在烧录时由 fastboot 或 update_engine 动态解稀疏。对于 vendor 分区,建议始终使用
-s 参数,可减少 30%~50% 的镜像体积。
2.2 分区大小规划:从需求到计算
vendor 分区大小直接影响系统启动稳定性。规划不足会导致 OTA 失败或开机无法挂载;规划过大则浪费动态分区空间。以下为典型规划流程:
- 统计实际内容大小:执行
du -sh vendor/获取目录实际占用。 - 预留元数据与对齐空间:ext4 文件系统约需 2%~5% 的元数据开销,加上 4KB 对齐填充。
- 加入安全余量:建议额外预留 10%~20% 空间用于后续 HAL 驱动升级或固件扩展。
- 对齐到 4KB 边界:最终大小必须为 4096 的整数倍,否则 mke2fs 会报错。
| 场景 | vendor 目录大小 | 元数据开销 (3%) | 安全余量 (15%) | 对齐后推荐大小 |
|---|---|---|---|---|
| 入门手机 (32GB eMMC) | ~180 MB | ~5.4 MB | ~27 MB | 256 MB |
| 中端手机 (64GB UFS) | ~350 MB | ~10.5 MB | ~52.5 MB | 512 MB |
| 旗舰手机 (128GB+ UFS) | ~700 MB | ~21 MB | ~105 MB | 1024 MB (1GB) |
常见陷阱:部分厂商在
BoardConfig.mk 中直接写死 BOARD_VENDORIMAGE_PARTITION_SIZE,但未考虑后续 OTA 增量包可能增大 vendor 内容。建议在构建脚本中动态计算大小,或至少每季度重新评估一次。
2.3 动态分区(super分区)与 vendor 的关联
Android 10 起引入动态分区(super 分区),将 system、vendor、product 等逻辑分区打包进一个物理 super 分区。vendor 镜像不再是直接写入独立分区,而是作为 super 内的一个逻辑卷存在。
动态分区架构要点:
- super 分区总大小 = system + vendor + product + 元数据 + 预留空间
- vendor 在 super 中的占比 通常为 15%~25%,取决于设备类型
- 逻辑分区大小 在
dynamic_partitions_op_list中定义,构建时由lpmake工具打包 - vendor 镜像大小 必须 ≤ 逻辑分区大小,否则 lpmake 报错
2.4 分区大小冲突排查与解决方案
在实际项目中,vendor 分区大小问题常表现为以下三类错误:
| 错误现象 | 根因 | 解决方案 |
|---|---|---|
mke2fs: Cannot create filesystem with given size |
vendor 目录实际内容超过 BOARD_VENDORIMAGE_PARTITION_SIZE |
增大分区大小,或清理 vendor 中冗余文件(如未使用的 HAL 库) |
lpmake: Not enough space in super |
所有逻辑分区总和 + 元数据 > super 分区物理大小 | 增大 super 分区(需修改分区表),或缩小 system/product 分区 |
开机 log 显示 Failed to mount /vendor |
vendor 镜像实际大小与分区表记录不一致 | 重新执行 mkuserimg_mke2fs 并确保 BOARD_VENDORIMAGE_PARTITION_SIZE 与 super 内逻辑卷大小匹配 |
调试技巧:使用
输出中会显示每个逻辑分区的名称、大小和槽位(slot),可用于验证 vendor 分区是否按预期分配。
lpdump 命令查看当前 super 分区内的逻辑卷布局:adb shell lpdump /dev/block/by-name/super输出中会显示每个逻辑分区的名称、大小和槽位(slot),可用于验证 vendor 分区是否按预期分配。
2.5 构建配置与动态分区参数对照
以下为 BoardConfig.mk 中与 vendor 和动态分区相关的关键变量:
# 独立分区模式(Android 9 及以下)
BOARD_VENDORIMAGE_PARTITION_SIZE := 536870912 # 512MB
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
# 动态分区模式(Android 10+)
BOARD_SUPER_PARTITION_SIZE := 4294967296 # 4GB
BOARD_SUPER_PARTITION_GROUPS := google_dynamic_partitions
BOARD_GOOGLE_DYNAMIC_PARTITIONS_SIZE := 4294967296
BOARD_GOOGLE_DYNAMIC_PARTITIONS_LIST := system vendor product
# vendor 在动态分区中的逻辑大小
BOARD_VENDORIMAGE_PARTITION_SIZE := 536870912 # 512MB(必须 ≤ 动态分区组内分配)
重要约束:在动态分区模式下,
1. 小于等于
2. 大于等于实际 vendor 目录内容 + 元数据开销 + 安全余量。
违反任一条件都会导致构建失败。
BOARD_VENDORIMAGE_PARTITION_SIZE 的值必须同时满足两个条件:1. 小于等于
BOARD_SUPER_PARTITION_SIZE 减去其他逻辑分区和元数据后的剩余空间。2. 大于等于实际 vendor 目录内容 + 元数据开销 + 安全余量。
违反任一条件都会导致构建失败。
2.6 实战:从 vendor 目录到 super 镜像的完整流程
- 编译 vendor 模块:
make vendorimage或make vendorbootimage - 生成 vendor.img:构建系统自动调用
mkuserimg_mke2fs,输出到out/target/product/<device>/vendor.img - 打包 super 镜像:
make superimage调用lpmake将 system.img、vendor.img、product.img 合并为super.img - 烧录验证:
fastboot flash super super.img,重启后检查df -h /vendor确认挂载正常
快速验证命令:
# 检查 vendor 镜像大小
ls -lh out/target/product/<device>/vendor.img
# 检查 super 镜像内 vendor 逻辑分区大小
lpdump out/target/product/<device>/super.img | grep vendor
# 挂载验证(本地)
mkdir -p /tmp/vendor_mount
sudo mount -o loop vendor.img /tmp/vendor_mount
df -h /tmp/vendor_mount
sudo umount /tmp/vendor_mount