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 系统其他分区的交互关系:

Vendor 分区文件系统布局与交互架构 Vendor 分区文件系统布局与交互架构 /vendor 分区 /vendor/bin/ HAL 服务入口 硬件测试工具 /vendor/etc/ 音频/传感器配置 init rc 脚本 /vendor/lib/ 32 位 HAL 库 VNDK 兼容库 /vendor/lib64/ 64 位 HAL 库 VNDK 兼容库 /vendor/firmware/ Wi-Fi/BT 固件 DSP/GPU 微码 /vendor/overlay/ RRO 资源覆盖 APK 静态资源覆盖 启动服务 加载配置 dlopen 加载 dlopen 加载 Linux 内核驱动 request_firmware() 固件加载 /system 分区 框架 / 服务管理器 IPC / HIDL 通信 📌 关键说明: • 所有目录权限均为 0755,文件权限根据类型不同为 0644 或 0755 • SELinux 上下文必须与目录用途匹配,否则导致服务启动失败或固件加载被拒绝

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 分区时的常见布局错误

  1. 将系统库放入 /vendor/lib: 如 libbinder.so、libutils.so 应保留在 /system/lib,放入 Vendor 会导致 linker 命名空间冲突。
  2. 固件文件权限错误: 固件文件设置为 0600 或 0700 会导致内核无法读取,应使用 0644 或 0444。
  3. 覆盖 APK 签名不匹配: /vendor/overlay 中的 APK 必须使用与系统相同的平台签名,否则资源覆盖不会生效。
  4. 缺少 VNDK 兼容库: HAL 库链接了非 VNDK 的系统库,导致在 Android 10+ 上 linker 报错 dlopen failed: cannot locate symbol。
  5. init rc 脚本路径错误: 将 init.rc 放在 /vendor/etc/init/ 而非 /vendor/etc/ 根目录,导致启动阶段未执行。
最佳实践: 在编译 Vendor 分区镜像前,使用 tree /vendor 检查目录结构是否符合预期。部署后通过 adb shell ls -lZ /vendor 验证所有文件和目录的权限与 SELinux 上下文是否正确。