VNDK 快照设计

系统映像可以使用 VNDK 快照为供应商映像提供正确的 VNDK 库,即使系统映像和供应商映像是基于不同版本的 Android 编译的也是如此。创建 VNDK 快照需要以快照形式捕获 VNDK 库,并使用版本号标记它们。供应商映像可以与特定的 VNDK 版本相关联,由此版本为供应商映像中的模块提供所需 ABI。不过,在同一 VNDK 版本内,VNDK 库必须具有稳定的 ABI

VNDK 快照设计包括用于执行以下两项操作的方法:从当前系统映像生成预编译的 VNDK 快照将这些预编译的库安装到更高 Android 版本的系统分区。

VNDK 库简介

Android 8.0 中引入的 HIDL-HAL 支持单独升级系统分区和供应商分区。VNDK 定义了可与供应商代码相关联的库集(VNDK-core、VNDK-SP 和 LL-NDK),并阻止供应商使用不在 VNDK 集内的库。因此,如果将系统映像上合适的 VNDK 集提供给供应商映像,则可以编译并运行供应商映像。

VNDK-core

VNDK-core 库集安装在 /system/lib[64]/vndk-${VER} 中,适用于 API 级别为 ${VER} 的供应商进程。系统进程不得使用这些库,而必须使用安装在 /system/lib[64] 中的库。由于每个进程都具有严格的命名空间限制,因此不会造成重复加载 VNDK-core 库。

要在 VNDK-core 中添加库,请将以下内容添加到 Android.bp 中:

vendor_available: true,
vndk: {
    enabled: true,
},

VNDK-SP

VNDK-SP 库安装在 /system/lib[64]/vndk-sp-${VER} 中,适用于供应商进程和系统进程(通过安装在供应商分区中的 SP-HAL 库)。VNDK-SP 库可以重复加载。

要在 VNDK-SP 中添加库,请将以下内容添加到 Android.bp 中:

vendor_available: true,
vndk: {
    enabled: true,
    support_system_process: true,
},

LL-NDK

LL-NDK 库安装在 /system/lib[64] 中。供应商模块可以使用 LL-NDK 存根库访问 LL-NDK 库的预选符号。LL-NDK 库必须支持向后兼容且具有 ABI 稳定性,以便旧版供应商模块使用新版 LL-NDK 库。由于 LL-NDK 具有 ABI 稳定特性,VNDK 快照无需包含旧版供应商映像的 LL-NDK 库。

VNDK 快照简介

Android 8.1 包含根据源代码编译的 VNDK 库。不过,对于更高版本的 Android,必须以快照形式捕获每个 VNDK 版本,并作为预编译版本提供,以便关联到较旧版本的供应商映像。

从 Android 9 开始,新版 Android 将在 Android 源代码中包含较低版本 Android 的 VNDK-core 和 VNDK-SP 目录的至少一个快照。编译时,所需快照将安装到 /system/lib[64]/vndk-${VER}/system/lib[64]/vndk-sp-${VER}(供应商分区可以使用的目录),其中 ${VER} 是表示 VNDK 快照版本名称的字符串变量。

由于每个 VNDK 版本的 VNDK 快照库可能各不相同,因此 VNDK 快照还包含按以下格式安装的链接器命名空间配置:etc/ld.config.${VER}.txt/etc/llndk.libraries.${VER}.txt/etc/vndksp.libraries.${VER}.txt

示例:升级系统映像和供应商映像

无需快照;无需针对 VNDK 快照进行其他配置即可编译。

示例:仅升级系统映像

必须在系统映像中包含供应商映像的 VNDK 快照和链接器命名空间配置文件。系统会自动配置链接器命名空间配置文件,以在 /system/lib[64]/vndk-${VER}/system/lib[64]/vndk-sp-${VER} 中搜索 VNDK 库。

图 1. 仅升级系统映像

示例:升级系统映像,少量更改供应商映像

根据 VNDK 快照编译供应商映像尚不受支持,因此您必须使用原始源代码单独编译供应商映像,然后按上一示例中所述升级系统映像。

VNDK 快照架构

要使 Android 9 系统映像与 Android 8.1 供应商映像兼容,必须为 Android 9 系统映像提供与 Android 8.1 供应商映像匹配的 VNDK 快照,如下所示:

图 2. VNDK 快照架构

VNDK 快照设计包括以下方法:

  • 为 VNDK-core 和 VNDK-SP 库生成快照。Android 9 包含一个脚本,您可以使用它来制作当前 VNDK 版本的快照。此脚本将 /system/lib[64]/vndk-28/system/lib[64]/vndk-sp-28 中的所有库组合在一起,这些库是采用当前源代码以 VNDK 快照形式编译的,其中 28 是 Android 9 的 VNDK 版本。快照还包含链接器命名空间配置文件 /etc/ld.config.28.txt/etc/llndk.libraries.28.txt/etc/vndksp.libraries.28.txt。生成的快照将用于较新的 Android 版本(高于 Android 9 的版本)。
  • 从快照安装预编译的 VNDK-core 和 VNDK-SP 库。在 Android 9 中,VNDK 快照具有一组预编译的 VNDK-core 库和一组 VNDK-SP 库,以及链接器命名空间配置文件。如果您提供了要安装的 VNDK 快照版本列表,系统映像会在编译时将 VNDK 快照库安装到 /system/lib[64]/vndk-${VER}/system/lib[64]/vndk-sp-${VER} 目录,并将这些 VNDK 快照的链接器命名空间配置文件安装到 /etc 目录。

VNDK 版本控制

每个 Android 版本都只有一个 VNDK 快照,并且 SDK 版本用作 VNDK 版本(这意味着 VNDK 版本必须采用整数,例如 Android 8.1 的 VNDK 版本为 27)。Android 版本发布时,VNDK 版本已确定。供应商分区使用的 VNDK 版本自动存储在 ro.vndk.version 属性中,可在运行时读取。然后,此版本用于识别一些库的供应商 VNDK 版本及命名空间配置的 VNDK 快照版本。

编译 VNDK 库

make vndk 命令可用于编译具有 vndk: { enabled: true, … } 的库,包括依赖项和命名空间配置文件。如果设置了 BOARD_VNDK_VERSION := current,则可使用 make 命令编译这些库。

由于这种编译方法不会从快照安装 VNDK 库,安装的 VNDK 库不具有 ABI 稳定性。不过,Android 版本发布时,当前 VNDK 版本的 ABI 已确定。此时,任何 ABI 损坏都属于编译错误,因此 Android 版本的补丁程序不得更改 VNDK 库的 ABI。