I seem to not find any documentation about android service wrappers and I'm stuck with "use of undeclared identificator "TJBatteryManager".
#include <Androidapi.Helpers.hpp>
#include <Androidapi.JNI.Telephony.hpp>
#include <Androidapi.JNI.Os.hpp>
...
int TGlobal::getBatteryLevel(){
_di_JObject BatterObj = SharedActivityContext()->getSystemService(TJContext::JavaClass->BATTERY_SERVICE);
return TJBatteryManager::Wrap(((_di_ILocalObject)BatterObj)->GetObjectID())->getIntProperty(BATTERY_PROPERTY_CAPACITY);
}
I found this syntax on some code samples and the project i'm working on already use this same process with TELEPHONY_SERIVCE and TJTelephonyManager::Wrap.
Am I the one that has to create this TJBatteryManager somewhere ?
I don't find any reference of TJTelephonyManager anywhere else than in this class tho.
Same thing about _di_JXXXX types. _di_JObject and _di_JTelephonyManager are used in my project and it seems they just come from the Androidapi includes, so why is it telling me _di_JBatteryManager does not exist ?
Related
I started out writing a simple C++ program that tried to get the handle of a service using
defaultServiceManager()->getService(String16('ServiceName'));
Which has now snowballed into this terrible dependency recursion. Ultimately what I need is:
libbinder for defaultServiceManager and getService
libutils for String16
Neither of these are available in the NDK. Their sources are in the SDK along with all the appropriate headers. I can get everything to behave nicely until link time:
undefined reference to `android::defaultServiceManager()'
undefined reference to `android::String16::String16(char const*)'
undefined reference to `android::String16::~String16()'
undefined reference to `android::String16::~String16()'
Is it required to build this as a part of AOSP? Perhaps through something like ndk-build? What I am building is more of a toy application that only needs access to those (and related, e.g. service->transact APIs) APIs along with Parcel.
Perhaps building AOSP once and using -L to include a search path to the generated libs.
libbinder and libutils are not part of the app API surface. https://developer.android.com/ndk/reference/group/ndk-binder is the NDK binder API.
This (dirty hack) is working fine for me:
#include <android/binder_ibinder.h>
typedef AIBinder* (*AServiceManager_getService_func)(const char* instance);
extern "C"
JNIEXPORT void JNICALL
Java_com_irsl_greedybinder_MainActivity_testService(JNIEnv *env, jclass clazz) {
void* binder_ndk = dlopen("/system/lib/libbinder_ndk.so", RTLD_LAZY);
if (binder_ndk == nullptr) {
ALOGI("Unable to load libbinder_ndk.so");
return;
}
AServiceManager_getService_func AServiceManager_getService;
AServiceManager_getService = (AServiceManager_getService_func) dlsym(binder_ndk, "AServiceManager_getService");
if(AServiceManager_getService == nullptr) {
ALOGI("Failed to look up AServiceManager_getService");
return;
}
ALOGI("AServiceManager_getService symbol found at: %p", AServiceManager_getService);
AIBinder* binder = AServiceManager_getService("activity");
if (binder == nullptr) {
ALOGI("Unable to obtain Activity Manager service");
return;
}
ALOGI("We got the binder to the Activity Manager!: %p", binder);
}
Disclaimer by Dan Albert applies: They exist for vendor and APEX users. Those domains do not carry the same guarantees that are needed for apps to use them reliably, so they are not exposed to apps.
I'm trying to build Tensorflow Lite for Android which has Eigen as dependencies.
And during build I get this error:
.../eigen/Eigen/src/Core/arch/NEON/Complex.h:383:83: error: 'vreinterpretq_u32_f64' was not declared in this scope
Packet2d eq_swapped = vreinterpretq_f64_u32(vrev64q_u32(vreinterpretq_u32_f64(eq)));
^
After some digging, I found out that:
vreinterpretq_u32_f64 is indeed not defined within Eigen and that
Eigen has only the standard library as dependency
So where exactly does this function supposed to come from? (I do have the standard library included explicitly android-ndk-r17c/sources/cxx-stl/llvm-libc++) am I missing some includes?
Anyone can help me shed some lights on this?
Thanks.
It seems that vreinterpretq_u32_f64 and vreinterpretq_f64_u32 is not defined.
If you look at Eigen/src/Core/arch/NEON/PacketMath.h line 604, vreinterpretq_f64_u64 and vreinterpretq_u64_f64 is defined.
Considering vector width as 128bits, vreinterpretq_u32_f64 should cast from f64x2 to u32x4, similarly for vreinterpretq_f64_u32
Just add this two definitions after line 604 in Eigen/src/Core/arch/NEON/PacketMath.h
template <typename T> float64x2_t vreinterpretq_f64_u32(T a) { return (float64x2) a; }
template <typename T> uint32x4_t vreinterpretq_u32_f64(T a) { return (uint32x4) a; }
Hope this helps!
I found that rand() function from bionic does't work without including stdlib.h
extern int rand(void);
static void foo()
{
int a = rand();
}
int main()
{
foo()
return 0;
}
Results for glibc:
Compilation successful
Results for bionic:
Compilation unsuccessful
error: undefined reference to 'rand'
In bionic sources we have following implementation:
static __inline__ int rand(void) {
return (int)lrand48();
}
Why it works for glibc but not for bionic
glibc's rand() is a "normal" function located in a library. I suspect you're getting a warning about the symbol not being defined from the compiler (which cannot find it), but since the function exists in a library, the link stage can still find and link to it.
bionic's rand() is a static inline in your header file, that means it's not even defined unless the header file is included. Since the compiler cannot find it without the include and it does not exist in any library that the linker can resolve it from, compilation will fail at the linking stage.
You will get the answer if you just compare bionic and glibc sources of rand function: https://github.com/android/platform_bionic/blob/master/libc/include/stdlib.h and
http://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/rand.c;hb=glibc-2.15#l26
You can see that in bionic library it inlined in header file so without .h file you can't use it.And in glibc it is separated like most of the functions. The reason is obvious I think - bionic library was developed specially for use in embedded and mobile devices with memory and speed limits, so less code and inline optimizations is useful.
I have a simple file stlTest2.cpp like this:
#include <jni.h>
#include <cmath>
bool isnan (void);
There is something more complicated in some code I am porting. My question is this. Why would this work when building using GCC outside of the NDK, but not with using the NDK? There error it gives is this:
jni/stlTest2.cpp:6: error: expected unqualified-id before 'sizeof'
jni/stlTest2.cpp:6: error: expected ')' before 'sizeof'
The immediate reason for this is that math.h (included via <cmath>) defines isnan as a macro. Why is the build outside of the ndk not including the #define from math.h, but this is? If I comment out the includes in the code, all is fine, but that is not acceptable as this problem repeats itself.... a lot.
The isnan macro was added in C99. In C++11 it was added as a function in the std namespace, overloaded for float and double and long double (so a typical <cmath> header, such as your non-NDK GCC is probably using, might have something like this:
#undef isnan
inline bool isnan(float ...) { ... }
inline bool isnan(double ...) { ... }
inline bool isnan(long double ...) { ... }
), but apparently the NDK hasn't gotten the memo, and is still providing the C99 macro as a convenience. (isnan was never a macro in C++, but before TR1 added std::tr1::isnan, there wasn't really a C++ alternative, so multiple C++ compilers provided the C99 macro.)
Do you need to be able to use the compiler-provided isnan or std::isnan? If not, then you can just change this:
#include <cmath>
to this:
#include <cmath>
#undef isnan
(and similarly for any other problematic macros, provided you don't need them).
In $ndk\sources\cxx-stl\gnu-libstdc++\libs\armeabi\include\bits\c++config.h (change armeabi to whatever is appropriate) change this:
/* #undef _GLIBCXX_USE_C99_MATH */
to
#define _GLIBCXX_USE_C99_MATH 1
Then clean and build your project again.
I have a core project which I'm building as a shared library. In one of the headers, I've defined a simple class shown below:
typedef pthread_mutex_t Mutex;
class CORE_API AutoLock
{
public:
AutoLock(Mutex& m);
~AutoLock();
private:
AutoLock();
AutoLock(const AutoLock&);
AutoLock& operator=(const AutoLock&);
Mutex m_Mutex;
};
where CORE_API is defined as:
#ifdef CORE_DLL
#define CORE_API __attribute__ ((dllexport))
#else
#define CORE_API __attribute__ ((dllimport))
#endif
In the Android.mk for core, I've defined CORE_DLL under LOCAL_CFLAGS. However, when building, I get the warning:
warning: 'dllimporot' attribute directive ignored
When ndk-build gets to the other project where I want to use the AutoLock class, I get the error:
error: 'AutoLock::AutoLock()' is private
error: within this context
Why would the compiler ignore the dllexport attribute? I would hope that once that's fixed, my other project should build and be able to use the AutoLock class without any problems.
Shared libraries are created differently on Android (Linux) than with Windows.
In Windows you have the special dllimport and dllexport directives but not on Android (Linux).
When using your shared library, you should just compile with -lYourLibraryName
This might help you: http://www.adp-gmbh.ch/cpp/gcc/create_lib.html
Have a look at the sample code available in the android-ndk, specially the Android.mk file this might solve your problem.