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

Commit 6ee09f04 authored by Andy Hung's avatar Andy Hung
Browse files

StreamOut: use atomic_sp<> for callback thread safety

Test: see bug
Test: basic audio works
Bug: 177278988
Change-Id: Id1f5036e36b2a3b3e71e0b0ec548d4c65a972b50
parent 2cac3d31
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,7 @@ cc_defaults {
        "libaudio_system_headers",
        "libaudio_system_headers",
        "libhardware_headers",
        "libhardware_headers",
        "libmedia_headers",
        "libmedia_headers",
        "libmediautils_headers",
    ],
    ],


    export_header_lib_headers: [
    export_header_lib_headers: [
+3 −3
Original line number Original line Diff line number Diff line
@@ -163,7 +163,7 @@ StreamOut::~StreamOut() {
        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
        ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
        ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
    }
    }
    mCallback.clear();
    mCallback = nullptr;
#if MAJOR_VERSION <= 5
#if MAJOR_VERSION <= 5
    mDevice->closeOutputStream(mStream);
    mDevice->closeOutputStream(mStream);
    // Closing the output stream in the HAL waits for the callback to finish,
    // Closing the output stream in the HAL waits for the callback to finish,
@@ -462,7 +462,7 @@ Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {


Return<Result> StreamOut::clearCallback() {
Return<Result> StreamOut::clearCallback() {
    if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
    if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
    mCallback.clear();
    mCallback = nullptr;
    return Result::OK;
    return Result::OK;
}
}


@@ -477,7 +477,7 @@ int StreamOut::asyncCallback(stream_callback_event_t event, void*, void* cookie)
    // It's correct to hold an sp<> to callback because the reference
    // It's correct to hold an sp<> to callback because the reference
    // in the StreamOut instance can be cleared in the meantime. There is
    // in the StreamOut instance can be cleared in the meantime. There is
    // no difference on which thread to run IStreamOutCallback's destructor.
    // no difference on which thread to run IStreamOutCallback's destructor.
    sp<IStreamOutCallback> callback = self->mCallback;
    sp<IStreamOutCallback> callback = self->mCallback.load();
    if (callback.get() == nullptr) return 0;
    if (callback.get() == nullptr) return 0;
    ALOGV("asyncCallback() event %d", event);
    ALOGV("asyncCallback() event %d", event);
    Return<void> result;
    Return<void> result;
+2 −1
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@
#include <fmq/MessageQueue.h>
#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <hidl/Status.h>
#include <mediautils/Synchronization.h>
#include <utils/Thread.h>
#include <utils/Thread.h>


namespace android {
namespace android {
@@ -158,7 +159,7 @@ struct StreamOut : public IStreamOut {
    audio_stream_out_t* mStream;
    audio_stream_out_t* mStream;
    const sp<Stream> mStreamCommon;
    const sp<Stream> mStreamCommon;
    const sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
    const sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
    sp<IStreamOutCallback> mCallback;  // Callback for non-blocking write and drain
    mediautils::atomic_sp<IStreamOutCallback> mCallback;  // for non-blocking write and drain
#if MAJOR_VERSION >= 6
#if MAJOR_VERSION >= 6
    sp<IStreamOutEventCallback> mEventCallback;
    sp<IStreamOutEventCallback> mEventCallback;
#endif
#endif