1.VNDK是什么
VNDK 的全称是 Vendor Native Development Kit,中文翻译过来叫“供应商原生开发套件”。本身实际上指的是 Google 提供给 Vendor 用来开发自己 HAL 的一套库。但实际上这个概念的引入有一个很大的背景,就是 Treble 项目。自 Android O(8.0)以来,Google 引入了 Treble 架构,希望对 vendor 和 system 分区进行解耦处理。期望实现的目标:
“In an ideal Android 8.0 and higher world, framework processes do not load vendor shared libraries, all vendor processes load only vendor shared libraries (and a portion of framework shared libraries), and communications between framework processes and vendor processes are governed by HIDL and hardware binder.”
注解:Google(AOSP)负责维护 system 分区里的内容和升级;vendor 负责维护 vendor 分区中的内容。为了解耦(所谓解耦,在官方文档上常用 dependency 指代,实际可以理解为动态库链接意义上的依赖),位于 system 分区的 framwork 进程不可以加载 vendor 分区中的共享库等资源,vendor 分区中的 vendor 进程(我理解这指的应该主要是提供 HAL 服务的后台进程)仅加载 vendor 分区中的共享库(vendor 编写的 HAL so)以及也可能会加载部分 system 分区中的共享库(具体是什么后面会总结),而 framework 进程和 vendor 进程之间按照 HIDL/AIDL 方式定义的接口,通过 IPC/hwbinder 的方式来实现通信。
这张图的红色虚线上面就是 system 分区,下面就是 vendor 分区。其中几个概念 LLNDK、VNDK、SP-HAL 的概念下面再聊。这里关键是要注意的红色禁止符号强调的内容,就是上面我们说的引入解耦后不允许出现的链接和加载情况。
注意该图中的 libcamera_metadata.so
被标注为 VNDK,这个就是我们关注的 VNDK。
那么 VNDK 到底是什么?官方的定义:
Eligible VNDK Libraries (VNDK) are Framework Shared Libraries that are safe to be copied twice. Framework Modules and Vendor Modules can link with their own copies. A framework shared library can become an eligible VNDK library only if it satisfies the following criteria:
- It does not send/receive IPCs to/from the framework.
- It is not related to ART virtual machine.
- It does not read/write files/partitions with unstable file formats.
- It does not have special software license which requires legal reviews.
- Its code owner does not have objections to vendor usages.
我的理解是,之所以 framework 和 vendor 的 modules(注,这里的 modules 包括了 so 和 exe 等资源) 存在耦合,关键是因为它们都依赖于同一份公共的库,系统升级时一旦这些库的 ABI/API 发生变化,那么负责 framework modules 的 Google 和负责 vendor modules 的各个 Vendor 都要同步升级,这是一件很麻烦的事情。
所以改造的核心对象就是 framework modules 和 vendor modules 都依赖的那份公共的库。也就是下图中的那个 Dependencies。这些 Dependencies 其实就是在引入 Treble 设计之前原先 framework 维护的那组 framework modules。
经过深入的分析,Google 把这些 Dependencies 基于解耦的需要又再次分为两大类:
Dependencies 中的第一类库的 API/ABI 相对稳定的,不会因为 AOSP 的升级而轻易改变,我们把它们叫做 LL-NDK,即 Low Level 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, and libvulkan.so,
对于 LL-NDK,仍然保持一份就好,framework modules 和 vendor modules 共享同一套 LL-NDK 库。
除了 LL-NDK,Dependencies 中还有一些 framework modules 会被 vendor modules 访问。注意如果出现这种依赖情况我们对这些 framework modules 还是和原来一样只维护一份就不合适了。如下 【图 3】所示,假设 libcamera_metadata.so
这个库既会被 Framework 中的 modules 访问,又会被 vendor modules(图上是 [email protected]
)访问。那么这里的 libcamera_metadata.so
就是一个耦合点。Google 采用的解耦方法也很简单,就是对于 libcamera_metadata
,我们在编译时会将其做成两份,一份给 Framework 的 modules 用,即图中的 libcamera_metadata.so (FWK-ONLY)
,一份给 vendor modules 用,即图中的 libcamera_metadata.so (VNDK)
。而给 vendor modules 用的这份 so 就叫 VNDK。在 【参考 4】 中基于 build system 的上下文环境,libcamera_metadata.so (FWK-ONLY)
也叫做 "core variant",libcamera_metadata.so (VNDK)
也叫做 "vendor variant"。
分成两份后,即引入多出来的那份 VNDK 后对升级的影响见下图。假设我们在构建某个 AOSP 版本,譬如 Android 8 时,采用的 Framework 和 VNDK 版本都是 26,结合上图,libcamera_metadata.so (FWK-ONLY)
属于 Framework-26 部分,libcamera_metadata.so (VNDK)
属于 VNDK-26,[email protected]
属于 Vendor-26 部分。那么 vendor module 构建时都是基于 VNDK-26 的,工作正常。升级系统时,我们制作 system image 时,里面可以带上新的 Framework-27,其中 libcamera_metadata.so (FWK-ONLY)
升级到新的 27,而 VNDK 部分依然采用 VNDK-26。这样新系统启动后,Vendor-26 部分的 [email protected]
依然会链接 VNDK-26 版本中的停留在 26 版本的 libcamera_metadata.so (VNDK)
,framework 会链接 27 版本的 libcamera_metadata.so (FWK-ONLY)
。也就是说,一式两份后,FWK-ONLY 和 VNDK 两部分可以单独升级,互不干扰,也就是解耦了。而且注意 FWK-ONLY 和 VNDK 这两部分还都在 Google 所掌控的 system image 中,Google 的控制权依然稳固。
值得注意的一点是,Dependencies 中的这第二类 framework modules 并不是都需要一式两份,这个实际 build 时也要看情况而定,具体的描述如下:
If some framework modules depend on this module, the core variant is built. If some vendor modules depend on this module, the vendor variant is built.
2.VNDK 在系统中存放的位置
VNDK APEX 章节有以下描述:
In Android 10 and lower, modules with vndk.enabled were installed in /system/lib[64]/vndk[-sp]-${VER}
. In Android 11 and higher, VNDK libraries are packaged in an APEX format and the name of VNDK APEX is com.android.vndk.v${VER}
. Depending on the device configuration, VNDK APEX is flattened or unflattened and is available from the canonical path /apex/com.android.vndk.v${VER}
.
实验的系统是 aosp 12,所以我们可以去看一下 out/target/product/emulator_riscv64/system/apex
, 下面的确存在一个 com.android.vndk.current.apex
文件。这个文件在系统启动阶段会被解压开后挂载在 /apex/com.android.vndk.v${VER}
下。
开模拟器登录会看到 /apex
下有个 com.android.vndk.v31
和 com.android.vndk.v31@1
,具体解压开的是哪个我还没去仔细看,但这两个目录的文件都是一样的。以 /apex/com.android.vndk.v31@1/lib64/[email protected]
为例,我们会发现 /system/lib64/
下也有一个同名的 [email protected]
。/system/lib64/[email protected]
就是 "core variant",而 /apex/com.android.vndk.v31@1/lib64/[email protected]
就是 "vendor variant"。
3.VNDK-SP
VNDK-SP 其本质也是一种 VNDK,唯一的例外是这些 so 专用于 SP-HAL。所以上面涉及 VNDK 的内容对 VNDK-SP 也是适用的。这里我们重点关心一下 VNDK-SP 和普通 VNDK 的区别。
SP-HAL 的定义有详细定义,摘录如下,更多的 SP-HAL 的介绍 :
Same-Process HAL (SP-HAL) is a set of predetermined HALs implemented as Vendor Shared Libraries and loaded into Framework Processes.
SP-HALs must depend only on LL-NDK and VNDK-SP.
VNDK-SP is a predefined subset of eligible VNDK libraries.
下面这幅图很好地给出了 SP-HAL 和 VNDK-SP 的例子
图中 libGLES_${chipset}.so
就是一个 SP-HAL。譬如 surfaceflinger 这个 framework 维护的system 进程要进行 GPU 合成的时候,需要访问位于 vendor 分区的 GPU 驱动(libvendor_gpu.so
),此时需要通过 libGLES_${chipset}.so
这个 HAL 代理,和普通 HAL 通过 IPC 方式不同,SP-HAL 是将 该 so 直接 dlopen 加载到 surfaceflinger 进程。由于属于 framework module 的 surfaceflinger 和来自 vendor module 的 libGLES_${chipset}.so
都要依赖 libcutils.so
,所以为了升级解耦的需要,我们同样要遵循 VNDK 的要求,将 libcutils.so
一式两份,其中我们称给 libGLES_${chipset}.so
链接的那份 so 为 VNDK-SP。
注意这里和普通 VNDK 有所不同的是,第三张图中 HAL service 和 client 之间采用 IPC,所以 libcamera_metadata.so (FWK-ONLY)
和 libcamera_metadata.so (FWK-VNDK)
实际加载在两个不同的进程中,不存在名字冲突的问题。但是在 上图 中 libcutils.so (FWK-ONLY)
和 libcutils.so (VNDK-SP)
两个 so 都会被加载到 surfaceflinger 这个进程中,为了解决加载冲突的问题,Google 又引入了 linker namespace 解决方案。这个专题也比较大,这里暂不展开。
4.VNDK的典型Issue
问题描述与分析
vndksupport:Could not load demo.so from default namespace:dlopen failed: library “libstdc++.so” not found.
demo.so位于vendor下面,找不到libstdc++.so,而libstdc++.so的库位于system/lib和system/lib64中。
这说明vendor下面的库引用libstdc++.so时,无法找到system/lib中的libstdc++.so。
Android O之后的变化,从 LL-NDK 库中移除 libstdc++.so,不再支持 libstdc++.so,改用 libc++.so。
这导致一些老的平台上依旧使用了 libstdc++.so,而产生了not found问题。
相关目录文件:
\system\core\rootdir\etc\
Solution 1
system/core/rootdir/etc/ld.config.txt文件中,[vendor]下,增加:
# Access to system libraries are allowed namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER% namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER% namespace.default.search.paths += /system/${LIB} namespace.default.search.paths += /product/${LIB}
Solution 2
当google/wahoo/BoardConfig.mk中,打开如下编译选项时:
BOARD_VNDK_VERSION := current
根据build/make/core/Makefile中的判断:
# ----------------------------------------------------------------- # FINAL_VENDOR_DEFAULT_PROPERTIES will be installed in vendor/default.prop if # property_overrides_split_enabled is true. Otherwise it will be installed in # ROOT/default.prop. ifdef BOARD_VNDK_VERSION ifeq ($(BOARD_VNDK_VERSION),current) FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION) else FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION) endif ifdef BOARD_VNDK_RUNTIME_DISABLE FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true endif else FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION) FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true endif
最终default.prop中会有ro.vndk.lite=true。当ro.vndk.lite=true时,动态链接器将加载 /system/etc/ld.config.vndk_lite.txt 中的链接器命名空间配置,这仅会隔离 SP-HAL 和 VNDK-SP。
即system/core/rootdir/etc/ld.config.vndk_lite.txt
而system/core/rootdir/etc/ld.config.vndk_lite.txt
中,已经包含了namespace.default.search.paths += /system/${LIB}。
因此,我们可以采取的操作为:
注释掉**/**/BoardConfig.mk中的编译选项:
#BOARD_VNDK_VERSION := current
Solution 3(不推荐)
找到libstdc++.so,将libstdc++.so文件拷贝到vendor/lib或者vendor/lib64中去。
参考链接
- 学习笔记: VNDK 基本概念 https://gitee.com/aosp-riscv/working-group/blob/master/articles/20220923-vndk.md
- Vendor Native Development Kit (VNDK) overview https://source.android.google.cn/docs/core/architecture/vndk
- 关于Android 供应商原生开发套件(VNDK)引发的问题 https://blog.csdn.net/Sunxiaolin2016/article/details/103542190
标签:vendor,modules,system,vndk,so,Android,VNDK From: https://www.cnblogs.com/ArsenalfanInECNU/p/17785351.html