Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Android VNDK使用原理

Android VNDK使用及原理深入探究

作者:戈壁老王

这篇文章主要为大家介绍了Android VNDK使用及原理深入探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

为何要使用 VNDK?

VNDK的全称是Vendor Native Development Kit,是Android 8.0引入的一种新技术。它表现一系列库的合集,用于让供应商开发自己的HALs。VNDK 包含在 system.img 中,并在运行时与供应商代码动态关联。

官方文档的解释给我的感觉其目的就是收敛Android的碎片化。不仅仅VNDK,Android 8.0引入许多的技术都是为了将System与Vendor分割开来。这样可以保持Android核心系统的纯净性,而将碎片化扔给供应商维护。渐渐的芯片供应商和设备厂商可以无需关心Android系统的实现,仅仅使用VNDK就可以完成产品开发。

VNDK相关概念

供应商模块

供应商模块是特定于供应商的可执行文件或共享库,这些模块将安装到供应商分区中。

Framework共享库

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

供应商进程需要使用Framework共享库可能随系统的更新而发生变化。为了保证供应商模块在多个Android版本上皆可正常工作,根据Framework共享库的特性不同,将其三个子类别:

LL-NDK

LL-NDK 共享库是具有稳定 ABI 的共享库。框架模块和供应商模块均具有相同的最新实现。对于每个 LL-NDK 共享库,Android.bp 都包含一个 llndk_library 模块定义:

llndk_library {
    name: "libvndksupport",
    symbol_file: "libvndksupport.map.txt",
}

该模块定义指定了模块名称和符号文件,后者描述了对供应商模块可见的符号。例如:

LIBVNDKSUPPORT {
  global:
    android_load_sphal_library; # vndk
    android_unload_sphal_library; # vndk
  local:
    *;
};

Same-Process HAL (SP-HAL)

Same-Process HAL (SP-HAL) 是预定义的的一组HAL,作为供应商共享库进行实现,并被加载到Framework进程中。SP-HAL 必须仅依赖于 LL-NDK 和 VNDK-SP。VNDK-SP 是一部分预定义的符合条件的 VNDK 库。VNDK-SP 库会被仔细审查,以确保将 VNDK-SP 库双重加载到Framework进程中不会导致问题。SP-HAL 和 VNDK-SP 均由 Google 定义,并通过链接器命名空间进行隔离。

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

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

以下 VNDK-SP 依赖项 (VNDK-SP-Private) 对 SP-HAL 来说是不可见的:

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

VNDK 库简介

VNDK 定义了可与供应商代码相关联的库集:VNDK-core、VNDK-SP 和 LL-NDK,并阻止供应商使用不在 VNDK 集内的库。

VNDK-core 库安装在 /system/lib[64]/vndk-${VER} 中,仅适用于 API 级别为 ${VER} 的供应商进程。${VER} 可以通过/vendor/default.prop中的系统属性ro.vndk.version获取。系统进程不得使用这些库,而必须使用安装在 /system/lib[64] 中的库。由于每个进程都具有严格的命名空间限制,因此不会造成重复加载 VNDK-core 库。要在 VNDK-core 中添加库,请将以下内容添加到 Android.bp 中:

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

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

目录

VNDK库可以大致划分为以下目录:

供应商模块从 /system/lib[64] 中加载 VNDK 库。

VNDK 电子表格

Google 会提供一个符合条件的 VNDK 电子表格(例如 eligible-list.csv),该电子表格会标记可由供应商模块使用的框架共享库:

标记说明
LL-NDK可由框架模块和供应商模块使用的共享库(具有稳定的 ABI/API)。
LL-NDK-PrivateLL-NDK 库的私有依赖项。供应商模块不得直接访问此类库。
VNDK-SPSP-HAL 框架共享库依赖项。
VNDK-SP-Private所有供应商模块都无法直接访问的 VNDK-SP 依赖项。
VNDK面向供应商模块(SP-HAL 和 SP-HAL-Dep 除外)提供的框架共享库。
VNDK-Private所有供应商模块都无法直接访问的 VNDK 依赖项。
FWK-ONLY供应商模块不得(直接或间接)访问、仅限框架使用的共享库。
FWK-ONLY-RS供应商模块不得访问(RS 用途除外)、仅限框架使用的共享库。

下表描述了适用于供应商共享库的标记:

标记说明
SP-HALSame-Process HAL 实现共享库。
SP-HAL-DepSP-HAL 供应商共享库依赖项(也称为 SP-HAL 依赖项,不包括 LL-NDK 和 VNDK-SP)。
VND-ONLY框架模块不可见且不得访问的共享库。所复制的扩展后 VNDK 库也将被标记为 VND-ONLY。

标记之间的关系:

VNDK 快照

VNDK 快照就是一组预编译的库文件和配置文件的集合。因为VNDK的实质就是要规范供应商的开发,如果保证VNDK接口稳定的标准化,供应商就无需修改VNDK库。系统只要提供所有VNDK版本的二进制文件,就可以满足供应商的开发。这些需求的文件就是VNDK快照需要提供的内容。

VNDK 快照包含以下文件:

以下示例展示了 arm64 (TARGET_ARCH=arm64) VNDK 快照 ZIP 文件 (android-vndk-arm64.zip) 的目录结构。

供应商镜像会依赖于特定版本的VNDK,所以系统镜像中应该提供供应商需求的VNDK版本的镜像。即使系统镜像与供应商镜像使用不同版本的Android进行编译,但是只要保证系统镜像能够提供正确的VNDK就保证正常运行。下图展示了Android P系统镜像使用Android O供应商镜像的场景。

启用 VNDK

编译选项

在 BoardConfig.mk添加BOARD_VNDK_VERSION=current可以在编译过程开启VNDK。也可以在编译模块时传递该编译选项,例如: m -j BOARD_VNDK_VERSION=current MY-LIB)。

当启用 BOARD_VNDK_VERSION=current 后,编译系统会检查库的依赖性和头文件的合法性。

启用 BOARD_VNDK_VERSION后,系统会移除多个默认的全局头文件搜索路径。模块使用这些路径下的头文件时,需要明确指定与 header_libsstatic_libs 和/或 shared_libs 的依赖关系。这些路径中包括:

供应商变体库

在 Android.bp 文件中,cc_librarycc_library_staticcc_library_shared 和 cc_library_headers 模块定义支持三个与 VNDK 相关的属性:vendor_availablevndk.enabled 和 vndk.support_system_process

如果 一个库标记为vendor_available 或 vndk.enabled 为 true,则可能被编译两次,生成两种变体:核心变体和供应商变体。

下表总结了编译系统如何处理供应商变体,

vendor_availablevndk .enabledvndk. support_system_process供应商变体说明
truefalsefalse供应商变体为 VND-ONLY。共享库将安装到 /vendor/lib[64] 中。
truefalsetrue无效(编译错误)
truetruefalse供应商变体为 VNDK。共享库将安装到 /system/lib[64]/vndk-${VER} 中。
truetruetrue供应商变体为 VNDK-SP。共享库将安装到 /system/lib[64]/vndk-sp-${VER} 中。
falsefalsefalse没有供应商变体。此模块为 FWK-ONLY。
falsefalsetrue无效(编译错误)
falsetruefalse供应商变体为 VNDK-Private。共享库将安装到 /system/lib[64]/vndk-${VER} 中。供应商模块不得直接使用这些变体。
falsetruetrue供应商变体为 VNDK-SP-Private。共享库将安装到 /system/lib[64]/vndk-sp-${VER} 中。供应商模块不得直接使用这些变体。

注意:供应商可以为其模块设置 vendor_available,但不得设置 vndk.enabled 和 vndk.support_system_process,因为供应商模块无法在通用系统映像 (GSI) 中找到它们。

条件编译

默认情况下,Android 编译系统会为供应商变体和 VNDK 扩展定义 __ANDROID_VNDK__。您可以使用 C 预处理器防护程序保护代码:

void all() { }

#if !defined(__ANDROID_VNDK__)
void framework_only() { }
#endif

#if defined(__ANDROID_VNDK__)
void vndk_only() { }
#endif

除了 __ANDROID_VNDK__,还可以在 Android.bp 中指定不同的 cflags 或 cppflags。在 target.vendor 中指定的 cflags 或 cppflags 是专门针对供应商变体的。

例如,以下 Android.bp 定义了 libexample 和 libexample_ext。它为libexample的供应商变体定义了"LIBEXAMPLE_ENABLE_VNDK=1",为libexample的扩展库定义了 "LIBEXAMPLE_ENABLE_VNDK=1" 和"LIBEXAMPLE_ENABLE_VNDK_EXT=1"。

cc_library {
    name: "libexample",
    srcs: ["src/example.c"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    target: {
        vendor: {
            cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"],
        },
    },
}

cc_library {
    name: "libexample_ext",
    srcs: ["src/example.c"],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample",
    },
    cflags: [
        "-DLIBEXAMPLE_ENABLE_VNDK=1",
        "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1",
    ],
}

VNDK 扩展

Android还提供了VNDK扩展的方法,就是使用自己修改的VNDK共享库来替换原始的VNDK共享库。因为供应商很可能根据自己的需求来更改AOSP库的源码,可能是为了提高性能,或者添加新钩子、新 API 或新功能。VNDK 扩展库会安装到 /vendor/lib[64]/vndk[-sp] 中,并在系统运行时会替换原始的 VNDK 共享库。

在 Android 9 及更高版本中,Android.bp 本身支持 VNDK 扩展。要编译 VNDK 扩展,请定义另一个具有 vendor:true 和 extends 属性的模块:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
}

具有 vendor:truevndk.enabled:true 和 extends 属性的模块可定义 VNDK 扩展:

VNDK-SP 扩展必须从 VNDK-SP 共享库进行扩展,就是说在定义时必须包含相同的vndk.support_system_process 。VNDK 扩展(或 VNDK-SP 扩展)也可以依赖于其他供应商共享库:

cc_library {
    name: "libvndk_sp",
    vendor_available: true,
    vndk: {
        enabled: true,
        support_system_process: true,
    },
}

cc_library {
    name: "libvndk_sp_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk_sp",
        support_system_process: true,
    shared_libs: [
        "libvendor",
    ],
}

cc_library {
    name: "libvendor",
    vendor: true,
}

如果供应商模块依赖于由 VNDK 扩展定义的其他 API,则该模块必须在其 shared_libs 属性中指定 VNDK 扩展的名称:

// A vendor shared library example
cc_library {
    name: "libvendor",
    vendor: true,
    shared_libs: [
        "libvndk_ext",
    ],
}

// A vendor executable example
cc_binary {
    name: "vendor-example",
    vendor: true,
    shared_libs: [
        "libvndk_ext",
    ],
}

如果供应商模块依赖于 VNDK 扩展,则这些 VNDK 扩展将自动安装到 /vendor/lib[64]/vndk[-sp] 中。如果某个模块不再依赖于 VNDK 扩展,请向 CleanSpec.mk 添加一个清理步骤,以移除共享库。例如:

$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)

规则和Sepolicy

VNDK 规则

完整的 VNDK 规则列表如下。

sepolicy

本部分中介绍的框架进程对应于 sepolicy 中的 coredomain,而供应商进程对应于 non-coredomain。例如,/dev/binder 只能在 coredomain 中被访问,而 /dev/vndbinder 只能在非 coredomain 中被访问。

类似政策会限制对系统分区和供应商分区上的共享库的访问。下表列出了访问不同类别的共享库时所需的权限:

类别分区是否可从 coredomain 访问是否可从 非 coredomain 访问
LL-NDK系统
LL-NDK-Private系统
VNDK-SP/VNDK-SP-Private系统
VNDK-SP-Ext供应商
VNDK系统
VNDK-Ext供应商
FWK-ONLY系统
FWK-ONLY-RS系统
SP-HAL供应商
SP-HAL-Dep供应商
VND-ONLY供应商

LL-NDK-Private 和 VNDK-SP-Private 必须从这两个域中都可访问,因为非 coredomain 会间接访问这些库。同样,SP-HAL-Dep 必须可从 coredomain 访问,因为 SP-HAL 依赖该域。

same_process_hal_file 标签

供应商分区中包含下面几个库。确保这些库既可以从 coredomain 访问,又可以从非 coredomain 访问。

将这些文件明确标记为 same_process_hal_file。因为在默认情况下,从 coredomain 无法访问 vendor 分区中的任何内容。请向供应商特定的 file_contexts 文件中添加与以下命令行类似的命令行:

/vendor/lib(64)?/hw/libMySpHal\.so        u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/vndk-sp/libBase\.so      u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libBaseInternal\.so      u:object_r:same_process_hal_file:s0

参考文档:

Android Source: VNDK

以上就是Android VNDK使用及原理深入探究的详细内容,更多关于Android VNDK使用原理的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文