Reputation: 731
I'm trying to understand the interaction between the java and jni, so I decided to trace one of the java API, public int write (byte[] audioData, int offsetInBytes, int sizeInBytes)
(https://android.googlesource.com/platform/frameworks/base/+/android-6.0.1_r1/media/java/android/media/AudioTrack.java#1699).
If someone would point out if my thought process is correct or not.
The method
public int write (byte[] audioData, int offsetInBytes, int sizeInBytes)
contains
return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING);
so it can be traced back to
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes, @WriteMode int writeMode)
Inside that function, it has
int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat, writeMode == WRITE_BLOCKING);
which calls the native method
private native final int native_write_byte(byte[] audioData,i nt offsetInBytes, int sizeInBytes, int format, boolean isBlocking);
After I grep through all of the AOSP, I found that the only place that contains native_write_byte
is in static JNINativeMethod gMethods[]
`"native_write_byte", "([BIIIZ)I",
(void*)android_media_AudioTrack_writeArray<jbyteArray>`
(`https://android.googlesource.com/platform/frameworks/base/+/android-
6.0.1_r1/core/jni/android_media_AudioTrack.cpp#1065`)
(`https://android.googlesource.com/platform/frameworks/base/+/android-
6.0.1_r1/core/jni/android_media_AudioTrack.cpp#592`)
Now I want to find in which shared objects contains the native function, so I downloaded all of the files in /system/bin and grep through them, and only found one which is libandroid_runtime.so
.
After opening the shared object in Ida pro, I found it by searching for the unique string.
So I'm thinking that when developers use the write function, they import libandroid_runtime.so and use write function which contains native_write_byte
function which is a native function that calls to static jint android_media_AudioTrack_writeArray
.
Is this the right way to trace back to the C++?
Upvotes: 0
Views: 362
Reputation: 57163
You did most of the work correctly.
I don't know why you stopped at android-6.0.1_r1, the same CPP file is available in master. This native method is implemented as a template specialization of a C++ function:
template <typename T>
static jint android_media_AudioTrack_writeArray(JNIEnv *env, jobject thiz,
T javaAudioData,
jint offsetInSamples, jint sizeInSamples,
jint javaAudioFormat,
jboolean isWriteBlocking) {
You can study how this function works. Note that here, as typical for Android platform code, the JNI calls are wrapped with nativehelper headers.
to find in which shared objects contains the native function, you can look up the corresponding Android.bp script.
cc_library_shared {
name: "libandroid_runtime",
...
srcs: [
...
"android_media_AudioTrack.cpp",
grep through /system/bin is not necessary, and could actually be misleading, especially if the library were built with obfuscation turned on.
So I'm thinking that when developers use the write function, they import libandroid_runtime.so and use write function which contains
native_write_byte
function which is a native function that calls tostatic jint android_media_AudioTrack_writeArray
.
Basically correct. In Java, we usually invoke System.loadLibrary(name)
to import libname dynamic library, and we would say «native_write_byte
is implemented with static jint android_media_AudioTrack_writeArray<jbytearray>()
» rather than speak about a call from native_write_byte
.
Android runtime is a bit different. It is started on system load and reused by all apps. This start invokes, among others, register_android_media_AudioTrack(JNIEnv *), and that registers all native methods listed in the gMethods table which belongs to android_media_AudioTrack.cpp.
Upvotes: 1