供应商原生开发套件 (VNDK)

供应商原生开发套件 (VNDK) 是专门用来让供应商实现其 HAL 的一组库。VNDK 包含在 system.img 中,并在运行时与供应商代码动态关联。

为何要使用 VNDK?

Android 8.0 及更高版本支持框架专用更新,在此类更新中,系统分区可以升级到最新版本,而供应商分区保持不变。这意味着在不同时间编译的二进制文件必须能够相互配合使用;VNDK 为 Android 版本迭代时发生的 API/ABI 变更所导致的问题提供了解决途径。

框架专用更新面临着以下挑战:

  • 框架模块与供应商模块之间的依赖关系。在 Android 8.0 之前的版本中,两种模块可以互相关联。但是,来自供应商模块的依赖关系对框架模块开发施加了不必要的限制。
  • AOSP 库的扩展。Android 8.0 及更高版本要求所有 Android 设备在系统分区被替换为标准常规系统映像 (GSI) 时,都可以通过 CTS 测试。不过,当供应商扩展 AOSP 库以提高性能或为其 HIDL 实现添加额外的功能时,使用标准 GSI 来刷写系统分区可能会破坏供应商的 HIDL 实现(有关如何防止此类破坏的指南,请参阅 VNDK 扩展)。

为了克服这些挑战,Android 8.0 引入了几项技术,例如 VNDK(如本部分中所述)、HIDL、hwbinder、设备树叠加层和 sepolicy 叠加层。

VNDK 资源

本部分包含以下 VNDK 资源:

  • VNDK 概念(参见下文)介绍了框架共享库、Same-Process HAL (SP-HAL) 和 VNDK 术语。
  • VNDK 扩展对供应商专属更改进行了分类。例如,具有供应商模块所依赖的扩展功能的库必须复制到供应商分区中,但禁止进行 ABI 不兼容的更改。
  • VNDK 编译系统支持介绍了与 VNDK 相关的编译系统配置和模块定义语法。
  • VNDK 定义工具可帮助您将源代码树迁移到 Android 8.0 及更高版本。
  • 链接器命名空间提供对共享库关联的精细控制。
  • 目录、规则和 sepolicy 定义了运行 Android 8.0 及更高版本的设备的目录布局,以及 VNDK 规则和关联的 sepolicy。
  • Android O 中的 VDNK 设计演示文稿阐述了 Android O 中使用的 VDNK 基本概念。

VNDK 概念

在理想的 Android 8.0 及更高版本环境中,框架进程不加载供应商共享库,所有供应商进程仅加载供应商共享库(和一部分框架共享库),而框架进程与供应商进程之间的通信由 HIDL 和硬件 binder 控制。

这样的环境存在以下可能:来自框架共享库的稳定、公共 API 可能不足以满足供应商模块开发者的需求(尽管 API 在不同的 Android 版本之间会有所变化),要防止出现这种情况,供应商进程需要能够访问一部分框架共享库。此外,由于性能要求可能会导致折中方案,因此必须区别对待某些对响应时间要求严格的 HAL。

以下部分详细介绍了 VNDK 如何处理适用于供应商的框架共享库以及 Same-Process HAL (SP-HAL)。

适用于供应商的框架共享库

本部分介绍了供应商进程可访问的共享库的分类标准。要让供应商模块在多个 Android 版本上皆可正常工作,有以下两种方法:

  1. 让框架共享库的 ABI/API 保持稳定。新的框架模块和旧的供应商模块可以使用同一共享库,以减少内存占用和存储空间占用。此外,通过使用同一共享库,还可以避免一些双重加载问题。不过,保持稳定的 ABI/API 的开发成本很高,因此让每个框架共享库导出的所有 ABI/API 都保持稳定是不现实的。
  2. 复制旧的框架共享库。此方法会严重限制边信道,即在框架模块与供应商模块之间进行通信的所有机制,包括(但不限于)binder、套接字、管道、共享内存、共享文件和系统属性。除非通信协议被冻结且保持稳定(例如通过 hwbinder 的 HIDL),否则不能进行通信。双重加载共享库也可能会导致出现问题;例如,如果将新库创建的对象传递到旧库的函数中,则可能会出错,因为这些库可能会以不同的方式解读该对象。

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

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

Same-Process HAL (SP-HAL)

Same-Process 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

以下库是 SP-HAL 可以访问的 VNDK-SP 库:

  • android.hardware.graphics.allocator@2.0.so
  • android.hardware.graphics.common@1.0.so
  • android.hardware.graphics.mapper@2.0.so
  • android.hardware.renderscript@1.0.so (Renderscript)
  • libRS_internal.so (Renderscript)
  • libbase.so
  • libc++.so
  • libcutils.so
  • libhardware.so
  • libhidlbase.so
  • libhidltransport.so
  • libhwbinder.so
  • libion.so
  • libutils.so
  • libz.so

以下 VNDK-SP 依赖项 (VNDK-SP-Indirect) 对 SP-HAL 不可见:

  • libRSCpuRef.so (Renderscript)
  • libRSDriver.so (Renderscript)
  • libbacktrace.so
  • libblas.so (Renderscript)
  • libbcinfo.so (Renderscript)
  • liblzma.so
  • libunwind.so

以下私有 VNDK-SP 依赖项 (VNDK-SP-Indirect-Private) 对所有供应商模块均不可见:

  • libcompiler_rt.so (Renderscript)

以下是具有 RS 例外的框架专用库 (FWK-ONLY-RS):

  • libft2.so (Renderscript)
  • libmediandk.so (Renderscript)

VNDK 术语

  • 模块是指共享库或可执行文件。
  • 进程是指可执行文件产生的操作系统任务。
  • 以“框架”打头的术语是指与系统分区相关的概念。
  • 以“供应商”打头的术语是指与供应商分区相关的概念。

例如:

  • 框架可执行文件是指 /system/bin/system/xbin 中的可执行文件。
  • 框架共享库是指 /system/lib[64] 下的共享库。
  • 框架模块是指框架共享库和框架可执行文件。
  • 框架进程是指框架可执行文件(例如 /system/bin/app_process)产生的进程。
  • 供应商可执行文件是指 /vendor/bin 中的可执行文件。
  • 供应商共享库是指 /vendor/lib[64] 下的共享库。
  • 供应商模块是指供应商可执行文件和供应商共享库。
  • 供应商进程是指供应商可执行文件(例如
  • /vendor/bin/android.hardware.camera.provider@2.4-service)产生的进程。

文档历史记录

本部分跟踪了对 VNDK 文档的更改。

Android 8.1 的变化

  • SP-NDK 库已合并到 LL-NDK 库中。
  • 在 RS 命名空间部分中将 libui.so 替换为 libft2.so。包含 libui.so 会出错。
  • libGLESv3.solibandroid_net.so 添加到 LL-NDK 库中。
  • libion.so 添加到 VNDK-SP 库中。
  • 从 LL-NDK 库中移除 libstdc++.so。改用 libc++.so。某些版本的独立工具链可以将 -lstdc++ 添加到默认链接器标记中。要停用默认设置,请将 -nodefaultlibs -lc -lm -ldl 添加到 LDFLAGS 中。
  • libz.so 从 LL-NDK 移到 VNDK-SP 库中。在某些配置中,libz.so 可能仍是 LL-NDK。但是,应该没有明显的差异。