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

Commit 7daa4f99 authored by Atneya Nair's avatar Atneya Nair
Browse files

Modify AAudio for new AudioTrack callback format

AAudio uses libaudioclient for its 'legacy' pathway.
We refactored libaudioclient callback registration to use an
interface. AudioStreamLegacy now implements the callback since
there will be shared behavior between Record and Track following
refactor.

Change-Id: If07ed3b349c223d7fd55a3e2e18e12a3d0f70865
parent 161f47e0
Loading
Loading
Loading
Loading
+56 −72
Original line number Original line Diff line number Diff line
@@ -37,15 +37,6 @@ AudioStreamLegacy::AudioStreamLegacy()
        : AudioStream() {
        : AudioStream() {
}
}


// Called from AudioTrack.cpp or AudioRecord.cpp
static void AudioStreamLegacy_callback(int event, void* userData, void *info) {
    AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
    streamLegacy->processCallback(event, info);
}

aaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
    return AudioStreamLegacy_callback;
}


aaudio_data_callback_result_t AudioStreamLegacy::callDataCallbackFrames(uint8_t *buffer,
aaudio_data_callback_result_t AudioStreamLegacy::callDataCallbackFrames(uint8_t *buffer,
                                                                        int32_t numFrames) {
                                                                        int32_t numFrames) {
@@ -73,51 +64,55 @@ int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes
    return (int32_t) callDataCallbackFrames(buffer, numFrames);
    return (int32_t) callDataCallbackFrames(buffer, numFrames);
}
}


void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {

    aaudio_data_callback_result_t callbackResult;
void AudioStreamLegacy::onNewIAudioTrack() {
    ALOGD("%s stream disconnected", __func__);
    forceDisconnect();
    mCallbackEnabled.store(false);
}

size_t AudioStreamLegacy::onMoreData(const android::AudioTrack::Buffer& buffer) {
    // This illegal size can be used to tell AudioRecord or AudioTrack to stop calling us.
    // This illegal size can be used to tell AudioRecord or AudioTrack to stop calling us.
    // This takes advantage of them killing the stream when they see a size out of range.
    // This takes advantage of them killing the stream when they see a size out of range.
    // That is an undocumented behavior.
    // That is an undocumented behavior.
    // TODO add to API in AudioRecord and AudioTrack
    // TODO add to API in AudioRecord and AudioTrack
    const size_t SIZE_STOP_CALLBACKS = SIZE_MAX;
    const size_t SIZE_STOP_CALLBACKS = SIZE_MAX;

    aaudio_data_callback_result_t callbackResult;
    switch (opcode) {
        case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
    (void) checkForDisconnectRequest(true);
    (void) checkForDisconnectRequest(true);


    // Note that this code assumes an AudioTrack::Buffer is the same as
    // Note that this code assumes an AudioTrack::Buffer is the same as
    // AudioRecord::Buffer
    // AudioRecord::Buffer
    // TODO define our own AudioBuffer and pass it from the subclasses.
    // TODO define our own AudioBuffer and pass it from the subclasses.
            AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
    size_t written = buffer.size;
    if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
    if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
                ALOGW("processCallbackCommon() data, stream disconnected");
        ALOGW("%s() data, stream disconnected", __func__);
        // This will kill the stream and prevent it from being restarted.
        // This will kill the stream and prevent it from being restarted.
        // That is OK because the stream is disconnected.
        // That is OK because the stream is disconnected.
                audioBuffer->size = SIZE_STOP_CALLBACKS;
        written = SIZE_STOP_CALLBACKS;
    } else if (!mCallbackEnabled.load()) {
    } else if (!mCallbackEnabled.load()) {
                ALOGW("processCallbackCommon() no data because callback disabled, set size=0");
        ALOGW("%s() no data because callback disabled, set size=0", __func__);
        // Do NOT use SIZE_STOP_CALLBACKS here because that will kill the stream and
        // Do NOT use SIZE_STOP_CALLBACKS here because that will kill the stream and
        // prevent it from being restarted. This can occur because of a race condition
        // prevent it from being restarted. This can occur because of a race condition
        // caused by Legacy callbacks running after the track is "stopped".
        // caused by Legacy callbacks running after the track is "stopped".
                audioBuffer->size = 0;
        written = 0;
    } else {
    } else {
                if (audioBuffer->frameCount == 0) {
        if (buffer.frameCount == 0) {
                    ALOGW("processCallbackCommon() data, frameCount is zero");
            ALOGW("%s() data, frameCount is zero", __func__);
                    return;
            return written;
        }
        }


        // If the caller specified an exact size then use a block size adapter.
        // If the caller specified an exact size then use a block size adapter.
        if (mBlockAdapter != nullptr) {
        if (mBlockAdapter != nullptr) {
                    int32_t byteCount = audioBuffer->frameCount * getBytesPerDeviceFrame();
            int32_t byteCount = buffer.frameCount * getBytesPerDeviceFrame();
            callbackResult = mBlockAdapter->processVariableBlock(
            callbackResult = mBlockAdapter->processVariableBlock(
                            (uint8_t *) audioBuffer->raw, byteCount);
                    static_cast<uint8_t*>(buffer.raw), byteCount);
        } else {
        } else {
            // Call using the AAudio callback interface.
            // Call using the AAudio callback interface.
                    callbackResult = callDataCallbackFrames((uint8_t *)audioBuffer->raw,
            callbackResult = callDataCallbackFrames(static_cast<uint8_t *>(buffer.raw),
                                                            audioBuffer->frameCount);
                                                    buffer.frameCount);
        }
        }
        if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
        if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
                    audioBuffer->size = audioBuffer->frameCount * getBytesPerDeviceFrame();
            written = buffer.frameCount * getBytesPerDeviceFrame();
        } else {
        } else {
            if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
            if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
                ALOGD("%s() callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
                ALOGD("%s() callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
@@ -125,7 +120,7 @@ void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode
                ALOGW("%s() callback returned invalid result = %d",
                ALOGW("%s() callback returned invalid result = %d",
                      __func__, callbackResult);
                      __func__, callbackResult);
            }
            }
                    audioBuffer->size = 0;
            written = 0;
            systemStopInternal();
            systemStopInternal();
            // Disable the callback just in case the system keeps trying to call us.
            // Disable the callback just in case the system keeps trying to call us.
            mCallbackEnabled.store(false);
            mCallbackEnabled.store(false);
@@ -136,20 +131,9 @@ void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode
            mCallbackEnabled.store(false);
            mCallbackEnabled.store(false);
        }
        }
    }
    }
    return written;
}
}
            break;

        // Stream got rerouted so we disconnect.
        case AAUDIO_CALLBACK_OPERATION_DISCONNECTED:
            ALOGD("processCallbackCommon() stream disconnected");
            forceDisconnect();
            mCallbackEnabled.store(false);
            break;


        default:
            break;
    }
}


aaudio_result_t AudioStreamLegacy::checkForDisconnectRequest(bool errorCallbackEnabled) {
aaudio_result_t AudioStreamLegacy::checkForDisconnectRequest(bool errorCallbackEnabled) {
    if (mRequestDisconnect.isRequested()) {
    if (mRequestDisconnect.isRequested()) {
+6 −10
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@
#define LEGACY_AUDIO_STREAM_LEGACY_H
#define LEGACY_AUDIO_STREAM_LEGACY_H


#include <media/AudioTimestamp.h>
#include <media/AudioTimestamp.h>
#include <media/AudioTrack.h>
#include <media/AudioSystem.h>
#include <media/AudioSystem.h>


#include <aaudio/AAudio.h>
#include <aaudio/AAudio.h>
@@ -30,8 +31,6 @@
namespace aaudio {
namespace aaudio {




typedef void (*aaudio_legacy_callback_t)(int event, void* user, void *info);

enum {
enum {
    /**
    /**
     * Request that the callback function should fill the data buffer of an output stream,
     * Request that the callback function should fill the data buffer of an output stream,
@@ -56,21 +55,17 @@ enum {
typedef int32_t aaudio_callback_operation_t;
typedef int32_t aaudio_callback_operation_t;




class AudioStreamLegacy : public AudioStream, public FixedBlockProcessor {
class AudioStreamLegacy : public AudioStream,
                          public FixedBlockProcessor,
                          protected android::AudioTrack::IAudioTrackCallback {
public:
public:
    AudioStreamLegacy();
    AudioStreamLegacy();


    virtual ~AudioStreamLegacy() = default;
    virtual ~AudioStreamLegacy() = default;


    aaudio_legacy_callback_t getLegacyCallback();


    int32_t callDataCallbackFrames(uint8_t *buffer, int32_t numFrames);
    int32_t callDataCallbackFrames(uint8_t *buffer, int32_t numFrames);


    // This is public so it can be called from the C callback function.
    // This is called from the AudioTrack/AudioRecord client.
    virtual void processCallback(int event, void *info) = 0;

    void processCallbackCommon(aaudio_callback_operation_t opcode, void *info);


    // Implement FixedBlockProcessor
    // Implement FixedBlockProcessor
    int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) override;
    int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) override;
@@ -86,7 +81,8 @@ public:
    }
    }


protected:
protected:

    size_t onMoreData(const android::AudioTrack::Buffer& buffer) override;
    void onNewIAudioTrack() override;
    aaudio_result_t getBestTimestamp(clockid_t clockId,
    aaudio_result_t getBestTimestamp(clockid_t clockId,
                                     int64_t *framePosition,
                                     int64_t *framePosition,
                                     int64_t *timeNanoseconds,
                                     int64_t *timeNanoseconds,
+10 −5
Original line number Original line Diff line number Diff line
@@ -37,6 +37,10 @@ using android::content::AttributionSourceState;
using namespace android;
using namespace android;
using namespace aaudio;
using namespace aaudio;


static void sCallbackWrapper(int event, void* userData, void* info) {
    static_cast<AudioStreamRecord*>(userData)->processCallback(event, info);
}

AudioStreamRecord::AudioStreamRecord()
AudioStreamRecord::AudioStreamRecord()
    : AudioStreamLegacy()
    : AudioStreamLegacy()
    , mFixedBlockWriter(*this)
    , mFixedBlockWriter(*this)
@@ -129,7 +133,7 @@ aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
    AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC;
    AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC;
    if (builder.getDataCallbackProc() != nullptr) {
    if (builder.getDataCallbackProc() != nullptr) {
        streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK;
        streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK;
        callback = getLegacyCallback();
        callback = sCallbackWrapper;
        callbackData = this;
        callbackData = this;
    }
    }
    mCallbackBufferSize = builder.getFramesPerDataCallback();
    mCallbackBufferSize = builder.getFramesPerDataCallback();
@@ -353,14 +357,15 @@ const void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, in
void AudioStreamRecord::processCallback(int event, void *info) {
void AudioStreamRecord::processCallback(int event, void *info) {
    switch (event) {
    switch (event) {
        case AudioRecord::EVENT_MORE_DATA:
        case AudioRecord::EVENT_MORE_DATA:
            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
        {
            AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
            audioBuffer->size = onMoreData(*audioBuffer);
            break;
            break;

        }
            // Stream got rerouted so we disconnect.
            // Stream got rerouted so we disconnect.
        case AudioRecord::EVENT_NEW_IAUDIORECORD:
        case AudioRecord::EVENT_NEW_IAUDIORECORD:
            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
            onNewIAudioTrack();
            break;
            break;

        default:
        default:
            break;
            break;
    }
    }
+3 −1
Original line number Original line Diff line number Diff line
@@ -65,7 +65,9 @@ public:
    }
    }


    // This is public so it can be called from the C callback function.
    // This is public so it can be called from the C callback function.
    void processCallback(int event, void *info) override;
    void processCallback(int event, void *info);

    void processCallbackRecord(aaudio_callback_operation_t opcode, void *info);


    int64_t incrementClientFrameCounter(int32_t frames) override {
    int64_t incrementClientFrameCounter(int32_t frames) override {
        return incrementFramesRead(frames);
        return incrementFramesRead(frames);
+13 −28
Original line number Original line Diff line number Diff line
@@ -103,14 +103,12 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
            : getFormat();
            : getFormat();


    // Setup the callback if there is one.
    // Setup the callback if there is one.
    AudioTrack::legacy_callback_t callback = nullptr;
    wp<AudioTrack::IAudioTrackCallback> callback;
    void *callbackData = nullptr;
    // Note that TRANSFER_SYNC does not allow FAST track
    // Note that TRANSFER_SYNC does not allow FAST track
    AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
    AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
    if (builder.getDataCallbackProc() != nullptr) {
    if (builder.getDataCallbackProc() != nullptr) {
        streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
        streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
        callback = getLegacyCallback();
        callback = wp<AudioTrack::IAudioTrackCallback>::fromExisting(this);
        callbackData = this;


        // If the total buffer size is unspecified then base the size on the burst size.
        // If the total buffer size is unspecified then base the size on the burst size.
        if (frameCount == 0
        if (frameCount == 0
@@ -157,7 +155,6 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
            frameCount,
            frameCount,
            flags,
            flags,
            callback,
            callback,
            callbackData,
            notificationFrames,
            notificationFrames,
            nullptr,       // DEFAULT sharedBuffer*/,
            nullptr,       // DEFAULT sharedBuffer*/,
            false,   // DEFAULT threadCanCallJava
            false,   // DEFAULT threadCanCallJava
@@ -293,15 +290,9 @@ void AudioStreamTrack::close_l() {
    AudioStream::close_l();
    AudioStream::close_l();
}
}


void AudioStreamTrack::processCallback(int event, void *info) {

    switch (event) {
        case AudioTrack::EVENT_MORE_DATA:
            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
            break;


void AudioStreamTrack::onNewIAudioTrack() {
    // Stream got rerouted so we disconnect.
    // Stream got rerouted so we disconnect.
        case AudioTrack::EVENT_NEW_IAUDIOTRACK:
    // request stream disconnect if the restored AudioTrack has properties not matching
    // request stream disconnect if the restored AudioTrack has properties not matching
    // what was requested initially
    // what was requested initially
    if (mAudioTrack->channelCount() != getSamplesPerFrame()
    if (mAudioTrack->channelCount() != getSamplesPerFrame()
@@ -310,14 +301,8 @@ void AudioStreamTrack::processCallback(int event, void *info) {
          || mAudioTrack->getRoutedDeviceId() != getDeviceId()
          || mAudioTrack->getRoutedDeviceId() != getDeviceId()
          || getBufferCapacityFromDevice() != getBufferCapacity()
          || getBufferCapacityFromDevice() != getBufferCapacity()
          || getFramesPerBurstFromDevice() != getFramesPerBurst()) {
          || getFramesPerBurstFromDevice() != getFramesPerBurst()) {
                processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
        AudioStreamLegacy::onNewIAudioTrack();
            }
            break;

        default:
            break;
    }
    }
    return;
}
}


aaudio_result_t AudioStreamTrack::requestStart_l() {
aaudio_result_t AudioStreamTrack::requestStart_l() {
Loading