Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6335c90 authored by Dave Sparks's avatar Dave Sparks
Browse files

Add locking around AudioRecord release() function in JNI. Bug 2481952.

There is a potential threading issue where an app could call release()
on two threads. This hack adds a static lock object that serializes
access to the Java fields that contain the pointer to the native
AudioRecord object and weak reference to the Java object. Also
modifies finalize() to call release() so that both use the locking
scheme.

Change-Id: I09dcb19b7f501dc582e40e8718142b493eba2518
parent f0f7eb06
Loading
Loading
Loading
Loading
+16 −14
Original line number Original line Diff line number Diff line
@@ -55,6 +55,8 @@ struct audiorecord_callback_cookie {
    jobject     audioRecord_ref;
    jobject     audioRecord_ref;
 };
 };


Mutex sLock;

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


#define AUDIORECORD_SUCCESS                         0
#define AUDIORECORD_SUCCESS                         0
@@ -255,12 +257,21 @@ android_media_AudioRecord_stop(JNIEnv *env, jobject thiz)




// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void android_media_AudioRecord_finalize(JNIEnv *env,  jobject thiz) {
static void android_media_AudioRecord_release(JNIEnv *env,  jobject thiz) {


    // delete the AudioRecord object
    // serialize access. Ugly, but functional.
    Mutex::Autolock lock(&sLock);
    AudioRecord *lpRecorder = 
    AudioRecord *lpRecorder = 
            (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
            (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
    audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetIntField(
        thiz, javaAudioRecordFields.nativeCallbackCookie);

    // reset the native resources in the Java object so any attempt to access
    // them after a call to release fails.
    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);


    // delete the AudioRecord object
    if (lpRecorder) {
    if (lpRecorder) {
        LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
        LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
        lpRecorder->stop();
        lpRecorder->stop();
@@ -268,27 +279,18 @@ static void android_media_AudioRecord_finalize(JNIEnv *env, jobject thiz) {
    }
    }
    
    
    // delete the callback information
    // delete the callback information
    audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetIntField(
        thiz, javaAudioRecordFields.nativeCallbackCookie);
    if (lpCookie) {
    if (lpCookie) {
        LOGV("deleting lpCookie: %x\n", (int)lpCookie);
        LOGV("deleting lpCookie: %x\n", (int)lpCookie);
        env->DeleteGlobalRef(lpCookie->audioRecord_class);
        env->DeleteGlobalRef(lpCookie->audioRecord_class);
        env->DeleteGlobalRef(lpCookie->audioRecord_ref);
        env->DeleteGlobalRef(lpCookie->audioRecord_ref);
        delete lpCookie;
        delete lpCookie;
    }
    }

}
}




// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void android_media_AudioRecord_release(JNIEnv *env,  jobject thiz) {
static void android_media_AudioRecord_finalize(JNIEnv *env,  jobject thiz) {
       
    android_media_AudioRecord_release(env, thiz);
    // do everything a call to finalize would
    android_media_AudioRecord_finalize(env, thiz);
    // + reset the native resources in the Java object so any attempt to access
    // them after a call to release fails.
    env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
    env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);
}
}