从Android.bp到刷机包:解密Android14分区镜像的生成路径与定制逻辑
当你完成m或mm编译后,面对out/target/product/[device]/下错综复杂的目录结构,是否曾困惑于自己编译的模块最终会出现在哪个分区镜像?本文将带你深入Android构建系统的内部机制,揭示从源码到刷机包的全链路过程。
1. Android分区架构解析
现代Android系统采用模块化设计,将不同功能的组件划分到独立的分区中。这种设计不仅提升了系统安全性,也为设备制造商提供了灵活的定制空间。以下是Android14中主要分区的功能定位:
| 分区名称 | 存储内容 | 可定制性 | 典型路径示例 |
|---|---|---|---|
| system | AOSP核心组件、系统应用 | 低(需签名验证) | out/target/product/xxx/system/ |
| vendor | SoC厂商提供的闭源驱动和HAL | 中等(需厂商签名) | out/target/product/xxx/vendor/ |
| product | 设备系列通用功能组件 | 高 | out/target/product/xxx/product/ |
| odm | 设备制造商定制组件 | 最高 | out/target/product/xxx/vendor/odm/ |
提示:从Android10开始引入的动态分区(如system_ext)进一步细化了系统组件的隔离粒度,但核心逻辑仍基于这四大分区。
2. 构建系统的输出目录结构
执行完整编译后,产物目录通常呈现如下结构:
out/target/product/[device]/ ├── system/ │ ├── bin/ │ ├── lib/ │ └── etc/ ├── vendor/ │ ├── bin/ │ ├── etc/ │ └── odm/ ├── product/ │ ├── app/ │ └── overlay/ └── obj/ ├── ETAPROJECTS/ └── NOTICE_FILES/关键目录说明:
- system/:存放所有标记为系统模块的构建产物
- vendor/:包含
vendor:true标记的模块输出 - product/:
product_specific:true模块的专属目录 - odm/:
device_specific:true模块的最终位置
3. 模块到分区的映射机制
3.1 Android.bp中的分区控制
模块的最终归属由构建描述文件中的特定属性决定。以下是一个典型的模块定义示例:
cc_binary { name: "my_daemon", srcs: ["src/*.cpp"], vendor: true, // 输出到vendor分区 product_specific: true, // 覆盖vendor设置,输出到product device_specific: true, // 最高优先级,输出到odm }属性优先级规则:
device_specific:true>product_specific:true>vendor:true- 无任何标记时默认进入system分区
3.2 历史遗留的Android.mk配置
对于仍使用Makefile的项目,对应的控制变量为:
LOCAL_MODULE := my_legacy LOCAL_VENDOR_MODULE := true # 等效于vendor:true LOCAL_PRODUCT_MODULE := true # 等效于product_specific LOCAL_ODM_MODULE := true # 等效于device_specific4. 从目录到镜像的生成过程
4.1 镜像组装流程
- 文件收集:根据分区表定义扫描各目录
- 权限处理:应用fs_config规则
- 镜像格式化:使用make_ext4fs工具
- 签名验证:对关键分区进行AVB签名
4.2 定制分区布局
通过修改BoardConfig.mk可以调整分区配置:
# 示例:调整system分区大小 BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2147483648 # 启用动态分区 BOARD_DYNAMIC_PARTITION_ENABLE := true常见定制场景:
- 扩展分区大小以适应预装应用
- 添加自定义分区(如preload)
- 调整文件系统类型(ext4/f2fs)
5. 高级调试技巧
当模块未出现在预期位置时,可通过以下命令追踪:
# 查看模块最终安装路径 m out/soong/.bootstrap/bin/soong_build && \ out/soong/.bootstrap/bin/soong_build --find-module my_module # 检查模块依赖关系 mmm --dump-module-info path/to/module典型问题排查步骤:
- 确认模块是否被正确编译(检查obj目录)
- 验证分区标记是否生效
- 检查是否有安装冲突(如相同文件存在于多个分区)