供应商原生开发工具包 (VNDK) 概述

供应商本机开发工具包 (VNDK)是一组库,由供应商或产品分区中的其他库或二进制文件在 dlopen 运行时使用。

为什么选择 VNDK?

AOSP 允许仅框架更新,其中系统分区可以升级到最新的框架版本,而供应商分区保持不变。尽管构建时间不同,但每个分区中的二进制文件必须能够相互协作。

仅框架更新包括以下挑战:

  • 框架模块和供应商模块之间的依赖关系。在 Android 8.0 之前,vendor 和 system 分区中的模块可以相互链接。但是,来自供应商模块的依赖性对框架模块的开发施加了不希望的限制。
  • AOSP 库的扩展。当系统分区被标准通用系统映像 (GSI) 替换时,Android 要求所有 Android 设备通过 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 和硬件管理粘合剂。

这样的世界包括来自框架共享库的稳定的公共 API 可能不足以供供应商模块开发人员使用(尽管 API 可以在 Android 版本之间更改),要求供应商进程可以访问框架共享库的某些部分。此外,由于性能要求可能导致妥协,因此必须区别对待一些对响应时间要求严格的 HAL。

以下部分详细介绍了 VNDK 如何为供应商和同进程 HAL (SP-HAL) 处理框架共享库。

供应商的框架共享库

本节描述了对供应商进程可访问的共享库进行分类的标准。有两种方法可以跨多个 Android 版本支持供应商模块:

  1. 稳定框架共享库的 ABI/API 。新的框架模块和旧的供应商模块可以使用相同的共享库来减少内存占用和存储大小。独特的共享库还避免了几个双重加载问题。但是,维持稳定的 ABI/API 的开发成本很高,要稳定每个框架共享库导出的所有 ABI/API 是不现实的。
  2. 复制旧的框架共享库。附带对侧通道的严格限制,定义为框架模块和供应商模块之间通信的所有机制,包括(但不限于)绑定器、套接字、管道、共享内存、共享文件和系统属性。除非通信协议被冻结和稳定(例如通过 hwbinder 的 HIDL),否则必须没有通信。双重加载共享库也可能会导致问题;例如,如果将新库创建的对象从旧库传递给函数,则可能会发生错误,因为这些库可能会以不同的方式解释该对象。

根据共享库的特性使用不同的方法。因此,框架共享库分为三个子类别:

  • LL-NDK 库是已知稳定的框架共享库。他们的开发人员致力于维护他们的 API/ABI 稳定性。
    • LL-NDK 包括以下库: libEGL.solibGLESv1_CM.solibGLESv2.solibGLESv3.solibandroid_net.solibc.solibdl.soliblog.solibm.solibnativewindow.solibneuralnetworks.solibsync.solibvndksupport.solibvulkan.so
  • 合格的 VNDK 库 (VNDK)是可以安全复制两次的框架共享库框架模块供应商模块可以链接到它们自己的副本。只有满足以下条件,框架共享库才能成为合格的 VNDK 库:
    • 它不会向/从框架发送/接收 IPC。
    • 它与 ART 虚拟机无关。
    • 它不会读取/写入文件格式不稳定的文件/分区。
    • 它没有需要法律审查的特殊软件许可证。
    • 它的代码所有者不反对供应商的使用。
  • 仅框架库 (FWK-ONLY)是不属于上述类别的框架共享库。这些库:
    • 被视为框架内部实现细节。
    • 供应商模块不得访问。
    • 具有不稳定的 ABI/API,并且没有 API/ABI 兼容性保证。
    • 不被复制。

同进程 HAL (SP-HAL)

Same-Process HAL ( SP-HAL ) 是一组预先确定的 HAL,它们被实现为供应商共享库并加载到框架进程中。 SP-HAL 由链接器命名空间隔离(控制对共享库可见的库和符号)。 SP-HAL 必须仅依赖于LL-NDKVNDK-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-HALS 不可见。

以下是具有 RS 异常 (FWK-ONLY-RS) 的仅框架库

  • libft2.so (渲染脚本)
  • libmediandk.so (渲染脚本)

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_CODENAMEREL ,请使用PLATFORM_SDK_VERSION (例如28 )。
    • 否则,使用PLATFORM_VERSION_CODENAME (例如P )。

供应商测试套件 (VTS)

Android 供应商测试套件 (VTS) 要求使用非空ro.vndk.version属性。新推出的设备和升级设备都必须定义ro.vndk.version 。一些 VNDK 测试用例(例如VtsVndkFilesTestVtsVndkDependencyTest )依赖ro.vndk.version属性来加载匹配的合格 VNDK 库数据集。