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相关概念

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

在 Android.bp 文件中,供应商模块必须将vendor或proprietary属性设置为 true。
在 Android.mk 文件中,供应商模块必须将 LOCAL_VENDOR_MODULE 或 LOCAL_PROPRIETARY_MODULE 设置为 true。

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

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

LL-NDK库:已知稳定的Framework共享库,它们的开发者致力于保持其 API/ABI 稳定性。LL-NDK 包含以下库:libEGL.so、libGLESv1_CM.so、libGLESv2.so、libGLESv3.so、libandroid_net.so、libc.so、libdl.so、liblog.so、libm.so、libnativewindow.so、libneuralnetworks.so、libsync.so、libvndksupport.so 和 libvulkan.so。
合格的 VNDK 库 (VNDK):可以安全复制两次的Framework共享库。Framework模块和供应商模块可以与其各自的库副本相关联。Framework共享库只有满足以下条件才能成为合格的 VNDK 库:

不向Framework发送或从Framework接收 IPC。
与 ART 虚拟机无关。
不读写文件格式不稳定的文件/分区。
没有需要法律审查的特殊软件许可。
其代码所有者不反对供应商使用该库。
框架专用库 (FWK-ONLY) :不属于上述类别的Framework共享库。此类库具有以下特点:

被视为Framework内部实现细节。
不得由供应商模块访问。
具有不稳定的 ABI/API,无 API/ABI 兼容性保证。
不会被复制。

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:

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.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-Private) 对 SP-HAL 来说是不可见的:

libRSCpuRef.so (Renderscript)
libRSDriver.so (Renderscript)
libbacktrace.so
libblas.so (Renderscript)
libbcinfo.so (Renderscript)
liblzma.so
libunwind.so
以下是具有 RS 例外的框架专用库 (FWK-ONLY-RS):

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

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] 包含所有Framework共享库,具体包括 LL-NDK、VNDK 和Framework专用库(包括 LL-NDK-Private 和一些与 VNDK-SP 中的库同名的库)。
/system/lib[64]/vndk-sp 包含适用于 Same-Process HAL 的 VNDK-SP 库。
/vendor/lib[64] 包含供应商扩展的 VNDK 库(DXUA 库或 DXUX VNDK 库)、Same-Process HAL 实现,以及其他供应商共享库。
/vendor/lib[64]/vndk-sp 可能包含供应商扩展的 VNDK-SP 库。
供应商模块从 /system/lib[64] 中加载 VNDK 库。

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

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

标记之间的关系:

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

VNDK 快照包含以下文件:

VNDK-core 和 VNDK-SP 共享库的供应商变体。

无需 LL-NDK 共享库,因为这类库是向后兼容的。
对于 64 位目标,TARGET_ARCH 和 TARGET_2ND_ARCH 库都将被编译并包含在内。
VNDK-core、VNDK-SP、LL-NDK 和 VNDK-private 库的列表,文件为 [vndkcore|vndksp|llndk|vndkprivate].libraries.txt。
链接器配置文件为 ld.config.txt。
许可文件。
module_paths.txt。记录所有 VNDK 库的模块路径;检查 GPL 项目是否已在指定 Android 源代码树中发布源代码时,需要用到这种文件。
以下示例展示了 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 后,编译系统会检查库的依赖性和头文件的合法性。

确保vendor对象仅依赖于VNDK库集:VNDK-core、VNDK-SP 和 LL-NDK。确保core组件不依赖与vendor组件。
移除全局头文件的依赖项,以便编译器可以明确是否使用-D__ANDROID_VNDK__来编译头文件。就是说全局头文件无法再使用传递方式包含在头文件内。
启用 BOARD_VNDK_VERSION后,系统会移除多个默认的全局头文件搜索路径。模块使用这些路径下的头文件时,需要明确指定与 header_libs、static_libs 和/或 shared_libs 的依赖关系。这些路径中包括:

frameworks/av/include
frameworks/native/include
frameworks/native/opengl/include
hardware/libhardware/include
hardware/libhardware_legacy/include
hardware/ril/include
libnativehelper/include
libnativehelper/include_deprecated
system/core/include
system/media/audio/include

供应商变体库
在 Android.bp 文件中,cc_library、cc_library_static、cc_library_shared 和 cc_library_headers 模块定义支持三个与 VNDK 相关的属性:vendor_available、vndk.enabled 和 vndk.support_system_process。

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

核心变体被视为Framework模块,将安装到 /system/lib[64] 中。
而供应商变体应被视为供应商模块。系统根据模块依赖性来决定是否编译变体,并进行依赖性检查。供应商变体安装路径会根据 Android.bp中的属性来决定。
下表总结了编译系统如何处理供应商变体,

注意:供应商可以为其模块设置 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:true、vndk.enabled:true 和 extends 属性的模块可定义 VNDK 扩展:

extends 属性必须指定基础 VNDK 共享库名称(或 VNDK-SP 共享库名称)。
VNDK 扩展(或 VNDK-SP 扩展)以扩展时所基于的基础模块名称命名。例如,libvndk_ext 的输出二进制文件是 libvndk.so,而非 libvndk_ext.so。
VNDK 扩展将安装到 /vendor/lib[64]/vndk 中。
VNDK-SP 扩展将安装到 /vendor/lib[64]/vndk-sp 中。
基础共享库必须同时具有 vndk.enabled:true 和 vendor_available:true。
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 规则列表如下。

框架进程不得从供应商分区中加载非 SP-HAL 共享库(此规则从 Android 8.1 开始严格地强制实施)。
供应商进程不得从系统分区中加载非 LL-NDK 库、非 VNDK-SP 库和非 VNDK 库(Android O 中并未严格地强制实施此规则,但未来版本中会这么做)。
注意:要想从未来版本(比 Android 8.0 更高的版本)仅针对框架的 OTA 中受益,就不得在搭载 Android 8.0 出厂的设备中违反此规则。
已安装的 VNDK 库必须是由 Google 定义的合格 VNDK 库的子集。
SP-HAL 和 SP-HAL-Dep 的外部依赖项必须仅限于 LL-NDK 库或由 Google 定义的 VNDK-SP 库。

SP-HAL 共享库的依赖项必须仅限于 LL-NDK 库、由 Google 定义的 VNDK-SP 库、其他 SP-HAL 库和/或可标记为 SP-HAL-Dep 库的其他供应商共享库。
只有当供应商共享库不是 AOSP 库,且其依赖项仅限于 LL-NDK 库、由 Google 定义的 VNDK-SP 库、SP-HAL 库和/或其他 SP-HAL-Dep 库时,才可标记为 SP-HAL-Dep 库。
VNDK-SP 必须保持独立。在 Android 8.0 中,系统以一种特殊方式处理 libRS_internal.so,但在未来版本中,其处理方式会被重新考虑。
不得通过非 HIDL 接口(包括但不限于 Binder、套接字、共享内存、文件等)进行框架-供应商通信。
系统分区必须足够大,以便容纳所有符合条件的 VNDK 库的两个副本,以及不符合条件的框架共享库的一个副本。

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

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

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

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

VNDK-SP-Ext,位于 /vendor/lib[64]/vndk-sp
SP-HAL,位于 /vendor/lib[64] 或 /vendor/lib[64]/hw
SP-HAL-Dep,位于 /vendor/lib[64] 或 /vendor/lib[64]/hw
将这些文件明确标记为 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使用原理的资料请关注vb.net教程C#教程python教程SQL教程access 2010教程xin3721自学网

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值