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

Commit 27e12e72 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "fix AudioTrack and AudioRecord JNI"

parents b94d4128 3d4c6419
Loading
Loading
Loading
Loading
+39 −6
Original line number Diff line number Diff line
@@ -393,13 +393,46 @@ static jint android_media_AudioRecord_readInShortArray(JNIEnv *env, jobject thi
                                                        jshortArray javaAudioData,
                                                        jint offsetInShorts, jint sizeInShorts) {

    jint read = android_media_AudioRecord_readInByteArray(env, thiz,
                                                        (jbyteArray) javaAudioData,
                                                        offsetInShorts*2, sizeInShorts*2);
    if (read > 0) {
        read /= 2;
    jshort* recordBuff = NULL;
    // get the audio recorder from which we'll read new audio samples
    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
    if (lpRecorder == NULL) {
        ALOGE("Unable to retrieve AudioRecord object, can't record");
        return 0;
    }
    return read;

    if (!javaAudioData) {
        ALOGE("Invalid Java array to store recorded audio, can't record");
        return 0;
    }

    // get the pointer to where we'll record the audio
    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
    // a way that it becomes much more efficient. When doing so, we will have to prevent the
    // AudioSystem callback to be called while in critical section (in case of media server
    // process crash for instance)
    recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);

    if (recordBuff == NULL) {
        ALOGE("Error retrieving destination for recorded audio data, can't record");
        return 0;
    }

    // read the new audio data from the native AudioRecord object
    const size_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize();
    const size_t sizeInBytes = sizeInShorts * sizeof(short);
    ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts * sizeof(short),
                                        sizeInBytes > recorderBuffSize ?
                                            recorderBuffSize : sizeInBytes);

    env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0);

    if (readSize < 0) {
        readSize = AUDIORECORD_ERROR_INVALID_OPERATION;
    } else {
        readSize /= sizeof(short);
    }
    return (jint) readSize;
}

// ----------------------------------------------------------------------------
+35 −6
Original line number Diff line number Diff line
@@ -637,14 +637,43 @@ static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz,
                                                  jshortArray javaAudioData,
                                                  jint offsetInShorts, jint sizeInShorts,
                                                  jint javaAudioFormat) {
    jint written = android_media_AudioTrack_write_byte(env, thiz,
                                                 (jbyteArray) javaAudioData,
                                                 offsetInShorts*2, sizeInShorts*2,
                                                 javaAudioFormat,
                                                 JNI_TRUE /*blocking write, legacy behavior*/);

    //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called",
    //    offsetInShorts, sizeInShorts);
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
    if (lpTrack == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for write()");
        return 0;
    }

    // get the pointer for the audio data from the java array
    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
    // a way that it becomes much more efficient. When doing so, we will have to prevent the
    // AudioSystem callback to be called while in critical section (in case of media server
    // process crash for instance)
    jshort* cAudioData = NULL;
    if (javaAudioData) {
        cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
        if (cAudioData == NULL) {
            ALOGE("Error retrieving source of audio data to play, can't play");
            return 0; // out of memory or no data to load
        }
    } else {
        ALOGE("NULL java array of audio data to play, can't play");
        return 0;
    }
    jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
                                offsetInShorts * sizeof(short), sizeInShorts * sizeof(short),
            true /*blocking write, legacy behavior*/);
    env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);

    if (written > 0) {
        written /= 2;
        written /= sizeof(short);
    }
    //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d",
    //     (int)written, (int)(sizeInShorts), (int)offsetInShorts);

    return written;
}