Overall Module Stack
This article is about the design of callback between Java and native modules. There is no doubt that JNI is the key man. The sample design is referenced from Multimedia framework.
Below figure is the event path from native modules to java. Let’s see the detailed process.
Init Media JNI
First step is to initialize media JNI. In android_media_MediaPlayer_native_init, JNI gets postEventFromNavtive defined in MediaPlayer (java) and assigns it to post_event of fields_t structure. JNI module will use post_event to dispatch media events to Java layer MediaPlayer in JNIMediaPlayerListener::notify.
Create JNI MediaPlayer Listener
Since MediaPlayer (java) requires to receive media events from native module, it is kind of a listener. Android registers MediaPlayer (java) as events listener in JNI during native_setup. A wrapper class JNIMediaPlayerListener was designed to wrap the weak reference of MediaPlayer (java) object. Actually, JNIMediaPlayerListener is the instance registered in native MedaiPlayer (cpp). Native media events are sent to MediaPlayer (java) via JNIMediaPlayerListener. Let’s take a look of it as below UML and code snippet. The member variables of mClass and mObject are assigned as MediaPlayer (java) class and WeakReference of MediaPlayer (java) respectively.
Below is the code snippet of native_setup implementation.
Notification flow of native media events
Finally, we can trace how a event was sent from MediaPlayer (cpp) to MediaPlayer (Java).