1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/audio_device/android/audio_manager_jni.h"
12
13 #include <assert.h>
14
15 #include "webrtc/modules/utility/interface/helpers_android.h"
16 #include "webrtc/system_wrappers/interface/trace.h"
17
18 namespace webrtc {
19
20 static JavaVM* g_jvm_ = NULL;
21 static JNIEnv* g_jni_env_ = NULL;
22 static jobject g_context_ = NULL;
23 static jclass g_audio_manager_class_ = NULL;
24 static jobject g_audio_manager_ = NULL;
25
AudioManagerJni()26 AudioManagerJni::AudioManagerJni()
27 : low_latency_supported_(false),
28 native_output_sample_rate_(0),
29 native_buffer_size_(0) {
30 if (!HasDeviceObjects()) {
31 assert(false);
32 }
33 AttachThreadScoped ats(g_jvm_);
34 JNIEnv* env = ats.env();
35 assert(env && "Unsupported JNI version!");
36 CreateInstance(env);
37 // Pre-store device specific values.
38 SetLowLatencySupported(env);
39 SetNativeOutputSampleRate(env);
40 SetNativeFrameSize(env);
41 }
42
SetAndroidAudioDeviceObjects(void * jvm,void * env,void * context)43 void AudioManagerJni::SetAndroidAudioDeviceObjects(void* jvm, void* env,
44 void* context) {
45 assert(jvm);
46 assert(env);
47 assert(context);
48
49 // Store global Java VM variables to be accessed by API calls.
50 g_jvm_ = reinterpret_cast<JavaVM*>(jvm);
51 g_jni_env_ = reinterpret_cast<JNIEnv*>(env);
52 g_context_ = g_jni_env_->NewGlobalRef(reinterpret_cast<jobject>(context));
53
54 // FindClass must be made in this function since this function's contract
55 // requires it to be called by a Java thread.
56 // See
57 // http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
58 // as to why this is necessary.
59 // Get the AudioManagerAndroid class object.
60 jclass javaAmClassLocal = g_jni_env_->FindClass(
61 "org/webrtc/voiceengine/AudioManagerAndroid");
62 assert(javaAmClassLocal);
63
64 // Create a global reference such that the class object is not recycled by
65 // the garbage collector.
66 g_audio_manager_class_ = reinterpret_cast<jclass>(
67 g_jni_env_->NewGlobalRef(javaAmClassLocal));
68 assert(g_audio_manager_class_);
69 }
70
ClearAndroidAudioDeviceObjects()71 void AudioManagerJni::ClearAndroidAudioDeviceObjects() {
72 g_jni_env_->DeleteGlobalRef(g_audio_manager_class_);
73 g_audio_manager_class_ = NULL;
74 g_jni_env_->DeleteGlobalRef(g_context_);
75 g_context_ = NULL;
76 g_jni_env_->DeleteGlobalRef(g_audio_manager_);
77 g_audio_manager_ = NULL;
78 g_jni_env_ = NULL;
79 g_jvm_ = NULL;
80 }
81
SetLowLatencySupported(JNIEnv * env)82 void AudioManagerJni::SetLowLatencySupported(JNIEnv* env) {
83 jmethodID id = LookUpMethodId(env, "isAudioLowLatencySupported", "()Z");
84 low_latency_supported_ = env->CallBooleanMethod(g_audio_manager_, id);
85 }
86
SetNativeOutputSampleRate(JNIEnv * env)87 void AudioManagerJni::SetNativeOutputSampleRate(JNIEnv* env) {
88 jmethodID id = LookUpMethodId(env, "getNativeOutputSampleRate", "()I");
89 native_output_sample_rate_ = env->CallIntMethod(g_audio_manager_, id);
90 }
91
SetNativeFrameSize(JNIEnv * env)92 void AudioManagerJni::SetNativeFrameSize(JNIEnv* env) {
93 jmethodID id = LookUpMethodId(env,
94 "getAudioLowLatencyOutputFrameSize", "()I");
95 native_buffer_size_ = env->CallIntMethod(g_audio_manager_, id);
96 }
97
HasDeviceObjects()98 bool AudioManagerJni::HasDeviceObjects() {
99 return g_jvm_ && g_jni_env_ && g_context_ && g_audio_manager_class_;
100 }
101
LookUpMethodId(JNIEnv * env,const char * method_name,const char * method_signature)102 jmethodID AudioManagerJni::LookUpMethodId(JNIEnv* env,
103 const char* method_name,
104 const char* method_signature) {
105 jmethodID ret_val = env->GetMethodID(g_audio_manager_class_, method_name,
106 method_signature);
107 assert(ret_val);
108 return ret_val;
109 }
110
CreateInstance(JNIEnv * env)111 void AudioManagerJni::CreateInstance(JNIEnv* env) {
112 // Get the method ID for the constructor taking Context.
113 jmethodID id = LookUpMethodId(env, "<init>", "(Landroid/content/Context;)V");
114 g_audio_manager_ = env->NewObject(g_audio_manager_class_, id, g_context_);
115 // Create a global reference so that the instance is accessible until no
116 // longer needed.
117 g_audio_manager_ = env->NewGlobalRef(g_audio_manager_);
118 assert(g_audio_manager_);
119 }
120
121 } // namespace webrtc
122