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

Commit f4158d85 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

AudioTrack: new transfer mode for Java offload support

New transfer mode for java AudioTrack using offload
  path, where data is provided through the write method,
  and the callback is used to notify the track owner
  more data can be written on the track.

Bug 86837964
Test: adb shell clof --source /sdcard/Music/my.mp3

Change-Id: I47c760b7fb8f1431945ca24ff4a26311b63cb761
parent 0917fc25
Loading
Loading
Loading
Loading
+34 −7
Original line number Diff line number Diff line
@@ -399,9 +399,10 @@ status_t AudioTrack::set(
        }
        break;
    case TRANSFER_CALLBACK:
    case TRANSFER_SYNC_NOTIF_CALLBACK:
        if (cbf == NULL || sharedBuffer != 0) {
            ALOGE("%s(): Transfer type TRANSFER_CALLBACK but cbf == NULL || sharedBuffer != 0",
                    __func__);
            ALOGE("%s(): Transfer type %s but cbf == NULL || sharedBuffer != 0",
                    convertTransferToText(transferType), __func__);
            status = BAD_VALUE;
            goto exit;
        }
@@ -1406,6 +1407,7 @@ const char * AudioTrack::convertTransferToText(transfer_type transferType) {
        MEDIA_CASE_ENUM(TRANSFER_OBTAIN);
        MEDIA_CASE_ENUM(TRANSFER_SYNC);
        MEDIA_CASE_ENUM(TRANSFER_SHARED);
        MEDIA_CASE_ENUM(TRANSFER_SYNC_NOTIF_CALLBACK);
        default:
            return "UNRECOGNIZED";
    }
@@ -1438,7 +1440,8 @@ status_t AudioTrack::createTrack_l()
            // use case 3: obtain/release mode
            (mTransfer == TRANSFER_OBTAIN) ||
            // use case 4: synchronous write
            ((mTransfer == TRANSFER_SYNC) && mThreadCanCallJava);
            ((mTransfer == TRANSFER_SYNC || mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK)
                    && mThreadCanCallJava);

        bool fastAllowed = sharedBuffer || transferAllowed;
        if (!fastAllowed) {
@@ -1795,7 +1798,7 @@ void AudioTrack::restartIfDisabled()

ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking)
{
    if (mTransfer != TRANSFER_SYNC) {
    if (mTransfer != TRANSFER_SYNC && mTransfer != TRANSFER_SYNC_NOTIF_CALLBACK) {
        return INVALID_OPERATION;
    }

@@ -1846,7 +1849,17 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking)

    if (written > 0) {
        mFramesWritten += written / mFrameSize;

        if (mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK) {
            const sp<AudioTrackThread> t = mAudioTrackThread;
            if (t != 0) {
                // causes wake up of the playback thread, that will callback the client for
                // more data (with EVENT_CAN_WRITE_MORE_DATA) in processAudioBuffer()
                t->wake();
            }
        }
    }

    return written;
}

@@ -2100,8 +2113,8 @@ nsecs_t AudioTrack::processAudioBuffer()
        if (ns < 0) ns = 0;
    }

    // If not supplying data by EVENT_MORE_DATA, then we're done
    if (mTransfer != TRANSFER_CALLBACK) {
    // If not supplying data by EVENT_MORE_DATA or EVENT_CAN_WRITE_MORE_DATA, then we're done
    if (mTransfer != TRANSFER_CALLBACK && mTransfer != TRANSFER_SYNC_NOTIF_CALLBACK) {
        return ns;
    }

@@ -2163,7 +2176,13 @@ nsecs_t AudioTrack::processAudioBuffer()
        }

        size_t reqSize = audioBuffer.size;
        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
        if (mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK) {
            // when notifying client it can write more data, pass the total size that can be
            // written in the next write() call, since it's not passed through the callback
            audioBuffer.size += nonContig;
        }
        mCbf(mTransfer == TRANSFER_CALLBACK ? EVENT_MORE_DATA : EVENT_CAN_WRITE_MORE_DATA,
                mUserData, &audioBuffer);
        size_t writtenSize = audioBuffer.size;

        // Sanity check on returned size
@@ -2174,6 +2193,14 @@ nsecs_t AudioTrack::processAudioBuffer()
        }

        if (writtenSize == 0) {
            if (mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK) {
                // The callback EVENT_CAN_WRITE_MORE_DATA was processed in the JNI of
                // android.media.AudioTrack. The JNI is not using the callback to provide data,
                // it only signals to the Java client that it can provide more data, which
                // this track is read to accept now.
                // The playback thread will be awaken at the next ::write()
                return NS_WHENEVER;
            }
            // The callback is done filling buffers
            // Keep this thread going to handle timed events and
            // still try to get more data in intervals of WAIT_PERIOD_MS
+5 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ public:
                                    // in the mapping from frame position to presentation time.
                                    // See AudioTimestamp for the information included with event.
#endif
        EVENT_CAN_WRITE_MORE_DATA = 9,// Notification that more data can be given by write()
                                    // This event only occurs for TRANSFER_SYNC_NOTIF_CALLBACK.
    };

    /* Client should declare a Buffer and pass the address to obtainBuffer()
@@ -153,6 +155,7 @@ public:
        TRANSFER_OBTAIN,    // call obtainBuffer() and releaseBuffer()
        TRANSFER_SYNC,      // synchronous write()
        TRANSFER_SHARED,    // shared memory
        TRANSFER_SYNC_NOTIF_CALLBACK, // synchronous write(), notif EVENT_CAN_WRITE_MORE_DATA
    };

    /* Constructs an uninitialized AudioTrack. No connection with
@@ -295,6 +298,8 @@ public:
     * Parameters not listed in the AudioTrack constructors above:
     *
     * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
     *      Only set to true when AudioTrack object is used for a java android.media.AudioTrack
     *      in its JNI code.
     *
     * Internal state post condition:
     *      (mStreamType == AUDIO_STREAM_DEFAULT) implies this AudioTrack has valid attributes