3. Vendor 分区文件系统布局:标准用途与权限要求
Vendor 分区是 Android 系统中存放设备专属二进制、库、配置和固件的独立分区。其文件系统布局遵循 Treble 架构 的严格规范,确保系统分区(system)与厂商实现(vendor)之间的清晰边界。理解每个目录的标准用途与权限要求,是定制 Vendor 分区和部署 HAL 驱动的基础。
3.1 顶层目录结构总览
标准的 Vendor 分区包含以下核心目录,每个目录都有明确的语义和访问控制策略:
| 目录 | 标准用途 | 典型权限 | 关键约束 |
|---|---|---|---|
/vendor/bin/ |
厂商专属可执行文件(HAL 服务、硬件测试工具) | 0755 / root:shell |
不可包含系统级守护进程(应放在 /system/bin) |
/vendor/etc/ |
硬件相关配置文件(audio_policy、GPS、传感器校准) | 0755 / root:root |
文件权限通常为 0644,不允许可执行位 |
/vendor/lib/ |
32 位 HAL 共享库(.so)及依赖库 | 0755 / root:root |
库文件权限 0644,需通过 linker 命名空间隔离 |
/vendor/lib64/ |
64 位 HAL 共享库(.so)及依赖库 | 0755 / root:root |
仅 64 位架构设备存在,与 lib 目录结构对称 |
/vendor/firmware/ |
无线、音频、传感器等硬件固件文件 | 0755 / root:root |
文件权限 0644,部分固件需 0444 只读 |
/vendor/overlay/ |
运行时资源覆盖层(RRO/静态覆盖 APK) | 0755 / root:root |
仅用于资源定制,不可存放可执行代码 |
关键原则: Vendor 分区挂载为
noexec 的情况较少,但 /vendor/bin 以外的目录不应包含可执行文件。所有 HAL 库必须通过 android.hardware.* 的 SELinux 上下文访问。
3.2 各目录深度解析
3.2.1 /vendor/bin/ — 厂商可执行程序
该目录存放由厂商提供的、在 Vendor 分区上下文中运行的守护进程和工具。典型内容包括:
- HAL 服务入口:
android.hardware.audio@2.0-service、android.hardware.camera.provider@2.4-service - 硬件测试工具:
vts_test_hal、sensors_test - 厂商自定义服务:
thermal-engine、charger_monitor
权限要求:
- 目录权限:
0755(所有者 root,组 shell) - 文件权限:
0755或0750(根据 SELinux 策略) - SELinux 上下文:
u:object_r:vendor_file:s0或特定服务上下文
常见错误: 将系统级守护进程(如
servicemanager)放入 /vendor/bin 会导致启动阶段 SELinux 拒绝访问。系统服务必须保留在 /system/bin。
3.2.2 /vendor/etc/ — 硬件配置与策略文件
该目录是 Vendor 分区中最重要的配置存放点,直接影响硬件功能的行为。常见子目录和文件:
| 文件/子目录 | 用途 | 典型来源 |
|---|---|---|
audio_policy_configuration.xml |
音频路由策略 | 音频 HAL 配置 |
mixer_paths.xml |
音频混音器路径 | ALSA 驱动配置 |
media_codecs.xml |
媒体编解码器能力声明 | Codec2 或 OMX 配置 |
permissions/ |
硬件权限白名单 | Android 框架权限 |
init/ |
Vendor 分区 init rc 脚本 | 厂商启动配置 |
wifi/ |
Wi-Fi 固件参数与配置文件 | WLAN 芯片配置 |
权限要求:
- 目录权限:
0755,文件权限:0644 - 不允许任何文件具有可执行权限(
+x) - SELinux 上下文:
u:object_r:vendor_configs_file:s0
3.2.3 /vendor/lib/ 与 /vendor/lib64/ — HAL 共享库
这两个目录存放所有 HAL 实现库及其直接依赖。Android 10+ 强制使用 VNDK(Vendor Native Development Kit) 和 LL-NDK 来隔离 Vendor 与 System 的库依赖。
典型库文件:
/vendor/lib/
├── hw/
│ ├── audio.primary.$(device).so
│ ├── camera.$(device).so
│ ├── gralloc.$(device).so
│ └── sensors.$(device).so
├── libstagefright_soft_*.so
├── libvulkan.so # 厂商 Vulkan 实现
└── libc++.so # VNDK 兼容的 C++ 运行时
权限要求:
- 目录权限:
0755,库文件权限:0644 - 库文件不可执行(即使有
+x也会被 linker 忽略) - SELinux 上下文:
u:object_r:vendor_file:s0 - 必须通过
/vendor/etc/ld.config.28.txt配置 linker 命名空间
VNDK 兼容性检查: 如果 HAL 库链接了非 VNDK 的系统库(如
libgui),在 Android 10+ 上会导致 linker 崩溃。使用 readelf -d libxxx.so | grep NEEDED 检查依赖,确保所有依赖都在 VNDK 或 Vendor 分区内。
3.2.4 /vendor/firmware/ — 硬件固件
固件文件由内核驱动在初始化或运行时加载到硬件设备中。常见固件类型:
- Wi-Fi/BT 固件:
fw_bcm43455.bin、nvram.txt - 音频 DSP 固件:
adsp.bin、audience-es704.bin - 传感器固件:
stm32l4xx_fw.bin - GPU 微码:
mali_csffw.bin
权限要求:
- 目录权限:
0755,文件权限:0644或0444(只读) - 固件文件通常由内核直接读取,不需要可执行权限
- SELinux 上下文:
u:object_r:firmware_file:s0 - 部分设备要求固件文件位于
/vendor/firmware/的子目录中(如wlan/、bt/)
3.2.5 /vendor/overlay/ — 资源覆盖层
该目录用于存放 运行时资源覆盖(RRO) 或 静态资源覆盖(SRO) APK。这些 APK 在编译时或运行时替换系统资源,用于定制设备专属 UI 主题、默认配置或区域设置。
典型结构:
/vendor/overlay/
├── framework_res_overlay.apk
├── Settings_res_overlay.apk
└── SystemUI_res_overlay.apk
权限要求:
- 目录权限:
0755,APK 文件权限:0644 - APK 必须使用平台签名或与 Vendor 分区相同的签名
- SELinux 上下文:
u:object_r:vendor_overlay_file:s0 - 不允许存放可执行代码或共享库
3.3 Vendor 分区文件系统布局 SVG 架构图
下图展示了 Vendor 分区标准目录结构及其与 Android 系统其他分区的交互关系:
3.4 权限与 SELinux 上下文对照表
下表汇总了每个目录的标准 SELinux 上下文,以及常见错误配置导致的后果:
| 目录 | 标准 SELinux 上下文 | 错误上下文示例 | 典型错误现象 |
|---|---|---|---|
/vendor/bin |
vendor_file 或 vendor_exec |
system_file |
服务启动时 SELinux 拒绝执行 |
/vendor/etc |
vendor_configs_file |
system_configs_file |
配置文件读取被拒绝,服务使用默认值 |
/vendor/lib |
vendor_file |
system_lib_file |
dlopen 失败,HAL 服务崩溃 |
/vendor/firmware |
firmware_file |
vendor_file |
内核 request_firmware 返回 -EACCES |
/vendor/overlay |
vendor_overlay_file |
vendor_file |
资源覆盖 APK 未生效,系统使用默认资源 |
权限排查提示: 当 HAL 服务启动失败或硬件功能异常时,首先检查
dmesg | grep avc 或 logcat -b events | grep avc 中的 SELinux 拒绝日志。常见的拒绝类型包括 execute(执行)、read(读取)和 open(打开)权限缺失。
3.5 定制 Vendor 分区时的常见布局错误
- 将系统库放入 /vendor/lib: 如
libbinder.so、libutils.so应保留在/system/lib,放入 Vendor 会导致 linker 命名空间冲突。 - 固件文件权限错误: 固件文件设置为
0600或0700会导致内核无法读取,应使用0644或0444。 - 覆盖 APK 签名不匹配:
/vendor/overlay中的 APK 必须使用与系统相同的平台签名,否则资源覆盖不会生效。 - 缺少 VNDK 兼容库: HAL 库链接了非 VNDK 的系统库,导致在 Android 10+ 上 linker 报错
dlopen failed: cannot locate symbol。 - init rc 脚本路径错误: 将
init.rc放在/vendor/etc/init/而非/vendor/etc/根目录,导致启动阶段未执行。
最佳实践: 在编译 Vendor 分区镜像前,使用
tree /vendor 检查目录结构是否符合预期。部署后通过 adb shell ls -lZ /vendor 验证所有文件和目录的权限与 SELinux 上下文是否正确。