AndroidRuntime::getJNIEnv() and callback threads

804 views
Skip to first unread message

K

unread,
Dec 23, 2011, 4:02:46 PM12/23/11
to android-ndk
I know AndroidRuntime::getJNIEnv() isn't part of the NDK, but I'm
trying to understand the following code, so please help.

I've been reading code from frameworks/base/ to understand how
callbacks from native services are propagated up to Java. A typical
example is the media stack. For instance, frameworks/base/media/jni/
android_media_MediaRecorder.cpp has the following:

void JNIMediaRecorderListener::notify(int msg, int ext1, int ext2)
{
LOGV("JNIMediaRecorderListener::notify");

JNIEnv *env = AndroidRuntime::getJNIEnv();
env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg,
ext1, ext2, 0);
}


The notify() method is called in the context of a random binder thread
(from its thread pool), and the method is supposed to call up to Java.
To do that, it uses AndroidRuntime::getJNIEnv() to get the JNIEnv*
pointer. I tried something similar in some code I was writing, and I
ended up with a NULL env pointer. I could guess why, because my
function is called from a native binder thread which is not visible to
the VM; so unless I do an AttachCurrentThread(), I would end up with a
NULL if I try getJNIEnv(). But what surprises me is that, none of
Android's framework code seems to use AttachCurrentThread() in this
situation. Somehow magically, their callback threads are VM-visible,
and their AndroidRuntime::getJNIEnv() returns a valid env pointer.

Could someone please explain how this works? For a situation like
this:

A is a native daemon that listens for calls from other processes
(through binder); and A also sends callbacks to registered listeners.
B is a Java UI process, that has a JNI component; the JNI component
registers itself with A, and receives callback through binder.

B's callback function would not be java visible by default, since the
callback thread is being allocated from binder's threadpool. Without
doing AttachCurrentThread(), how would AndroidRuntime::getJNIEnv()
return a valid pointer? How is this working with many framework
services like the media recorder, media player etc. ?

bin shao

unread,
Dec 31, 2011, 1:30:15 AM12/31/11
to android-ndk
pls check below method in AndroidRuntime.cpp
---------------------------------------------------------------------
int AndroidRuntime::startReg(JNIEnv* env)

androidSetCreateThreadFunc((android_create_thread_fn)
javaCreateThreadEtc)
/*
* This hook causes all future threads created in this process to
be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
Reply all
Reply to author
Forward
0 new messages