乐趣区

Android VNDK限制下的解决方案

你有没有遇到过这个错误呢?
F linker: CANNOT LINK EXECUTABLE “/system/bin/xxx”: library “libxxx.so” not found
首先在 android 生态里,一般的应用开发者,不会遇到这个问题。系统开发者也只有在某些情况下会遇到这个问题。什么情况呢?
我们先来了解下什么是 vndk 以及其规则。
VNDK 就是 vendor NDK
SDK(software development kit),NDK(native development kit) 都不陌生吧,尤其是 android 应用开发者来说,就是某某开发包包含了 api 及其规范等等使得你开发的 apk 可以在 android 上运行。那么怎么理解,vendor native development kit 呢,这要从 android 整个软硬件框架及其生态说起,开发者常说的 android 其实指的是 AOSP,而一个完整的 android 生态,至少包含四个个部分,一个是 android,一个是硬件厂家芯片,屏幕,整机等等,一个是应用开发者,一个是消费者(是硬件消费者同时也是软件,内容消费者)。可以看到 android 在产品架构上起了一个承上启下的作用,将硬件厂家和开发者连接在一起。这里有一个看似矛盾的地方,android 是谷歌开源的,而谷歌是一个商业公司不是慈善机构。谷歌开源的目的是推广它的广告系统从中得利,但是太开放版本混乱体验不一致反过来会损害它的利益。所以需要在开放的同时进行控制。如果 SDK,NDK 是应用开发者的开发规范,那 VNDK 是针对硬件厂家的开发规范。
谷歌是这样介绍 VNDK 的
在理想的 Android 8.0 及更高版本环境中,框架进程不加载供应商共享库,所有供应商进程仅加载供应商共享库(和一部分框架共享库),而框架进程与供应商进程之间的通信由 HIDL 和硬件 binder 控制。主要意思是,系统分区和 vendor 分区隔离,尤其系统分区内的框架进程不要链接加载 vendor 下的 so 库,规则不允许这样做,强行加载会报错,就是文章开头贴的错误。谷歌以这种方式保持系统对底层的统一,限制每个硬件厂家在底层对系统的不统一的修改。所以系统开发者如果用框架进程无论是已经存在的还是新增的去加载 vendor 下的库都会遇到这个问题。可能有人会说,android 是开源的,我把这个限制在源码里去掉就可以了啊,别忘了我们在之前一篇文章里说过谷歌会考试,这么做考试会不及格的。不及格就拿不到谷歌的印章,没有印章,产品想上市麻烦事有很多,所以这几行代码代价太高了,不能这么做。
如何满足 VNDK 的规则呢?
VNDK 给出了解决方案方案 1. 把 vendor 下的资源通过供应商进程的方式暴露出来,框架进程通过 hidl 或者硬件 binder 的方式与供应商进程通信达到访问 vendor 资源的目的。方案 2. 如果 vendor 下的资源比如 so 库,能够从 vendor 下彻底脱离,也可以拷贝一份到 system 下,这样合理的避开了这个问题,而且还省掉了开发供应商进程的成本,以及 hidl 或 binder 通信的消耗。
在框架进程必须要加载这个库的情况下,如果 vendor 下的 so 库能彻底脱离 vendor,拷贝一份在 system 是最佳的方案。为什么不是直接挪到 system 下,而是要拷贝一份呢?因为 so 放在 vendor 下就是因为 vendor 要用,而 vendor 进程只能加载一部分谷歌允许的框架 so,所以这个库如果不是谷歌允许的 so 只放在 system 下那 vendor 也加载不到了。这种情况两边都要放。
前几天也遇到了类似的问题
用框架进程去加载一个 vendor 下的共享库,vendor/lib/libxxx.so, vendor/lib64/libxxx.so,这个库是芯片厂家提供的。报告错误,F linker: CANNOT LINK EXECUTABLE “/system/bin/xxx”: library “libxxx.so” not found。正准备将 vendor 下的 libxxx.so 拷贝到 system 下,修改脚本的时候注意到一个叫 libxxx_system.so 被拷贝到了 system 下,libxxx_system.so 与 libxxx.so 同名,只是多了_system 后缀。突然一个想法闪过“libxxx_system.so 就是 libxxx.so 在 system 的拷贝”,初步通过 3 个步骤得到了确认 1. 看大小两个差不多 2. 看链接的库,两个 so 链接的库一样,而且都是谷歌允许的框架的 so3. 看符号表基本一样然后框架进程改成链接 system/lib/libxxx_system.so 和 system/lib64/libxxx_system.so 编译通过,运行通过,问题解决。看来芯片厂家已经做了相关的预案。
仅献给遇到此问题的朋友,F linker: CANNOT LINK EXECUTABLE “/system/bin/xxx”: library “libxxx.so” not found。
VNDK 详细介绍:https://source.android.com/de…

退出移动版