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

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

为何要使用 VNDK?

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

Framework-Only 更新面临着以下挑战:

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

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

VNDK 资源

本部分包含以下 VNDK 资源:

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

VNDK 概念

在理想的 Android O 环境中,框架进程不加载供应商共享库,所有供应商进程仅加载供应商共享库(和一部分框架共享库),而框架进程与供应商进程之间的通信由 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 和 SP-NDK 是已知稳定的框架共享库。它们的开发者致力于保持其 API/ABI 的稳定性。
    • LL-NDK 包含以下库:libandroid_net.solibc.solibstdc++.solibdl.soliblog.solibm.solibz.solibvndksupport.so
    • SP-NDK 包含以下库:libEGL.solibGLESv1_CM.solibGLESv2.solibGLESv3.solibvulkan.solibnativewindow.solibsync.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、SP-NDK 和 VNDK-SP。

VNDK-SP 是一部分预定义的符合条件的 VNDK 库。我们会仔细审查 VNDK-SP 库,以确保将 VNDK-SP 库双重加载到框架进程中不会导致问题。SP-HAL 和 VNDK-SP 均由 Google 定义。

以下库是经过批准的 SP-HAL:

  • libGLESv2_${driver}.so
  • libGLESv1_CM_${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
  • libutils.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)产生的进程。