AI 技术博客
Android全栈9 分钟阅读5122

【全栈第7课】Treble 架构 + VINTF(进入 HAL 阶段)

Android 全栈工程师进阶教程 第07课。Treble 架构 + VINTF(进入 HAL 阶段)。基于公开 AOSP 知识整理,含原理、可编译示例、常见问题定位。

> 本文是《Android 全栈工程师进阶教程》系列第 07 课。完整 26 课见 GitHub 仓库

【全栈第7课】Treble 架构 + VINTF(进入 HAL 阶段)


0. 这节课你将做出什么

看懂 某真实机型 里真实的 VINTF 文件(vendor manifest + framework matrix),并写一个 vendor manifest 示例(为 L9 写 HAL 预声明)。 学完你能回答:为什么 Android 把系统拆成 system/vendor 两半?它们靠什么约定接口、保证升级不出事?HAL 是怎么"被系统发现"的? 这是从"框架工程师"跨到"BSP 工程师"的认知分水岭。

1. 背景:为什么要 Treble

Android 8 之前,每个厂商把内核/驱动/HAL 和 Android 框架编译在一起,改动深度耦合。结果:Google 发了新版本 Android,厂商要花几个月重新适配自己的魔改,碎片化严重、升级极慢

Android 8 引入 Treble,把 OS 物理拆成两个分区:

  • system 分区:Google/AOSP 的框架,所有设备统一
  • vendor 分区:芯片厂/OEM 的 HAL、驱动适配,各设备不同

好处:升级 Android 大版本时,只换 system 分区,vendor 不动 → 升级快。 代价:两边是不同团队、不同节奏开发的,必须有一套接口契约保证它们能配合——这就是 VINTF

2. 全局图:Treble 两分区 + VINTF 两契约

┌───────────── system 分区(AOSP,统一)──────────────┐
│  Framework / system_server                          │
│  要求:"本设备必须提供这些 HAL"                       │
│        → framework compatibility_matrix.xml (type=framework)  │
└───────────────────────┬─────────────────────────────┘
                        │ 开机时 VINTF 校验:matrix(要求) 对得上 manifest(提供) 吗?
┌───────────────────────┴─────────────────────────────┐
│  vendor 分区(芯片厂/OEM)                              │
│  声明:"我提供这些 HAL"                                │
│        → vendor manifest.xml (type=device)            │
│  HAL 进程(vibrator/nfc/...)                           │
└──────────────────────────────────────────────────────┘

VINTF 两份契约:

文件谁写说什么
vendor manifest(type=device)vendor提供哪些 HAL
framework compatibility_matrix(type=framework)AOSPframework 要求哪些 HAL

开机时校验:manifest 提供的必须满足 matrix 要求的,否则开不了机。这保证了 system 升级后,只要 matrix 没变,老 vendor 还能配合。

3. 某真实机型 真实源码印证

vendor manifest 实物 device/xiaomi/popsicle/odm/nfc/vintf/manifest_nxp_nfc.xml:

<manifest version="1.0" type="device" target-level="202404">
    <hal format="aidl">
        <name>vendor.nxp.nxpnfc_aidl</name>   <!-- HAL 接口包名 -->
        <version>1</version>
        <fqname>INxpNfc/default</fqname>      <!-- 接口名/实例名 -->
    </hal>
</manifest>
  • type="device" = 这是 vendor/设备侧 manifest
  • target-level="202404" = 兼容的 FCM(Framework Compatibility Matrix)版本
  • format="aidl" = 用 AIDL HAL(对比老的 hidl)

framework matrix 实物 hardware/interfaces/compatibility_matrices/:

compatibility_matrix.202604.xml      ← 新季度版本 的矩阵
compatibility_matrix.<新版本>.xml ← Android 新版本 矩阵

4. 前置准备

  • 依赖 L1(AIDL/Binder 基础)。
  • 本课只写一个 xml 示例 + 一份分析文档,为 L9 写真 HAL 铺路。

5. 动手:写一个 vendor manifest 示例

为 L9 要写的 hello HAL 预声明 manifest_hello_hal.xml:

<!-- vendor manifest:vendor 侧声明"我提供 hello HAL" -->
<manifest version="1.0" type="device" target-level="202604">
    <hal format="aidl">
        <name>vendor.example.demo</name>    <!-- HAL 接口包名,和 L9 的 aidl 包一致 -->
        <version>1</version>
        <fqname>IHelloHal/default</fqname>   <!-- 接口名/实例名,L9 注册时也用这个 -->
    </hal>
</manifest>

逐行讲:

  • type="device":vendor 侧(L9 里这个 xml 作为 vintf_fragment 随 HAL 一起装进 vendor 分区)。
  • target-level="202604":声明兼容 新季度版本(新版本)的 FCM 版本。
  • <name> + <fqname>:这俩组合起来 = 这个 HAL 在系统里的"身份证"。L9 的 HAL 用 AServiceManager_addService 注册时,服务名就是 vendor.example.demo.IHelloHal/default,和这里对应。

6. 看底层:开机 VINTF 校验干了什么

开机时 vintf 框架会:

  1. 读 vendor manifest(所有 vendor 提供的 HAL 清单)
  2. 读 framework compatibility_matrix(framework 要求的 HAL 清单 + 版本范围)
  3. 逐条比对:matrix 里标 optional="false"(必须)的 HAL,manifest 里有没有、版本对不对?
  4. 不满足 → init 阶段报错,开不了机(或进 recovery)。

所以你加一个新 HAL,光写实现不够,还得在 manifest 里声明它(L9/L11 会做),否则系统"不知道"它存在。

7. 编译 & 运行(验证状态如实)

# 看设备实际生效的 VINTF
adb shell cat /vendor/etc/vintf/manifest.xml         # vendor 提供的
adb shell cat /system/etc/vintf/compatibility_matrix.device.xml  # framework 要求的
adb shell vintf                                       # 有的设备有 vintf 命令直接查
# 校验是否兼容
adb shell cmd android.hardware.vintf ...              # 或看开机 init 日志

> 验证状态(诚实):本课为概念课,xml 示例是真实 VINTF 格式(对照 某真实机型 NFC manifest 写);真正生效在 L9(随 HAL vintf_fragment 装入)。

8. 踩坑提醒

  1. manifest 声明了但 HAL 没真起:开机 VINTF 校验只看声明,不保证 HAL 进程真跑起来;HAL 起不来另查(L11)。
  2. target-level 不匹配:vendor manifest 的 target-level 和实际 framework FCM 版本对不上,校验失败。
  3. fqname 写错:IHelloHal/default 里实例名 default 要和 HAL 注册时的实例名一致,否则 framework 找不到。
  4. format 写错:aidl HAL 写成 format="hidl",或反之 → 校验/查找失败。
  5. vintf_fragment 没打进 vendor 分区:Android.bp 里没配 vintf_fragments,manifest 不生效(L9 会配)。

9. 常见问题分析与定位(Treble/VINTF 实战)

9.1 常见问题清单

  1. 开机失败 / 卡 logo,日志有 VINTF incompatible
  2. framework 找不到 HAL(getService 返回 null)
  3. 升级后 vendor HAL 失效
  4. CTS/VTS VINTF 相关 fail
  5. 新加的 HAL 系统"看不见"

9.2 分析与定位

① 开机 VINTF incompatible

  • 现象:卡 logo,adb logcat/init 日志有 device manifest ... incompatible with framework compatibility matrix
  • 定位:
adb shell dmesg | grep -i vintf
# 比对:vendor manifest 提供的 vs matrix 要求的,哪条对不上
adb shell cat /vendor/etc/vintf/manifest.xml
adb shell cat /system/etc/vintf/compatibility_matrix.*.xml
  • 修复:补上 matrix 要求但 manifest 缺的 HAL,或修正版本/target-level。

② getService 找不到 HAL

  • 原因:HAL 没在 manifest 声明 / fqname 不一致 / HAL 进程没起。
  • 定位:
adb shell lshal | grep hello       # lshal 列出所有 HAL,看你的在不在、状态
adb shell lshal list               # 看哪些声明了但没起(N/A)
  • lshal 是查 HAL 的神器:声明了没起 = manifest 有但进程问题(查 .rc/sepolicy,L11);压根没列出 = manifest 没声明。

③ 升级后 vendor HAL 失效

  • 原因:升级动了 framework matrix,要求变了,老 vendor manifest 不满足。
  • 定位:对比新旧 matrix 差异;看 新版本 新增的强制 HAL(见 新版本 总结)。

④ VTS/CTS VINTF fail

  • 原因:声明的 HAL 版本/接口和实际不符,或缺必需 HAL。
  • 定位:看 VTS 报告具体哪条 VINTF assertion 失败,对照 manifest 修。

9.3 定位决策树

Treble/VINTF 出问题
├─ 开机 incompatible → dmesg vintf + 比对 manifest vs matrix → 补缺的 HAL/修版本
├─ 找不到 HAL → lshal | grep → 没列出=manifest 没声明;列出 N/A=进程没起(L11)
├─ 升级后失效 → 对比新旧 matrix → 补 新版本 新增强制 HAL
└─ VTS/CTS fail → 看具体 assertion → 对照 manifest 修版本/接口

10. 小结

  1. Treble = system/vendor 物理分区:升级只换 system,vendor 不动 → 升级快。
  2. VINTF 两契约:vendor manifest(提供)+ framework matrix(要求),开机校验兼容性。
  3. HAL 的"身份证" = <name> 包名 + <fqname> 接口/实例名,注册和查找都用它。
  4. lshal 是查 HAL 的神器:声明了没起 vs 压根没声明,一眼看出。
  5. 排查口诀:开机挂比对 manifest/matrix;找不到 HAL 用 lshal;升级失效查 matrix 差异。

下节预告

L8:HIDL 老式 HAL —— 在写 AIDL HAL(L9)前,先看一眼被淘汰的 HIDL 长什么样,理解为什么 新版本 强制转 AIDL。

评论