Appearance
12 Treble 与 Mainline:让 Android 可分模块升级的工程
本页导读:本页讲 Android 史上最成功的两项「反熵增」工程:Treble 把系统与厂商切开(Android 8),Mainline 再把 Google 的能力从 system 里拆出来装进 APEX(Android 10+)。VNDK 是中途修了又拆的脚手架,动态分区是承载一切的地基。理解了「接口化 + 分层交付」,才能看懂第 01 页的分区表、第 08 页的 APEX 扫描、以及为什么 Android 16 时代 OTA 只需几十分钟。基线 Android 16(API 36)。
读完本页你要能回答:为什么「OTA 只刷 system 不动 vendor」是工程奇迹?APEX 和 APK 什么关系?应用开发者到底要不要关心模块版本?
一、Treble:一条 system/vendor 国境线
Android 8 之前,framework 直链厂商 .so,每次平台升级都要厂商重新适配全部私有库——升级周期以「年」计是物理必然。Treble 的手术刀:
- framework 与 vendor 之间只允许跨 Binder 的 HAL 接口,禁止 dlopen 对方实现;
- 接口定义集中在
hardware/interfaces,由 AIDL/HIDL 描述、自动生成 C++/Java 桩; - vendor 侧库进
vendor/odm分区,平台侧进system/system_ext,互不越境(第 00 页分区表); - 效果:平台 OTA 可以不动 vendor——GSI(Generic System Image) 从此可行,AOSP 能跑在海量存量设备上。
一句话本质:Treble 不是技术发明,是合同管理——把二进制兼容问题全部收敛到版本化的接口上。
二、HAL 接口化:从 HIDL 到 AIDL 的接力
| 阶段 | 接口语言 | 载体 | 状态 |
|---|---|---|---|
| Android 8~10 | HIDL(.hal) | hwservicemanager + hwbinder | 存量维护 |
| Android 11 起 | AIDL(.aidl + @VintfStability) | servicemanager + binder(可 binderfs 专道) | 新增唯一选择 |
| Android 13(API 33) | — | — | 新设备不再接受 HIDL 新接口 |
| Android 15~16 | AIDL 为主 | VINTF 校验 | 主流子系统全部 AIDL 化(长尾以 AOSP 清单为准) |
AIDL HAL 的三个关键标签:@VintfStability(声明稳定 ABI,可跨版本)、VERSION(接口版本化,客户端按版本探测能力)、sysci/framework-vendor 分区策略(决定实现放哪、谁能用)。
一个 AIDL HAL 长什么样(power stats 为例,路径真实存在):
text
hardware/interfaces/power/stats/aidl/android/hardware/power/stats/IPowerHint.aidl
├ interface IPowerHint { ... @VintfStability 生效 }
└ 生成:C++/Java/Rust 桩 + stability 标注 + VERSION 支持调试入口三件套:lshal(枚举 HAL 与状态)、servicemanager -l(AIDL 注册表,需权限)、VINTF 兼容失败日志在 vintf 相关 dump 与开机 dropbox(命令名以设备为准)。
三、VINTF:开机时互查户口本
- 设备声明
manifest.xml:我提供了哪些 HAL、哪些版本、frameworks 兼容矩阵版本; - 平台携带
compatibility_matrix.xml:我要求设备上必须有谁、至少什么版本; - 开机早期(init)互查,不兼容直接阻断启动——把「升级翻车」从运行期挪到编译/开机期;
- FCM(Framework Compatibility Matrix)版本随 API 演进,Android 16 设备需声明不低于对应 FCM 版本(映射表见 source.android.com 的 VINTF 文档,具体数字以其为准)。
VINTF 是「接口化」的执法者:没有它,Treble 只是一句口号。
补充两个细节:manifest/matrix 都是 XML 落盘(/vendor/etc/vintf/、/system/etc/vintf/ 一类路径,以设备为准),可用文本工具直接读;otatools/设备侧 vintf 校验在 OTA 预检阶段也会跑,防止「刷上去变砖」的接口断裂。
四、VNDK:一座修完就拆的桥
VNDK(Vendor Native Development Kit,Android 9 引入)想解决「vendor 二进制依赖平台 .so」的历史债:把 vendor 可用的平台库固化为版本化快照(vndk-sp、ld.config.vndkXX.so 命名空间隔离)。
- 现实问题:库集合大、维护成本高、与接口化精神(只走 HAL)不符;
- 结局:Android 12 起弱化、13 正式退场(新设备不再发 VNDK 包;存量设备保留快照以维持旧 vendor 镜像可用,细节与时间点以 AOSP 发布说明为准);
- 留下的遗产:链接命名空间(linker namespace)成为默认安全机制——vendor 进程 dlopen 平台私有库从「能跑但脏」变成「根本找不到」,这是第 01/04 页 SELinux 之外的第二道墙。
五、APEX:系统组件的「应用化」封装
APEX(Android Pony EXpress)是 Mainline 模块的物理载体,/system/apex 出厂、/data/system/apex 承载升级副本、/apex/<模块名> 是运行视图(激活目录布局以 AOSP 为准):
text
com.android.art.apex(zip 容器示意)
├ apex_manifest.json # name/version(Android 11+ 支持 proto 与扁平 .so 命名)
├ apex_payload_signature / META/ # 载荷签名(AVB 公钥信任链)
└ contents/ # 挂载后的真实文件系统:lib/ bin/ etc/ java/…- 挂载由
apexd(早期)/APEXService线负责:环回设备挂载 + 激活事务 + 回滚(OTA 失败自动回退旧版本); - 模块可带 native 库、服务(rc)、可依赖其它模块(
usesLibrary/mainline jar); - 与 APK 的关系:APEX 可含 APK(如 Wi-Fi/Telephony 模块内服务),PMS 经
ApexManager注册其能力(第 08 页专线); - 升级通道三选一:OTA(update_engine)、
adb install-apex、Play 系统组件更新——同一激活事务语义; - 版本与回滚:APEX 激活记录在持久状态里,开机时若校验失败自动回退上一版;「降级」被显式禁止,安全补丁不可逆;
- 盘点命令:
ls /apex看激活视图;apex-info list(AOSP 工具,部分设备裁剪)与dumpsys package的 apex 段看版本细节(以设备为准)。
六、Mainline 模块版图与 API 约束
以 Android 15/16 世代为参照(清单随版本增删,以 AOSP/官方发布为准):
| 模块 | 承载内容 | 代表能力 |
|---|---|---|
| com.android.art | ART 运行时、核心库、installd 等 | 运行时升级、GC 改进 |
| com.android.i18n / tzdata | ICU、时区数据 | 区域/时区热修 |
| com.android.conscrypt | 安全提供者 | TLS 栈热修 |
| com.android.media / mediamodule | 媒体框架组件 | 编解码相关修复 |
| com.android.mediaprovider | 媒体/相册存储 | MediaStore 演进 |
| com.android.permission | 权限体系 | 授权语义演进 |
| com.android.networkstack / wifi / tethering / uwb / nfc 方向 | 连接子系统 | 协议栈热修 |
| com.android.adbd | 调试守护 | adb 协议演进 |
| com.android.sdkext / resolver / os.stats 等 | SDK 扩展、解析、统计 | 细分能力独立交付 |
API 约束的核心三条:
- 模块对外的平台 API 行为冻结:public API 不能因模块升级而变语义,兼容性靠
@FlaggedApi/CompatChanges 与cts 门禁保证(具体机制名以 AOSP 为准); - 模块间/模块对平台的非公开接口必须过 sdk 层(
@SystemApi/mainline-stable 面),不能反向依赖 framework 内部类; - 能力探测走
SdkExtensions/ExtensionVersion(API 34 起成为标准姿势),而不是猜 Android 版本号。
模块开发的内部纪律还有:API 面由 metalava 从源码抽 stub 并进 api/current.txt 类基线(不同模块目录形态不同,以 AOSP 为准);@FlaggedApi 把「新 API 配新行为」绑成原子;跨模块共享代码走 stable AIDL 或显式 declared library,禁止「复制粘贴式依赖」。
七、动态分区:super 容器与 A/B 家族
- Android 10 起,system/system_ext/vendor/product/odm 等装进
super动态分区(lpmeta 记录分组与大小),fastboot可对子分区单独刷写,空间在组内动态划拨; - 更新策略两代:classic A/B(双槽全量并存,回滚换槽)与 Virtual A/B(VAB,单槽 + snapshot 增量,Android 12+ 主流,节省一半空间);
- 与 APEX 的关系:APEX 激活事务与 VAB 快照同层「可回滚」哲学,OTA 是两者的编排者(
update_engine→snapshotctl/install 会话,第 08 页 staged session); super.img的构建由build/make的 super image 规则产出(具体变量/布局以 AOSP 构建文档为准)。
八、术语速查
| 术语 | 一句话 |
|---|---|
| Treble | system/vendor 以 HAL 接口为界的架构契约 |
| HIDL / AIDL HAL | 两代 HAL 接口语言,后者胜出 |
| VINTF | manifest × matrix 的开机兼容性互查 |
| VNDK | 已退役的 vendor 二进制依赖快照层 |
| linker namespace | linker 层的库可见性隔离墙 |
| APEX | 系统组件的签名容器格式与挂载机制 |
| Mainline 模块 | 以 APEX/专用通道独立交付的 Android 组件 |
| SdkExtensions | 模块扩展版本探测 API |
| GSI | 只换 system 的通用系统镜像 |
| VAB/Virtual A/B | 单槽 + 快照的增量 OTA 更新机制 |
九、CompatChanges 与「可演进兼容」
分层交付带来新风险:同一平台版本,模块新旧不同行为可能不同。framework 的答案是 CompatChanges(frameworks/base/core/java/android/compat/Compatibility.java 与 changeId 体系):
- 每个行为变更挂一个 changeId,按 targetSdk 与模块扩展版本双维判定是否启用新行为;
- 应用可用
Compatibility.isChangeEnabled(id)查询,调试可用adb shell am compat enable|disable <id> <pkg>(子命令以 AOSP 为准); - 这是「不破坏存量」的制度化:Android 16 上的 CompatChanges 清单已成百上千条,读源码看到
SUPPORTS_XX常量别慌,它只是闸门编号。
十、对开发者的实际影响清单
- 别再假设「平台 = 一个版本」:同一 Android 16 设备上,ART/媒体/连接的版本可以互相不同;行为分支用扩展版本探测;
- 崩溃栈里出现
apex路径是常态(/apex/com.android.art/...),定位时按模块归属找 changelog; - vendor 侧调试记住三道墙:SELinux(域/类型)、linker namespace(库不可见)、VINTF(接口版本);
- 隐私/安全变更几乎都走模块通道快速下发——「商店没更新但行为变了」的谜团九成出自 Mainline;
- 长寿命设备(IoT/车机)选型时优先选 Mainline 覆盖度高 + VAB 的机型,OTA 成本差异是数量级的。
十一、排障清单
| 症状 | 方向 | 取证 |
|---|---|---|
| 开机卡 VINTF 报错 | 新 framework 配旧 vendor manifest | vintf 校验日志/兼容矩阵版本 |
| HAL 找不到服务 | 注册表/域权限/版本不匹配 | lshal + servicemanager -l + avc |
| APEX 激活失败回滚 | 签名/依赖版本/空间 | logcat apex 线与 apexd 日志 |
| 模块升级后行为变化 | CompatChanges 闸门 | am compat 状态 + 扩展版本号 |
| vendor 加载库失败 | linker namespace 墙 | ld.config 与 /proc/<pid>/maps |
| OTA 后首开异常慢 | VAB snapshot merge | bootstat 与 update_engine 日志 |
十二、版本注记
- Android 8(API 26):Treble 落地;HIDL/hwbinder;分区分离。
- Android 9(API 28):VNDK 登场;强制 VNDK 快照概念起步。
- Android 10(API 29):APEX 首发(先装 ART/i18n 等);动态分区;VNDK 强制。
- Android 11(API 30):AIDL 稳定 HAL;Mainline 大扩容(Wi-Fi/媒体等入列);
adb install-apex。 - Android 12(API 31):VAB 主流化;VNDK 弱化开始。
- Android 13(API 33):新设备去 VNDK;HIDL 新接口冻结。
- Android 14(API 34):
SdkExtensions/ExtensionVersion 成为模块能力探测标准。 - Android 15~16(API 35~36):16KB 页对全部 native 产物重编(Mainline 模块首当其冲);pkg/设置存储等继续模块化的方向推进(边界以 AOSP 为准);Mainline 通过 Play 的月度下发已成常态供应链。
十三、自测清单
- 能讲清 Treble 边界两侧分别禁止什么;
- 能解释 VINTF manifest 与 matrix 的方向差异(设备提供 vs 平台要求);
- 能说出 APEX 的三种升级通道与回滚语义;
- 能用 ExtensionVersion 替代版本号判断模块能力;
- 能解释为什么同一 Android 大版本内「行为变了」不再等于 bug。
本页小结
本页小结:Treble 定了国境线(system/vendor),VINTF 是海关,AIDL/HAL 是护照;APEX 是集装箱,把系统组件装成可独立航行的船;VNDK 是拆掉的脚手架,linker namespace 是留下的围墙;CompatChanges 保证风浪来时老船不翻。全册回望:本册每一页的能力,都活在这套「接口化 + 分层交付」的工程底座之上。
参考
- Treble/VINTF/HAL(AOSP):source.android.com/docs/core/architecture
- APEX 格式(AOSP):source.android.com/docs/core/ota/apex
- 动态分区/VAB(AOSP):source.android.com/docs/core/ota
- 行为变更适配:developer.android.com/guide/app-compatibility/behavior-changes
- 平台与 Mainline 模块(SDK 侧):developer.android.com/guide/sdk-platform