供应商原生开发工具包 (VNDK) 是一组库,供供应商或产品分区中的其他库或二进制文件在运行时使用 dlopen。
弃用
供应商 NDK 在 Android 8.0 中引入,旨在提供框架和供应商代码之间的 API。虽然 VNDK 已成功使用多年,但它存在一些缺点- 存储
- 单个 VNDK APEX 打包了所有 VNDK 库,无论它们是否从设备中使用。
- GSI 包含多个版本的 VNDK APEX,以支持多个版本的供应商镜像。
- 可更新性
- 很难将 VNDK APEX 与平台更新分开更新。
- 供应商镜像经常通过无线 (OTA) 方式更新,从而降低了将 VNDK 打包在系统镜像中的好处。
关于 VNDK 弃用的详细信息
所有 VNDK 库都打包到 VNDK APEX 中,并安装在 system (-ext) 镜像中。随着 VNDK 的弃用,以前的 VNDK 库将安装在供应商(或产品)镜像中,与其他供应商可用的库相同。这些功能将随着 VNDK 的弃用而移除- Android 15 的 VNDK APEX
- 如果供应商或产品分区是为 Android 15 构建的,则指示目标 VNDK 版本的系统属性将被移除
ro.vndk.version
ro.product.vndk.version
- 由于没有 VNDK,VNDK 优化将不可用
TARGET_VNDK_USING_CORE_VARIANT
for Android Go devicesuse_vndk_as_stable
for Vendor APEXes
- 供应商快照,高度依赖于 VNDK
弃用的例外情况
这些功能不会随着 VNDK 的弃用而改变- VNDK 版本为 14 或更低的 VNDK APEX,这是支持现有供应商镜像所必需的。
- LL-NDK 不是 VNDK 的一部分。
为何使用 VNDK?
AOSP 允许仅框架更新,其中系统分区可以升级到最新的框架版本,而供应商分区保持不变。尽管在不同时间构建,但每个分区中的二进制文件必须能够彼此协作。
仅框架更新包括以下挑战
- 框架模块和供应商模块之间的依赖关系。在 Android 8.0 之前,供应商和系统分区中的模块可以彼此链接。然而,来自供应商模块的依赖关系对框架模块的开发施加了不必要的限制。
- AOSP 库的扩展。Android 要求所有 Android 设备在系统分区替换为标准通用系统镜像 (GSI) 时通过 CTS。然而,由于供应商扩展 AOSP 库以提高性能或为其 HIDL 实现添加额外功能,因此使用标准 GSI 刷写系统分区可能会破坏供应商的 HIDL 实现。有关防止此类破坏的指南,请参阅VNDK 扩展。
为了应对这些挑战,Android 包含多项功能,例如 VNDK(本节中描述)、HIDL、hwbinder、设备树覆盖和 sepolicy 覆盖。
VNDK 特定术语
VNDK 相关文档使用以下术语- 模块 指的是共享库或可执行文件。模块构成构建时依赖项。
- 进程 是从可执行文件衍生的操作系统任务。进程构成运行时依赖项。
- 框架 限定的术语与
system
分区相关 - 框架可执行文件 指的是
/system/bin
或/system/xbin
中的可执行文件。 - 框架共享库 指的是
/system/lib[64]
下的共享库。 - 框架模块 指的是框架共享库和框架可执行文件。
- 框架进程 是从框架可执行文件衍生的进程,例如
/system/bin/app_process
。 - 供应商 限定的术语与
vendor
分区相关 - 供应商可执行文件 指的是
/vendor/bin
中的可执行文件 - 供应商共享库 指的是
/vendor/lib[64]
下的共享库。 - 供应商模块 指的是供应商可执行文件和供应商共享库。
- 供应商进程 是从供应商可执行文件衍生的进程,例如
/vendor/bin/android.hardware.camera.provider@2.4-service
。
VNDK 概念
在理想的 Android 8.0 及更高版本中,框架进程不加载供应商共享库,所有供应商进程仅加载供应商共享库(以及一部分框架共享库),并且框架进程和供应商进程之间的通信受 HIDL 和硬件 Binder 监管。
这样的世界包括以下可能性:来自框架共享库的稳定公共 API 可能不足以满足供应商模块开发者的需求(尽管 API 在 Android 版本之间可能会发生变化),因此需要让供应商进程访问一部分框架共享库。此外,由于性能要求可能会导致妥协,因此必须区别对待一些响应时间至关重要的 HAL。
以下部分详细介绍了 VNDK 如何处理供应商的框架共享库和同进程 HAL (SP-HAL)。
供应商的框架共享库
本节介绍了对供应商进程可访问的共享库进行分类的标准。支持跨多个 Android 版本的供应商模块有两种方法:
- 稳定框架共享库的 ABI/API。新的框架模块和旧的供应商模块可以使用相同的共享库,以减少内存占用和存储空间。唯一的共享库还可以避免一些双重加载问题。但是,维护稳定的 ABI/API 的开发成本很高,并且稳定每个框架共享库导出的所有 ABI/API 是不现实的。
- 复制旧的框架共享库。随之而来的是对侧信道的严格限制,侧信道定义为框架模块和供应商模块之间进行通信的所有机制,包括(但不限于)Binder、套接字、管道、共享内存、共享文件和系统属性。除非通信协议已冻结且稳定(例如,通过 hwbinder 的 HIDL),否则不得进行通信。双重加载共享库也可能会导致问题;例如,如果由新库创建的对象被传递到旧库的函数中,则可能会发生错误,因为这些库可能会以不同的方式解释该对象。
根据共享库的特性,使用不同的方法。因此,框架共享库分为三个子类别:
- LL-NDK 库 是已知稳定的框架共享库。它们的开发者致力于维护其 API/ABI 的稳定性。
- LL-NDK 包括以下库:
libEGL.so
、libGLESv1_CM.so
、libGLESv2.so
、libGLESv3.so
、libandroid_net.so
、libc.so
、libdl.so
、liblog.so
、libm.so
、libnativewindow.so
、libneuralnetworks.so
、libsync.so
、libvndksupport.so
和libvulkan.so
。
- LL-NDK 包括以下库:
- 符合条件的 VNDK 库 (VNDK) 是可以安全复制两次的框架共享库。框架模块 和 供应商模块 可以与其自己的副本链接。框架共享库只有在满足以下条件时才能成为符合条件的 VNDK 库:
- 它不向框架发送/接收 IPC。
- 它与 ART 虚拟机无关。
- 它不读取/写入具有不稳定文件格式的文件/分区。
- 它没有需要法律审核的特殊软件许可。
- 其代码所有者不反对供应商使用。
- 仅限框架库 (FWK-ONLY) 是不属于上述类别的框架共享库。这些库:
- 被视为框架内部实现细节。
- 供应商模块不得访问。
- 具有不稳定的 ABI/API,且没有 API/ABI 兼容性保证。
- 不被复制。
同进程 HAL (SP-HAL)
同进程 HAL (SP-HAL) 是一组预定的 HAL,它们被实现为供应商共享库 并加载到框架进程 中。SP-HAL 通过链接器命名空间(控制对共享库可见的库和符号)进行隔离。SP-HAL 必须仅依赖于 LL-NDK 和 VNDK-SP。
VNDK-SP 是符合条件的 VNDK 库的预定义子集。VNDK-SP 库经过仔细审查,以确保将 VNDK-SP 库双重加载到框架进程中不会引起问题。SP-HAL 和 VNDK-SP 均由 Google 定义。
以下库是被批准的 SP-HAL:
libGLESv1_CM_${driver}.so
libGLESv2_${driver}.so
libGLESv3_${driver}.so
libEGL_${driver}.so
vulkan.${driver}.so
android.hardware.renderscript@1.0-impl.so
android.hardware.graphics.mapper@2.0-impl.so
VNDK-SP 库在其 Android.bp 文件中指定 vndk: { support_system_process: true }
。如果还指定了 vndk: {private:true}
,则这些库称为 VNDK-SP-Private
,并且 SP-HAL 看不到它们。
以下是 具有 RS 例外的仅限框架库 (FWK-ONLY-RS):
libft2.so
(RenderScript)libmediandk.so
(RenderScript)
VNDK 版本控制
VNDK 共享库已进行版本控制
ro.vndk.version
系统属性会自动添加到/vendor/default.prop
。- VNDK 和 VNDK-SP 共享库作为 VNDK apex
com.android.vndk.v${ro.vndk.version}
安装,并挂载到/apex/com.android.vndk.v${ro.vndk.version}
。
ro.vndk.version
的值由以下算法选择:
- 如果
BOARD_VNDK_VERSION
不等于current
,则使用BOARD_VNDK_VERSION
。 - 如果
BOARD_VNDK_VERSION
等于current
: - 如果
PLATFORM_VERSION_CODENAME
为REL
,则使用PLATFORM_SDK_VERSION
(例如28
)。 - 否则,使用
PLATFORM_VERSION_CODENAME
(例如P
)。
供应商测试套件 (VTS)
Android 供应商测试套件 (VTS) 强制要求使用非空的 ro.vndk.version
属性。新推出的设备和升级设备都必须定义 ro.vndk.version
。一些 VNDK 测试用例(例如 VtsVndkFilesTest
和 VtsVndkDependencyTest
)依赖于 ro.vndk.version
属性来加载匹配的符合条件的 VNDK 库数据集。