Android 11 JNI 禁用 fdsan

Posted

技术标签:

【中文标题】Android 11 JNI 禁用 fdsan【英文标题】:Android 11 JNI disable fdsan 【发布时间】:2021-11-14 21:58:17 【问题描述】:

我有一个使用带有本机库的库的应用,现在由于 fdsan 在 android 11 中崩溃。

我已联系库提供商,但他们不会提供解决此问题的新版本库,因此我需要能够以某种方式禁用 fdsan。

我认为解决方案是在我使用 Android 11 或更高版本时调用:

if(android_get_device_api_level()>=30)
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);

但由于错误无法编译:

使用未声明的标识符“android_fdsan_set_error_level”

因为这只是在 Android 10 (API 29) 中添加的

所以我的问题是如何在我的项目中调用这个函数? 我为此创建了一个特定的 cpp 文件和一个特定的库,所以我需要一些如何为这个库说它仅适用于 Android 10 或更高版本。 cpp 文件或 Android.mk 文件中是否有一些定义可以用来编译这个特定的库,只有在我的应用程序启动时才能从 Android 11 或更高版本中的 Java 调用?

【问题讨论】:

【参考方案1】:

根据文档here,您应该这样做:

if (android_fdsan_set_error_level) 
    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);

您必须将目标 SDK 设置为 10 或更高版本才能正常工作。

或者,如果要将其编译为单独的本机二进制文件,则可以使用条件编译。

包括this 文件。

然后做这样的事情:

#if __ANDROID_API__ >= __ANDROID_API_P__
    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
#endif

只要确保这个二进制文件永远不会在旧设备上加载,否则链接器会出错。 根据您的整个项目的构建方式,您可能需要为此打包一个单独的 APK。

最后,如果一切都失败了,您可以尝试使用dlopendlsym 在运行时动态加载函数,但您需要找出它到底包含在哪个模块中。

【讨论】:

#if ANDROID_API >= ANDROID_API_P 将不起作用。这是一个有条件的编译,因为我的目标是旧的 Android 版本,它根本不会编译 我确实尝试过 dlopen 和 dlsym,但从未找到它包含在哪个模块中 @FilipeMadureira 您可以尝试以下方法:使用此针对 Android 10 或更高版本的函数调用编译示例,然后在此上运行 objdump -T 命令。您需要 Linux 或 Mac 才能使用此命令,但它会准确显示每个函数的导入位置。 @FilipeMadureira 从我所见,我很确定谷歌将它内置到他们的 glibc 中,在 Android 上称为“Bionic”,但我不完全确定你需要来自@的名称987654330@. 感谢仿生/glibc 提示。它在 libc.so 中,所以我从那里加载了 android_fdsan_set_error_level() 并让它工作

以上是关于Android 11 JNI 禁用 fdsan的主要内容,如果未能解决你的问题,请参考以下文章

[RK3568][Android11]JNI调用流程分析

JNI技术。开发时在Android或Linux平台上,所以呢?

Opencv将Mat从Android传递到JNI错误

Android 11.0源码系列之IMSInputManager

Android 开创java世界(JNI Invocation API)

实现自己的HAL-11 控制led(jni 的编写),从app 到 hal 到底层内核kernel层的驱动 的实现