在 arm64 平台中删除了获取 android 系统属性的 API

Posted

技术标签:

【中文标题】在 arm64 平台中删除了获取 android 系统属性的 API【英文标题】:API to get android system properties is removed in arm64 platforms 【发布时间】:2015-04-09 09:56:51 【问题描述】:

我正在使用 sys/system_properties.h 中的 __system_property_get() 来获取系统属性。我正在尝试使用 r10c ndk,因为我需要 arm64 工具链。

__system_property_get() 在 libc.so 中定义。下面是 armv5/armv7a 的 libc.so 的 readelf 输出。

readelf -Ws libc.so | grep property_get

       194: 00009100    20 FUNC    GLOBAL DEFAULT    4 __system_property_get
       198: 00009100    20 FUNC    GLOBAL DEFAULT    4 __system_property_get

但是,看来 arm64 版本已将其删除!我收到一个链接器错误,说它没有定义。我分析了arm64的所有共享库,但没有一个有那个符号。

是否有替代 API 来获取本机代码中的系统属性?

谢谢!

【问题讨论】:

【参考方案1】:

它是原生应用程序的有用 API,就像 Java 应用程序一样,它源自原生端(参见 http://rxwen.blogspot.com/2010/01/android-property-system.html),其他 Android 系统代码使用它,因此不太可能很快消失。

#include <android/log.h>
#include <dlfcn.h>

#if (__ANDROID_API__ >= 21)
// Android 'L' makes __system_property_get a non-global symbol.
// Here we provide a stub which loads the symbol from libc via dlsym.
typedef int (*PFN_SYSTEM_PROP_GET)(const char *, char *);
int __system_property_get(const char* name, char* value)

    static PFN_SYSTEM_PROP_GET __real_system_property_get = NULL;
    if (!__real_system_property_get) 
        // libc.so should already be open, get a handle to it.
        void *handle = dlopen("libc.so", RTLD_NOLOAD);
        if (!handle) 
            __android_log_print(ANDROID_LOG_ERROR, "foobar", "Cannot dlopen libc.so: %s.\n", dlerror());
         else 
            __real_system_property_get = (PFN_SYSTEM_PROP_GET)dlsym(handle, "__system_property_get");
        
        if (!__real_system_property_get) 
            __android_log_print(ANDROID_LOG_ERROR, "foobar", "Cannot resolve __system_property_get(): %s.\n", dlerror());
        
    
    if (!__real_system_property_get) return (0);
    return (*__real_system_property_get)(name, value);
 
#endif // __ANDROID_API__ >= 21

【讨论】:

谢谢你,bleater - 有用的代码。在我的特定 NDK 标头组合中,我必须使用 RTLD_LAZY 代替 RTLD_NOLOAD,它运行良好。 从 NDK r11 开始,它似乎作为一个全局符号重新出现。 我回来是因为android.googlesource.com/platform/ndk/+/…。我猜 Google 从来没有认真考虑过像“稳定的 API/ABI”这样的事情。 什么是 PFN_SYSTEM_PROP_GET ? 根据typedef,它是为了方便声明函数指针而定义的类型。【参考方案2】:

在较旧的 NDK 中,这不是官方支持的 API。它在早期被错误地暴露于 32 位 ABI,但直到正式支持才暴露于 64 位 ABI。无论如何,它由系统在所有 API 级别公开,因此无论 ABI 或 minSdkVersion 是什么,较新的 NDK 都能够使用它。

【讨论】:

如果它不应该是公共 API(但为了 ABI 兼容性而保留实现),它也应该从 NDK 标头中删除(至少对于 64 位版本的标头)。我也在b.android.com/143627 提交了一个关于此的问题/错误报告。 是的,标题仍然存在一个错误。感谢您的报告。 是的。 API 仍然存在于标题中,这促使我在 NDK 的所有库中搜索符号。我正在使用本机库中的系统属性获取设备的序列号、型号等。有没有其他方法可以做到这一点? 您可以阅读来自/system/build.prop的信息。您可以查看source for the Java API 以获取此信息,以确定哪些键映射到哪些值。 您也可以直接调用 Java API。这可能是最好的解决方案,因为 build.prop 不能保证是稳定的(甚至存在)。【参考方案3】:

确认@bleater 的答案是未公开的 __system_properties_* 符号的解决方法:根据需要 dlopen libc 和 dlsym。

【讨论】:

以上是关于在 arm64 平台中删除了获取 android 系统属性的 API的主要内容,如果未能解决你的问题,请参考以下文章

linux查询静态库是arm平台还是x86平台

如何在 arm64 主机平台上运行 amd64 docker 镜像

arm64-v8a 静态成员模板 undefined reference to

Android push framework.jar 解决机器无法正常开机

删除/重新添加文件,现在我得到架构 arm64 的未定义符号:

应该使用哪个 Android 虚拟设备在 Windows 上启动 arm64-v8a APK?