API to get android system properties is removed in arm64 platforms
Asked Answered
L

3

9

I am using __system_property_get() from sys/system_properties.h to get a system property. I am trying to use r10c ndk because I need arm64 toolchain.

__system_property_get() is defined in libc.so. Below is the readelf output of libc.so for armv5/armv7a.

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

But, looks like it has been removed for arm64 version! I am getting a linker error saying it is not defined. I analyzed all the shared libraries of arm64 but none of them have that symbol.

Is there an alternate API to get the system property in the native code?

Thank you!

Loralorain answered 9/2, 2015 at 15:43 Comment(0)
E
4

In older NDKs this was not an officially supported API. It was mistakenly exposed to the 32-bit ABIs early on, but wasn't exposed to the 64-bit ABIs until it was officially supported. Regardless, it is exposed by the system at all API levels, so newer NDKs are able to use this regardless of ABI or minSdkVersion.

Eads answered 9/2, 2015 at 18:29 Comment(8)
If it wasn't supposed to be a public API (but the implementation kept for ABI compatibility), it should be removed from the NDK headers as well (at least for the 64 bit version of the headers). I filed a question/bug report about this at b.android.com/143627 as well.Etude
Yeah, the header still being there is a bug. Thanks for the report.Eads
Yes. The API is still present in the header which prompted me to search for the symbols in all the libraries in the NDK. I am getting the device's serial number, model, etc using the system properties in my native library. Is there any other way to achieve this?Loralorain
You can read the information from /system/build.prop. You can check the source for the Java API for this information to figure out which keys map to which values.Eads
Thank you. I looked at that file and most of the properties are present in it. Although, I could not find ro.serialno in it. Probably it is coming from elsewhere.Loralorain
You can also just call up into the Java API. That's probably the best solution, as build.prop isn't guaranteed to be stable (or even present).Eads
@DanAlbert Did this removal get reverted since 2015? Is it correct to say that __system_property_get is deprecated, but still usable for reliably getting ro.build.version.sdk and the like? groups.google.com/forum/#!msg/android-ndk/yaOW7iG7jOE/…Fabiolafabiolas
Yeah, this answer is out of date. It's an officially supported API with an unfortunately unsupported looking name these days. I'll make an edit.Eads
E
10

It's useful API for native apps, just as it is for Java apps, it originates from the native side (see http://rxwen.blogspot.com/2010/01/android-property-system.html), and other Android system code uses it, so it's unlikely to go away soon.

#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
Eyelet answered 28/9, 2015 at 10:36 Comment(5)
Thank you, bleater - useful code. I had to use RTLD_LAZY in place of RTLD_NOLOAD in my particular combination of NDK headers and it works well.Swedish
As of NDK r11, it appears to be back as a global symbol.Eyelet
I was back due to android.googlesource.com/platform/ndk/+/…. I guess Google never take things like "stable API/ABI" into serious consideration.Luminiferous
what is PFN_SYSTEM_PROP_GET ?Shankle
As per the typedef, it's a type defined for convenience of declaring the function pointer.Eyelet
E
4

In older NDKs this was not an officially supported API. It was mistakenly exposed to the 32-bit ABIs early on, but wasn't exposed to the 64-bit ABIs until it was officially supported. Regardless, it is exposed by the system at all API levels, so newer NDKs are able to use this regardless of ABI or minSdkVersion.

Eads answered 9/2, 2015 at 18:29 Comment(8)
If it wasn't supposed to be a public API (but the implementation kept for ABI compatibility), it should be removed from the NDK headers as well (at least for the 64 bit version of the headers). I filed a question/bug report about this at b.android.com/143627 as well.Etude
Yeah, the header still being there is a bug. Thanks for the report.Eads
Yes. The API is still present in the header which prompted me to search for the symbols in all the libraries in the NDK. I am getting the device's serial number, model, etc using the system properties in my native library. Is there any other way to achieve this?Loralorain
You can read the information from /system/build.prop. You can check the source for the Java API for this information to figure out which keys map to which values.Eads
Thank you. I looked at that file and most of the properties are present in it. Although, I could not find ro.serialno in it. Probably it is coming from elsewhere.Loralorain
You can also just call up into the Java API. That's probably the best solution, as build.prop isn't guaranteed to be stable (or even present).Eads
@DanAlbert Did this removal get reverted since 2015? Is it correct to say that __system_property_get is deprecated, but still usable for reliably getting ro.build.version.sdk and the like? groups.google.com/forum/#!msg/android-ndk/yaOW7iG7jOE/…Fabiolafabiolas
Yeah, this answer is out of date. It's an officially supported API with an unfortunately unsupported looking name these days. I'll make an edit.Eads
G
-1

Confirming @bleater's answer as a workaround for the unexposed __system_properties_* symbols: dlopen libc and dlsym as needed.

Ganoid answered 3/12, 2015 at 23:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.