I am using JNI with Android Studio 1.5.1 targeting Android API 18 and my questions are:
Q.1) How can I call Dalvik internal functions from native code?
For example in the Android source code, in the interpreter module, in the stack.cpp, how can I call the function dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) from native code?
It seems that I need to include some files and link to some libraries as stated in this answer but I need specific details. Which files do I need to link to and which files do I need to include in my native code to successfully call the dvmDumpThreadStack function for example?
This is the content of the Andorid.md file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyLibrary
LOCAL_SRC_FILES := MyLibrary.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
Q.2) How to define the required arguments with the required values to call Dalvik internal functions? For example, before I call the dvmDumpThreadStack function, how to define target and thread and which values to store in them before I call the function.
Generally speaking, you don't. They're called "internal" functions for a reason.
If you're really determined to do this, you can find the function pointers by using dlsym() to find the address at runtime. You'll need the "mangled" name, which you can get by examining the binary with nm. (This was easier before the code was switched from C to C++ back in 4.1 or thereabouts.) You can get the Thread* the same way the VM does it, by calling one of the dvmGetThread functions in Thread.cpp (dvmGetThreadByHandle, dvmGetThreadByThreadId, dvmGetThreadFromThreadObject), or by calling dvmThreadSelf() if you're interested in the current thread. Pass that to dvmDumpThread(), which will set up the DebugOutputTarget so you don't have to.
You don't need a header file that defines Thread* to pass a Thread* around. Just declare the thread-getter functions as returning void*, and the thread-dump function as accepting a void* argument. If you're worried about type-safety and portability, don't call internal VM functions from an app.
The one time I actually wanted to do this -- debugging something, don't remember what -- I actually added a new extern "C" function to the VM that took no arguments and just dumped the current thread's stack. That made everything much easier.
Related
After more than two days of building errors, I give up...
I followed this good tutorial here: http://www.cryptopp.com/wiki/Android_(Command_Line) .
It compiles, and the "cryptest.exe" passes all tests. So, I guess that the static library "libcryptopp.a" is OK.
So, I move the "libcryptopp.a" and all the headers files in the Android project.
But when it comes to the building step (as often... :-) ), there are compilation errors, like:
.../Classes/libs/android/libcryptopp.a(files.o): in function std::basic_filebuf<char, std::char_traits<char> >::_M_unshift()
[clone .part.40]:/Users/toto/Developer/NDKs/AndroidNDKs/android-ndk-r8e/sources/cxx-stl/stlport/stlport/stl/_fstream.h:322:
error: undefined reference to 'std::_Filebuf_base::_M_write(char*, int)'
and ~50 others ...
"undefined reference to" errors usually mean that a library is not present, but "libcryptopp.a" is correct here. So I expect that something is missing in the "Android.mk":
include $(CLEAR_VARS)
LOCAL_MODULE := cryptopp-prebuilt
LOCAL_SRC_FILES := ...narf/Classes/libs/android/libcryptopp.
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
/*
here are included other library
*/
LOCAL_STATIC_LIBRARIES := cryptopp-prebuilt
include $(BUILD_SHARED_LIBRARY)
After tries with "APP_STL := stlport_static/dynamic", "APP_STL := gnustl_static/dynamic", etc... no more chances.
Being really not a building/compilation expert (even worse on Android), can somebody help me.
Thank you very much!
Ok. It is working now!
So the linking of "libcryptopp.a" is not working on my Android project with "stlport" but only with "gnustl_static". Perhaps because of others include like "cocosd2-x".
So following the tuto "http://www.cryptopp.com/wiki/Android_(Command_Line)" you must change the script "setenv-android.sh" to have a result like this:
ANDROID_STL_INC: /Users/toto/Developer/NDKs/AndroidNDKs/android-ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.6/include/
ANDROID_STL_LIB: /Users/toto/Developer/NDKs/AndroidNDKs/android-ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/libgnustl_static.a
and also move the files (just for the compilation)
/Users/toto/Developer/NDKs/AndroidNDKs/android-ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include/bits
in
/Users/toto/Developer/NDKs/AndroidNDKs/android-ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.6/include/bits
otherwise there are compilation problems...
Ouf!
I think there are a couple problems with your answer.
First, when multiple libraries use the standard runtimes, you must use the shared object version and not the static version. That's covered in ANDROID_NDK_ROOT/docs/CPLUSPLUS-SUPPORT.html.
Second, you probably have a problem with library load order. Static linking makes it go away because references to std::_Filebuf_base::_M_write(char*, int) (and friends) are resolved at compile time, and not link/load time. To fix this, you must load libstlport_shared.so (or libgnustl_shared.so) first, and then load libcryptopp.so second.
If you load libcryptopp.so first, then there is no runtime loaded into the process to resolve std::_Filebuf_base::_M_write(char*, int) (and friends). That's covered under the wiki page with the LD_PRELOAD tricks.
To fix it in Android Java, you would perform the following. See Is -rpath working? for details.
static {
System.loadLibrary("stlport_shared");
System.loadLibrary("cryptopp");
}
The Crypto+++ Andrid wiki page has been updated: http://www.cryptopp.com/wiki/Android_(ommand_Line)#Android_Activity.
I have went through a myriad of resources (including, but not limited to, OpenCV4Android's Google group, StackOverflow and OpenCV's answers page trying to resolve this, reaching a point where suggestions become redundant. The problem may be more or less similar to a previous (yet to be resolved) question of mine, but a different situation and thus perhaps a different source of error.
I have added an Android Activity to a package containing a successfully-running app (OpenCV's tutorial 3 sample demonstrating ndk use). The activity uses OpenCV's java API, but there is a call to System.loadLibrary("nativefile"); where nativefile represents a native library. The block where the loadLibrary is called is mentioned below; it is in the onManagerConnected() method. At the loadLibrary line, Logcat emits:
02-17 19:27:39.239: E/AndroidRuntime(10872): FATAL EXCEPTION: main
02-17 19:27:39.239: E/AndroidRuntime(10872): java.lang.UnsatisfiedLinkError: Library nativefile not found
02-17 19:27:39.239: E/AndroidRuntime(10872): at java.lang.Runtime.loadLibrary(Runtime.java:461)
02-17 19:27:39.239: E/AndroidRuntime(10872): at java.lang.System.loadLibrary(System.java:557)
Such error indeed did occur multiple times in other questions; and I have tried the suggestions I came across. However, there is a noteworthy observation to this problem; the app that successfully runs (the OpenCV sample) calls the same library through System.loadLibrary("nativefile");.
The code is rather long and thus not helpful to place in the question. However below summarises what I presume are key elements regarding the problem, it also summarises some of the previous answers related to the matter.
The .cpp file called has the correct method name, where I verify that it includes the package name and the class name, as well as the method name, in a pattern similar to: Java_packageNameSeperatedWithUnderScores_callingClassName_methodName. Morever; the code is surrounded within an extern "C" block, as with other OpenCV sample cpp files for native development.
The Android manifest is updated to learn that it launches the activity in question.
Below is the Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include ../../sdk/native/jni/OpenCV.mk
LOCAL_MODULE := nativefile
LOCAL_SRC_FILES := nativefile.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
Below is the Application.mk file
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all
I have tried replacing all in the APP_ABI line with armeabi and also again tried with armeabi-v7a, no different results however.
I've also verified, as suggested in a comment here, that the apk (after being extracted) contains the needed .so file in lib folder under the various architecture type folders.
Below is the BaseLoaderCallBack instantiation block, not much unlike that in the OpenCV sample, however I do not call the OpenCV camera, since the app performs image processing on images read from the SD card.
BaseLoaderCallback loader = new BaseLoaderCallback(this){
public void onManagerConnected(int status){
switch(status){
case LoaderCallbackInterface.SUCCESS:{
System.loadLibrary("nativefile"); break; }
default:{
super.onManagerConnected(status); break; }
} } };
Unlike OpenCV's sample however, in the Activity in question the line loader.onManagerConnected(LoaderCallbackInterface.SUCCESS); is added to the onCreate() method, since the method onManagerConnected didn't seem to be called otherwise.
Before every OpenCV block of statements, the condition if (OpenCVLoader.initDebug()) is checked. I've also tried the recommended OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, loader) conditional check, but still no different results.
Also, the ndk-build runs successfully building the .so files for the native library nativefile.
Given that the other activity, within the same package, load the library and utilises it finely (of course after amending the manifest file and cpp method name accordingly), I presume the project properties are correct (such as adding OpenCV library, and necessary environment paths, etc).
I reviewed the OpenCV sample multiple times and followed the same practice with slight variances, as detailed above.
Any ideas what could be the source of the problem?
Thank you for your time.
A question from https://stackoverflow.com/a/11467040/1442443
my final target is to dump user space stack.
I try to build a cpp file as below to a executable on android platform. Therefore, by calling tryToGetStack(), I can get call stack of my executable in run time.
#include <utils/CallStack.h>
namespace android
{
extern "C" void tryToGetStack()
{
CallStack stack;
stack.update();
stack.dump("");
}
}
and add lib setting to to Android.mak since CallStack.tpp is in libutils
LOCAL_SHARED_LIBRARIES += libutils
but I always get error with message:
error: undefined reference to 'android::CallStack::CallStack()'
error: undefined reference to 'android::CallStack::update(int, int)'
...
It seems the executable resolve the symbols at link time rather than load the .so file in runtime?
Do I missing something or there is some limit in Android build system?
I know it is a simple question, but I really need help...
update1
I try to add the code to another executable. The result is same... Does anyone knows the rule of android build system?
update2
There are some key words in my console "target StaticExecutable: ...", I think is is the answer.
http://en.wikipedia.org/wiki/Static_executable
my final target is to dump user space stack.
after google so many information from internet, I found there are 4 ways:
ptraceļ¼ http://en.wikipedia.org/wiki/Ptrace
It is really hard to use ptrace, and we need to stop the thread before using ptrace to attach
_unwind_backtrace: the way used by CallStack (CallStack class in CallStack.cpp)
example: http://git.stlinux.com/?p=stm/uclibc.git;a=blob;f=libubacktrace/sysdeps/sh/backtrace.c;h=18b91b1bb3fa26344a521927c631553a410fcf56;hb=d6a3d9ece5922a337800a8e2ed4db7e226f9ccb3
It is work with a drawback: if you use it as the thread is processing signal, it would dump signal stack rather than dump thread stack
The same problen: How to get fullstacktrace using _Unwind_Backtrace on SIGSEGV
backtrace: http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
a GNU extension function, not be implemented in Bionic libc used by Android
reference: https://stackoverflow.com/a/8295238/1442443
reference: http://lists.puredata.info/pipermail/pd-list/2012-02/094258.html
a patch to dump user space thread stack: http://www.gossamer-threads.com/lists/linux/kernel/1525096
but only be implemented in X86 architecture... orz
I try to port it to android, no it only shows the first frame of stack since arm does not use frame pointer.
So... 2 is the answer.
However, I wonder if someone can resolve the problem : How to get fullstacktrace using _Unwind_Backtrace on SIGSEGV
update:
if you can use cross compiler to use glic to compile your code, maybe you can use 3. backtrace !
http://communities.mentor.com/community/cs/archives/arm-gnu/msg02514.html
update2
a good article
http://codingrelic.geekhold.com/2009/05/pre-mortem-backtracing.html
Since this is such an important question here is my answer that worked for me. My code is in C so it has to call a C++ function that can access android::CallStack.
stackdump.cpp:
#include < utils/CallStack.h >
extern "C" void dumpCallStack( char *label)
{
android::CallStack cs;
cs.update();
cs.dump(label);
}
my main code (foo.c):
void dumpCallStack(char *label);
...
dumpCallStack(\__FUNCTION__);
I have had the same problem once. And it is hard to interpret.
The syntax is of course correct and reasonable!
I have tried many methods but it did not work.
Finally, I got an idea that, the lib reference "LOCAL_SHARED_LIBRARIES += libutils" should be put into a makefile generating a dynamic library rather than into a makefile generating a static library. This is the final reason.
Reference:
http://yongbingchen.github.io/blog/2013/05/09/dump-stack-in-android-native-c-code/
I also received this error, but I added:
LOCAL_STATIC_LIBRARIES += libutils
before line of LOCAL_MODULE := xxx in vm/Android.m of three targets and added
LOCAL_SHARED_LIBRARIES += libcorkscrew
in vm/Android.mk
and libdex/Android.mk, and same for the dexlist/Android.mk, dexdump/Android.mk
After all these done, it works for me.
i'm developing a computer vision application for Android.
That work involves getting camera frames as fast as possible, so I'm trying to build a android application directly in c++ using "android_native_app_glue" and "libnative_camera" to get camera frames.
It seems to be incompatible.
I tested out 2 options.
I tried to use OpenCV on the android NDK sample "NativeActivity", just make the few necessary changes (convert sample to c++, modify android.mk y application.mk and including using namespaces and includes) It gives the following error:
sharedLibrary : libnative-activity.so
C:/Development/android-opencv-wsp/samples/native-activity/obj/local/armeabi-v7a/objs/native-activity/main.o: In function ~Mat':
C:\Development\android-opencv-wsp\samples\native-activity/../../OpenCV-2.3.1/share/OpenCV/../../include/opencv2/core/mat.hpp:297: undefined reference tocv::fastFree(void*)'
and so on
I tried to import the necessary libraries to make a native activity on the OpenCV2.3.1 tutorial 3 sample. I simply modified the Android.mk and added:
LOCAL_STATIC_LIBRARIES := android_native_app_glue
Immediately, when I add this line, I get the following error:
SharedLibrary : libnative_sample.so
C:/Development/android-opencv-wsp/samples/tutorial-3-native/obj/local/armeabi-v7a/objs/native_sample/jni_part.o: In function ~Mat':
C:\Development\android-opencv-wsp\samples\tutorial-3-native/../../OpenCV-2.3.1/share/OpenCV/../../include/opencv2/core/mat.hpp:297: undefined reference tocv::fastFree(void*)'
and so on...
Please, has anyone tested a purely native activity with openCV2.3.1 and libnative_camera to get camera frames?
Thanks in advance.
I solved the problem there. It was my fault (as usual xD) the problem was I was writting in my Android.mk this line: LOCAL_STATIC_LIBRARIES := android_native_app_glue, instead of this line: LOCAL_STATIC_LIBRARIES += android_native_app_glue. I needed the "plus" symbol, in order to add the new library and not deleting the previously loaded. Thanks anyway!!
#Adi Shavit - thx
Change LOCAL_STATIC_LIBRARIES := android_native_app_glue to LOCAL_STATIC_LIBRARIES += android_native_app_glue. Note the plus sign. This will add the new library without deleting the previously loaded one. Source: Edanna in the comments
Maybe you should take a look at the V4L interface? You might want to check out this thread: http://comments.gmane.org/gmane.comp.handhelds.android.ndk/2824
If I recall you can read directly from a camera's dev file in OpenCV.
-James
I want to add my own framework code that runs in the Android "system_server" (handles all the system level services). My service loads a JNI library that talks to a driver I have added to the kernel. The service is designed to allow an app to register a listener with it to get updates from the driver. I found a pretty good blog post (http://www.androidenea.com/2009/12/adding-system-server-to-android.html) that explains how to add a system service, but I cannot get it completely working.
First of all, the post mentions that an "appropriate" Android.mk file should be used to write the client/test application, but does not give an example of this. When I try to build it, I get build errors saying it can't find the service I have added. Could someone give an example of what this might look like?
Also, I'd like to implement this in the vendor directory (or device directory in froyo) rather than in the Android open source code. The blog post mentions that the proper place for this is the vendor directory, but does not give an example of what this should look like. Anyone know?
ANY additional information on implementing your own system service in Android would be helpful. Again my specific workflow is:
Android App -> System Service -> JNI (native) library -> Device Driver
Texas instruments has provided a nice example:
http://processors.wiki.ti.com/index.php/Android-Adding_SystemService
Additionally, the CyanogenMod SystemServer.java has also code for dynamically loading system services as defined in the array "config_vendorServices" in config.xml (see core/res/res/values/config.xml), which I believe can be overwritten in the vendor or device directories using the overlays. This is a CyanogenMod-specific addition, added in this commit:
https://github.com/CyanogenMod/android_frameworks_base/commit/88fff90131f54d45dc496c45127ac1d16ad257df
There are multiply way (or 6 ways, just to be explicit) of adding a system service.
What you tried (Android App -> System Service -> JNI (native) library -> Device Driver) is one of them. You might want check out this article for an in-depth explanation regarding system service implementation patterns.
Follow the below steps for writing your own System Service in android framework.
Write your Own Service/Manager with API's exposed by inheriting the stub.
Create an aidl file for your service to expose & include in build.
Add your service in System Server, you service will start along with all core services.
Register your service context in context impl file.
Use your service in application by calling getSystemService(Context of your service)
PS; if your service get some fatal exception, device will soft reboot, as your service is running under system service.
Here is an example of an Android.mk used to compile a JNItest.c located at system/extras/JNITest. The Android.mk is also inside system/extras/JNITest directory.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= JNITest1.c
LOCAL_MODULE:= JNITest
#LOCAL_FORCE_STATIC_EXECUTABLE := true
#LOCAL_STATIC_LIBRARIES := libc
LOCAL_SHARED_LIBRARIES := libc
#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := eng
include $(BUILD_EXECUTABLE)