1 #include "jni.h"
2 #include <assert.h>
3 #include "cubeb-jni-instances.h"
4 
5 #define AUDIO_STREAM_TYPE_MUSIC 3
6 
7 struct cubeb_jni {
8   jobject s_audio_manager_obj = nullptr;
9   jclass s_audio_manager_class = nullptr;
10   jmethodID s_get_output_latency_id = nullptr;
11 };
12 
13 extern "C"
14 cubeb_jni *
cubeb_jni_init()15 cubeb_jni_init()
16 {
17   jobject ctx_obj = cubeb_jni_get_context_instance();
18   JNIEnv * jni_env = cubeb_get_jni_env_for_thread();
19   if (!jni_env || !ctx_obj) {
20     return nullptr;
21   }
22 
23   cubeb_jni * cubeb_jni_ptr = new cubeb_jni;
24   assert(cubeb_jni_ptr);
25 
26   // Find the audio manager object and make it global to call it from another method
27   jclass context_class = jni_env->FindClass("android/content/Context");
28   jfieldID audio_service_field = jni_env->GetStaticFieldID(context_class, "AUDIO_SERVICE", "Ljava/lang/String;");
29   jstring jstr = (jstring)jni_env->GetStaticObjectField(context_class, audio_service_field);
30   jmethodID get_system_service_id = jni_env->GetMethodID(context_class, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
31   jobject audio_manager_obj = jni_env->CallObjectMethod(ctx_obj, get_system_service_id, jstr);
32   cubeb_jni_ptr->s_audio_manager_obj = reinterpret_cast<jobject>(jni_env->NewGlobalRef(audio_manager_obj));
33 
34   // Make the audio manager class a global reference in order to preserve method id
35   jclass audio_manager_class = jni_env->FindClass("android/media/AudioManager");
36   cubeb_jni_ptr->s_audio_manager_class = reinterpret_cast<jclass>(jni_env->NewGlobalRef(audio_manager_class));
37   cubeb_jni_ptr->s_get_output_latency_id = jni_env->GetMethodID (audio_manager_class, "getOutputLatency", "(I)I");
38 
39   jni_env->DeleteLocalRef(ctx_obj);
40   jni_env->DeleteLocalRef(context_class);
41   jni_env->DeleteLocalRef(jstr);
42   jni_env->DeleteLocalRef(audio_manager_obj);
43   jni_env->DeleteLocalRef(audio_manager_class);
44 
45   return cubeb_jni_ptr;
46 }
47 
48 extern "C"
cubeb_get_output_latency_from_jni(cubeb_jni * cubeb_jni_ptr)49 int cubeb_get_output_latency_from_jni(cubeb_jni * cubeb_jni_ptr)
50 {
51   assert(cubeb_jni_ptr);
52   JNIEnv * jni_env = cubeb_get_jni_env_for_thread();
53   return jni_env->CallIntMethod(cubeb_jni_ptr->s_audio_manager_obj, cubeb_jni_ptr->s_get_output_latency_id, AUDIO_STREAM_TYPE_MUSIC); //param: AudioManager.STREAM_MUSIC
54 }
55 
56 extern "C"
cubeb_jni_destroy(cubeb_jni * cubeb_jni_ptr)57 void cubeb_jni_destroy(cubeb_jni * cubeb_jni_ptr)
58 {
59   assert(cubeb_jni_ptr);
60 
61   JNIEnv * jni_env = cubeb_get_jni_env_for_thread();
62   assert(jni_env);
63 
64   jni_env->DeleteGlobalRef(cubeb_jni_ptr->s_audio_manager_obj);
65   jni_env->DeleteGlobalRef(cubeb_jni_ptr->s_audio_manager_class);
66 
67   delete cubeb_jni_ptr;
68 }
69