系统预置三方应用so库加载失败:System.err: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol...

1.问题:预置三方应用到system/app目录,且保持应用的签名即LOCAL_CERTIFICATE := PRESIGNED;预置成功后,使用应用过程中,应用闪退。但是直接安装(adb install或是把apk放在文件管理器中然后进行安装)不存在此问题。

2.关键Log:

12-22 19:33:30.664 10290 10290 W System.err: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "EVP_aead_null_sha1_ssl3" referenced by "/system/app/xxxAppName/xxxAppName.apk!/lib/arm64-v8a/libssl.so"...
……
12-22 19:33:30.664 10290 10290 W System.err: 	at java.lang.Runtime.loadLibrary0(Runtime.java:1071)
12-22 19:33:30.664 10290 10290 W System.err: 	at java.lang.Runtime.loadLibrary0(Runtime.java:1007)
12-22 19:33:30.664 10290 10290 W System.err: 	at java.lang.System.loadLibrary(System.java:1667)
12-22 19:33:30.664 10290 10290 W System.err: 	at com.baidu.mapsdkplatform.comapi.NativeLoader.a(NativeLoader.java:103)
……
12-22 19:33:30.667 10290 10290 E NativeLoader: loadException
12-22 19:33:30.667 10290 10290 E NativeLoader: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "EVP_aead_null_sha1_ssl3" referenced by "/data/data/xxx.xxx.xxx/files/libs/arm64-v8a/libssl.so"...
12-22 19:33:30.667 10290 10290 E NativeLoader: 	at java.lang.Runtime.load0(Runtime.java:938)
12-22 19:33:30.667 10290 10290 E NativeLoader: 	at java.lang.System.load(System.java:1631)
12-22 19:33:30.667 10290 10290 E NativeLoader: 	at com.baidu.mapsdkplatform.comapi.NativeLoader.f(NativeLoader.java:214)
……
12-22 19:33:30.676 10290 10290 E NativeLoader: BaiduMapSDK_map_v7_1_0 Failed to load.
12-22 19:33:30.676 10290 10290 E NativeLoader: ssl Failed to load.

在/system/vendor/lib/以及/system/vendor/lib64/下都有libssl.so

3.Android.mk文件如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := xxxAppName
LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := find_xxx-release.apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)

LOCAL_CERTIFICATE := PRESIGNED

include $(BUILD_PREBUILT)

4.分析过程:
(1).最开始错以为是找不到so库,所以在mk文件中增加了如下修改:

LOCAL_PREBUILT_JNI_LIBS_arm64 += \
    lib/arm64-v8a/libBaiduMapSDK_base_v7_1_0.so \
    lib/arm64-v8a/libBaiduMapSDK_map_v7_1_0.so \
    lib/arm64-v8a/libcrypto.so \
    lib/arm64-v8a/libgnustl_shared.so \
    lib/arm64-v8a/libhardware_jni.so \
    lib/arm64-v8a/libindoor.so \
    lib/arm64-v8a/liblocSDK8a.so \
    lib/arm64-v8a/libssl.so

验证依然不行,仔细看才发现不是so找不到,而是Fail to load:
12-22 19:33:30.676 10290 10290 E NativeLoader: BaiduMapSDK_map_v7_1_0 Failed to load.
12-22 19:33:30.676 10290 10290 E NativeLoader: ssl Failed to load.
所以此问题不是so库找不到的问题。

(2).排除权限问题
adb shell setenforce 0,设置成Permissive mode,无效,问题依然存在。(因为根本没有报avc问题,所以这步只是为了排除)

(3).开始查找Failed to load的解决办法
尝试了一系列百度上的办法,如:
在mk中添加:LOCAL_LDFLAGS += -fuse-ld=bfd    //无效
怀疑是混淆问题,在mk中添加: LOCAL_PROGUARD_ENABLED := disabled    //无效
怀疑是odex问题,在mk中添加: LOCAL_DEX_PREOPT := false    //无效

修改system/core/libnativeloader/native_loader.cpp中的:
修改前:static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
修改后:static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand:/system/app";
也无效。

5.问题原因:Android N 之后, third party app 会被限定不能使用非AOSP library (ex: libaal)
在N版本中为了增强安全性,三方应用不能随意加载系统没有暴露出来的库,从而会导致三方应用无法运行。
系统的应用,可以调用系统库,而三方应用,只能调用或者加载NDK 暴露出来的一些 库,如libc.so等之类的和他自身的一些库。
详细内容参考google 官方说明 https://source.android.com/devices/tech/config/namespaces_libraries.html

6.有效修改方案
方案一:应用预置成可卸载方案,即预置在data/app目录下,不会报错及闪退。
方案二:应用还是预置在system/app目录下不可卸载,但是修改签名为:LOCAL_CERTIFICATE := platform,不会报错及闪退。
方案三:根据log,此问题的原因是Android N 之后, third party app 会被限定不能使用非AOSP library;
              所以把机器中的system/etc/public.libraries.txt文件pull出来,把libssl.so添加到system/etc/public.libraries.txt文件中;
              即把libssl.so开放出来;然后再把public.libraries.txt文件push进去,重启手机即可验证。
              因为system/etc/public.libraries.txt文件是由/system/core/rootdir/etc/public.libraries.android.txt生成,
              所以真正的修改是:把libssl.so添加到/system/core/rootdir/etc/public.libraries.android.txt中;
              这样全编译出来,在system/etc/public.libraries.txt文件中就包含了libssl.so。完成~

2021.5.7日更新:

真正的原因是:应用自带的libssl.so包含一个外部lib未实现的函数(/system/lib64/libssl.so不包含),所以load失败;即系统的libssl.so与应用的libssl.so版本不一致导致。

上面的三种方案其实都不是好的解法,准确说不是从根本上解决,如第三种方式,这种方式由于把系统的libssl.so暴露出来,会导致其它同样使用了libssl.so库的三方应用出现闪退,原因也是系统的libssl.so与应用的libssl.so版本不一致导致。

解决方式:(1)应用把自带的libssl.so替换成系统的/system/lib64/libssl.so,可以解决此问题(验证可行);

                  (2)把系统的/system/lib64/libssl.so换成应用的libssl.so,可以解决此问题(验证可行);(百度SDK推荐,但是系统不推荐,怕出现不可控风险等);

即把应用和系统的libssl.so的版本统一起来,或者说版本可以不一样,只要不出现这种“应用自带的libssl.so包含一个外部lib未实现的函数(/system/lib64/libssl.so不包含)”即可。

其实之前的方案三与现在的解决方式没有本质的区别,都是使系统的libssl.so与应用的libssl.so版本一致,只不过方案三由于把系统的libssl.so暴露出来,影响太大,即对所有的三方应用均产生影响;而现在的解决方式(1)只会对单独的应用产省影响。

可以参考百度关于Android定位SDK的说明 http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/create-project/android-studio

猜你喜欢

转载自blog.csdn.net/hanhan1016/article/details/111908771