Home | History | Annotate | Download | only in android
      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 
     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 
     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 
     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 
     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 
     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 
     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 
     98 bool AudioManagerJni::HasDeviceObjects() {
     99   return g_jvm_ && g_jni_env_ && g_context_ && g_audio_manager_class_;
    100 }
    101 
    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 
    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