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

Commit cb1b6c8f authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

le_audio_software_aidl: Fix race condition on start request confirm

Uses atomic compare and exchange to avoid cases where the confirmed
stream request is not registered and overwritten. This happens when
the other thread confirms the request after we already checked the
state, but before it is set here.

Bug: 258127534
Test: Manual testing
Change-Id: I3528e97d6944949bf5031975b9f8e436db68aa3c
parent feba28e9
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include "le_audio_software_aidl.h"

#include <atomic>
#include <unordered_map>
#include <vector>

@@ -70,25 +71,33 @@ LeAudioTransport::LeAudioTransport(void (*flush)(void),
BluetoothAudioCtrlAck LeAudioTransport::StartRequest(bool is_low_latency) {
  SetStartRequestState(StartRequestState::PENDING_BEFORE_RESUME);
  if (stream_cb_.on_resume_(true)) {
    if (start_request_state_ == StartRequestState::CONFIRMED) {
    auto expected = StartRequestState::CONFIRMED;
    if (std::atomic_compare_exchange_strong(&start_request_state_, &expected,
                                            StartRequestState::IDLE)) {
      LOG_INFO("Start completed.");
      SetStartRequestState(StartRequestState::IDLE);
      return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
    }

    if (start_request_state_ == StartRequestState::CANCELED) {
    expected = StartRequestState::CANCELED;
    if (std::atomic_compare_exchange_strong(&start_request_state_, &expected,
                                            StartRequestState::IDLE)) {
      LOG_INFO("Start request failed.");
      SetStartRequestState(StartRequestState::IDLE);
      return BluetoothAudioCtrlAck::FAILURE;
    }

    expected = StartRequestState::PENDING_BEFORE_RESUME;
    if (std::atomic_compare_exchange_strong(
            &start_request_state_, &expected,
            StartRequestState::PENDING_AFTER_RESUME)) {
      LOG_INFO("Start pending.");
    SetStartRequestState(StartRequestState::PENDING_AFTER_RESUME);
      return BluetoothAudioCtrlAck::PENDING;
    }
  }

  LOG_ERROR("Start request failed.");
  SetStartRequestState(StartRequestState::IDLE);
  auto expected = StartRequestState::PENDING_BEFORE_RESUME;
  std::atomic_compare_exchange_strong(&start_request_state_, &expected,
                                      StartRequestState::IDLE);
  return BluetoothAudioCtrlAck::FAILURE;
}