Fix crash in java code

The bug fix is to take global reference of context.

TBR=henrikg
BUG=issue 826
TEST=local test
Review URL: https://webrtc-codereview.appspot.com/798008

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2789 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
leozwang@webrtc.org 2012-09-19 16:39:07 +00:00
parent d0b31b2e03
commit aaf6ba57e0
7 changed files with 549 additions and 541 deletions

View File

@ -29,7 +29,7 @@ namespace webrtc
JavaVM* AudioDeviceAndroidJni::globalJvm = NULL;
JNIEnv* AudioDeviceAndroidJni::globalJNIEnv = NULL;
jobject AudioDeviceAndroidJni::globalSndContext = NULL;
jobject AudioDeviceAndroidJni::globalContext = NULL;
jclass AudioDeviceAndroidJni::globalScClass = NULL;
// ----------------------------------------------------------------------------
@ -46,7 +46,6 @@ WebRtc_Word32 AudioDeviceAndroidJni::SetAndroidAudioDeviceObjects(
void* context) {
// TODO(leozwang): Make this function thread-safe.
globalJvm = reinterpret_cast<JavaVM*>(javaVM);
globalSndContext = reinterpret_cast<jobject>(context);
if (env) {
globalJNIEnv = reinterpret_cast<JNIEnv*>(env);
@ -54,16 +53,26 @@ WebRtc_Word32 AudioDeviceAndroidJni::SetAndroidAudioDeviceObjects(
jclass javaScClassLocal = globalJNIEnv->FindClass(
"org/webrtc/voiceengine/AudioDeviceAndroid");
if (!javaScClassLocal) {
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
"%s: could not find java class", __FUNCTION__);
return -1; // exception thrown
}
else {
}
// Create a global reference to the class (to tell JNI that we are
// referencing it after this function has returned).
globalScClass = reinterpret_cast<jclass> (
globalJNIEnv->NewGlobalRef(javaScClassLocal));
if (!globalScClass) {
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
"%s: could not create reference", __FUNCTION__);
return -1;
}
globalContext = globalJNIEnv->NewGlobalRef(
reinterpret_cast<jobject>(context));
if (!globalContext) {
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
"%s: could not create context reference", __FUNCTION__);
return -1;
}
@ -71,12 +80,17 @@ WebRtc_Word32 AudioDeviceAndroidJni::SetAndroidAudioDeviceObjects(
globalJNIEnv->DeleteLocalRef(javaScClassLocal);
}
else { // User is resetting the env variable
WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, -1,
"%s: env is NULL, assuming deinit", __FUNCTION__);
if (!globalJNIEnv) {
WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, -1,
"%s: saved env already NULL", __FUNCTION__);
return 0;
}
globalJNIEnv->DeleteGlobalRef(globalScClass);
globalJNIEnv = (JNIEnv *) NULL;
globalJNIEnv = reinterpret_cast<JNIEnv*>(NULL);
}
return 0;
@ -406,6 +420,9 @@ WebRtc_Word32 AudioDeviceAndroidJni::Terminate()
_javaDirectPlayBuffer = NULL;
_javaDirectRecBuffer = NULL;
env->DeleteGlobalRef(_javaContext);
_javaContext = NULL;
// Delete the references to the java buffers, this allows the
// garbage collector to delete them
env->DeleteGlobalRef(_javaPlayBuffer);
@ -2144,7 +2161,7 @@ WebRtc_Word32 AudioDeviceAndroidJni::InitJavaResources()
{
// todo: Check if we already have created the java object
_javaVM = globalJvm;
_javaContext = globalSndContext;
_javaContext = globalContext;
_javaScClass = globalScClass;
// use the jvm that has been set
@ -2199,7 +2216,7 @@ WebRtc_Word32 AudioDeviceAndroidJni::InitJavaResources()
return -1;
}
// create a reference to the object (to tell JNI that we are referencing it
// Create a reference to the object (to tell JNI that we are referencing it
// after this function has returned).
_javaScObj = env->NewGlobalRef(javaScObjLocal);
if (!_javaScObj)
@ -2215,29 +2232,25 @@ WebRtc_Word32 AudioDeviceAndroidJni::InitJavaResources()
//////////////////////
// AUDIO MANAGEMENT
// This is not mandatory functionality.
// This is not mandatory functionality
if (_javaContext) {
// Get Context field ID
jfieldID fidContext = env->GetFieldID(_javaScClass, "_context",
jfieldID context_id = env->GetFieldID(globalScClass,
"_context",
"Landroid/content/Context;");
if (!fidContext) {
if (!context_id) {
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
"%s: could not get Context fid", __FUNCTION__);
"%s: could not get _context id", __FUNCTION__);
return -1;
}
// Set the Java application Context so we can use AudioManager
// Get Context object and check it.
jobject javaContext = (jobject) _javaContext;
env->SetObjectField(_javaScObj, fidContext, javaContext);
javaContext = env->GetObjectField(_javaScObj, fidContext);
env->SetObjectField(_javaScObj, context_id, globalContext);
jobject javaContext = env->GetObjectField(_javaScObj, context_id);
if (!javaContext) {
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
"%s: could not set Context", __FUNCTION__);
"%s: could not set or get _context", __FUNCTION__);
return -1;
}
// Delete local object ref.
env->DeleteLocalRef(javaContext);
}
else {
WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,

View File

@ -24,8 +24,8 @@ namespace webrtc
{
class EventWrapper;
const WebRtc_UWord32 N_REC_SAMPLES_PER_SEC = 44000; // Default is 44.1 kHz
const WebRtc_UWord32 N_PLAY_SAMPLES_PER_SEC = 44000; // Default is 44.1 kHz
const WebRtc_UWord32 N_REC_SAMPLES_PER_SEC = 16000; // Default is 16 kHz
const WebRtc_UWord32 N_PLAY_SAMPLES_PER_SEC = 16000; // Default is 16 kHz
const WebRtc_UWord32 N_REC_CHANNELS = 1; // default is mono recording
const WebRtc_UWord32 N_PLAY_CHANNELS = 1; // default is mono playout
@ -264,7 +264,7 @@ class AudioDeviceAndroidJni : public AudioDeviceGeneric {
// reliable. Chromium has a good example at base/android.
static JavaVM* globalJvm;
static JNIEnv* globalJNIEnv;
static jobject globalSndContext;
static jobject globalContext;
static jclass globalScClass;
};

View File

@ -238,10 +238,10 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_StopInco
/*
* Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI
* Method: VoE_Create
* Signature: ()Z
* Signature: (Landroid/content/Context)Z
*/
JNIEXPORT jboolean JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Create
(JNIEnv *, jobject);
(JNIEnv *, jobject, jobject);
/*
* Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI

View File

@ -225,7 +225,7 @@ public:
};
// JNI_OnLoad
jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) {
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
webrtcGlobalVM = vm;
if (!webrtcGlobalVM)
{
@ -1099,15 +1099,15 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_StopInco
/*
* Class: org_webrtc_videoengineapp_ViEAndroidJavaAPI
* Method: VoE_Create
* Signature: ()Z
* Signature: (Landroid/content/Context)Z
*/
JNIEXPORT jboolean JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Create(
JNIEnv *env,
jobject context)
{
jobject context,
jobject ctx) {
__android_log_write(ANDROID_LOG_DEBUG, WEBRTC_LOG_TAG, "Create VoiceEngine");
VoiceEngine::SetAndroidObjects(webrtcGlobalVM, env, context);
VoiceEngine::SetAndroidObjects(webrtcGlobalVM, env, ctx);
// Check if already created
if (voeData.ve) {

View File

@ -86,7 +86,7 @@ public class ViEAndroidJavaAPI {
// Voice Engine API
// Create and Delete functions
public native boolean VoE_Create();
public native boolean VoE_Create(Context context);
public native boolean VoE_Delete();
// Initialization and Termination functions

View File

@ -671,7 +671,7 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback,
private int SetupVoE() {
// Create VoiceEngine
// Error logging is done in native API wrapper
ViEAndroidAPI.VoE_Create();
ViEAndroidAPI.VoE_Create(getApplicationContext());
// Initialize
if (0 != ViEAndroidAPI.VoE_Init(enableTrace)) {