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

Commit aa488ac2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "aaudio: prevent noise upon disconnect" into oc-mr1-dev

parents c12dd9ac 2d5ba532
Loading
Loading
Loading
Loading
+56 −33
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ using namespace android;
using namespace aaudio;

AudioStreamLegacy::AudioStreamLegacy()
        : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
        : AudioStream()
        , mDeviceCallback(new StreamDeviceCallback(this)) {
}

AudioStreamLegacy::~AudioStreamLegacy() {
@@ -78,18 +79,20 @@ int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes
void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
    aaudio_data_callback_result_t callbackResult;

    if (!mCallbackEnabled.load()) {
        return;
    }

    switch (opcode) {
        case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
            if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
            checkForDisconnectRequest();

            // Note that this code assumes an AudioTrack::Buffer is the same as
            // AudioRecord::Buffer
            // TODO define our own AudioBuffer and pass it from the subclasses.
            AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
                if (audioBuffer->frameCount == 0) return;
            if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED || !mCallbackEnabled.load()) {
                audioBuffer->size = 0; // silence the buffer
            } else {
                if (audioBuffer->frameCount == 0) {
                    return;
                }

                // If the caller specified an exact size then use a block size adapter.
                if (mBlockAdapter != nullptr) {
@@ -107,17 +110,40 @@ void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode
                    audioBuffer->size = 0;
                }

                if (updateStateMachine() == AAUDIO_OK) {
                    break; // don't fall through
                if (updateStateMachine() != AAUDIO_OK) {
                    forceDisconnect();
                    mCallbackEnabled.store(false);
                }
            }
        }
        /// FALL THROUGH
            break;

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

        default:
            break;
    }
}



void AudioStreamLegacy::checkForDisconnectRequest() {
    if (mRequestDisconnect.isRequested()) {
        ALOGD("checkForDisconnectRequest() mRequestDisconnect acknowledged");
        forceDisconnect();
        mRequestDisconnect.acknowledge();
        mCallbackEnabled.store(false);
    }
}

void AudioStreamLegacy::forceDisconnect() {
    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
        if (getErrorCallbackProc() != nullptr) {
            (*getErrorCallbackProc())(
                    (AAudioStream *) this,
@@ -125,12 +151,6 @@ void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode
                    AAUDIO_ERROR_DISCONNECTED
            );
        }
            mCallbackEnabled.store(false);
        }
            break;

        default:
            break;
    }
}

@@ -175,15 +195,18 @@ void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
    ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
    if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
            getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
        // if we have a data callback and the stream is active, send the error callback from
        // data callback thread when it sees the DISCONNECTED state
        if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
            (*getErrorCallbackProc())(
                    (AAudioStream *) this,
                    getErrorCallbackUserData(),
                    AAUDIO_ERROR_DISCONNECTED
                    );
        // Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
        // If we have a data callback and the stream is active, then ask the data callback
        // to DISCONNECT and call the error callback.
        if (isDataCallbackActive()) {
            ALOGD("onAudioDeviceUpdate() request DISCONNECT in data callback due to device change");
            // If the stream is stopped before the data callback has a chance to handle the
            // request then the requestStop() and requestPause() methods will handle it after
            // the callback has stopped.
            mRequestDisconnect.request();
        } else {
            ALOGD("onAudioDeviceUpdate() DISCONNECT the stream now");
            forceDisconnect();
        }
    }
    setDeviceId(deviceId);
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include "AudioStream.h"
#include "AAudioLegacy.h"
#include "utility/AAudioUtilities.h"
#include "utility/FixedBlockAdapter.h"

namespace aaudio {
@@ -111,6 +112,10 @@ protected:

    void onAudioDeviceUpdate(audio_port_handle_t deviceId);

    void checkForDisconnectRequest();

    void forceDisconnect();

    void onStart() { mCallbackEnabled.store(true); }
    void onStop() { mCallbackEnabled.store(false); }

@@ -130,6 +135,8 @@ protected:
    aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
    int32_t                    mCallbackBufferSize = 0;
    const android::sp<StreamDeviceCallback>   mDeviceCallback;

    AtomicRequestor            mRequestDisconnect;
};

} /* namespace aaudio */
+1 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ aaudio_result_t AudioStreamRecord::requestStop() {
    mAudioRecord->stop();
    mFramesRead.reset32();
    mTimestampPosition.reset32();
    checkForDisconnectRequest();
    return AAUDIO_OK;
}

+2 −0
Original line number Diff line number Diff line
@@ -261,6 +261,7 @@ aaudio_result_t AudioStreamTrack::requestPause() {
    onStop();
    setState(AAUDIO_STREAM_STATE_PAUSING);
    mAudioTrack->pause();
    checkForDisconnectRequest();
    status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
    if (err != OK) {
        return AAudioConvert_androidToAAudioResult(err);
@@ -300,6 +301,7 @@ aaudio_result_t AudioStreamTrack::requestStop() {
    mFramesWritten.reset32();
    mTimestampPosition.reset32();
    mAudioTrack->stop();
    checkForDisconnectRequest();
    return AAUDIO_OK;
}

+5 −2
Original line number Diff line number Diff line
@@ -346,15 +346,18 @@ private:
 */
class AtomicRequestor {
public:

    __attribute__((no_sanitize("integer")))
    void request() {
        // TODO handle overflows, very unlikely
        mRequested++;
    }

    __attribute__((no_sanitize("integer")))
    bool isRequested() {
        return mRequested.load() > mAcknowledged.load();
        return (mRequested.load() - mAcknowledged.load()) > 0;
    }

    __attribute__((no_sanitize("integer")))
    void acknowledge() {
        mAcknowledged++;
    }