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。
最后,如果一切都失败了,您可以尝试使用dlopen
和dlsym
在运行时动态加载函数,但您需要找出它到底包含在哪个模块中。
【讨论】:
#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的主要内容,如果未能解决你的问题,请参考以下文章
JNI技术。开发时在Android或Linux平台上,所以呢?
Android 11.0源码系列之IMSInputManager