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

Commit fba97d88 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

libaudiohal@aidl: Resolve async callbacks concurrency

While the I/O thread is receiving a reply from sending of
a 'burst' or 'drain' command, the HAL can already invoke
an asynchronous notification. This makes possible to read
the current stream state from the last reply in the notification
handler before it was updated by 'sendCommand' on the I/O thread.

The asynchronous handler needs to "wait" before 'sendCommand'
finished. This is achieved by taking the lock which protects
access to command and reply queues, as 'sendCommand' only
releases when the command handling is done and the last reply
was updated.

Bug: 363958142
Test: atest CtsMediaAudioTestCases
Change-Id: I4d4d94ffc7f093b6716d291a8f705376f079965b
parent 92949994
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -528,7 +528,14 @@ status_t StreamHalAidl::exit() {
}

void StreamHalAidl::onAsyncTransferReady() {
    if (auto state = getState(); state == StreamDescriptor::State::TRANSFERRING) {
    StreamDescriptor::State state;
    {
        // Use 'mCommandReplyLock' to ensure that 'sendCommand' has finished updating the state
        // after the reply from the 'burst' command.
        std::lock_guard l(mCommandReplyLock);
        state = getState();
    }
    if (state == StreamDescriptor::State::TRANSFERRING) {
        // Retrieve the current state together with position counters unconditionally
        // to ensure that the state on our side gets updated.
        sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
@@ -539,7 +546,14 @@ void StreamHalAidl::onAsyncTransferReady() {
}

void StreamHalAidl::onAsyncDrainReady() {
    if (auto state = getState(); state == StreamDescriptor::State::DRAINING) {
    StreamDescriptor::State state;
    {
        // Use 'mCommandReplyLock' to ensure that 'sendCommand' has finished updating the state
        // after the reply from the 'drain' command.
        std::lock_guard l(mCommandReplyLock);
        state = getState();
    }
    if (state == StreamDescriptor::State::DRAINING) {
        // Retrieve the current state together with position counters unconditionally
        // to ensure that the state on our side gets updated.
        sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr,