diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp index 50119bf399..2f3ddaf213 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp +++ b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp @@ -43,7 +43,10 @@ AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration = AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {}; static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending +static constexpr int kFmqReceiveTimeoutMs = + 1000; // 1000 ms timeout for receiving static constexpr int kWritePollMs = 1; // polled non-blocking interval +static constexpr int kReadPollMs = 1; // polled non-blocking interval static inline timespec timespec_convert_from_hal(const TimeSpec& TS) { return {.tv_sec = static_cast(TS.tvSec), @@ -402,6 +405,39 @@ size_t BluetoothAudioSession::OutWritePcmData(const void* buffer, return totalWritten; } +// The control function reads stream from FMQ +size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) { + if (buffer == nullptr || !bytes) return 0; + size_t totalRead = 0; + int ms_timeout = kFmqReceiveTimeoutMs; + do { + std::unique_lock lock(mutex_); + if (!IsSessionReady()) break; + size_t availableToRead = mDataMQ->availableToRead(); + if (availableToRead) { + if (availableToRead > (bytes - totalRead)) { + availableToRead = bytes - totalRead; + } + if (!mDataMQ->read(static_cast(buffer) + totalRead, + availableToRead)) { + ALOGE("FMQ datapath reading %zu/%zu failed", totalRead, bytes); + return totalRead; + } + totalRead += availableToRead; + } else if (ms_timeout >= kReadPollMs) { + lock.unlock(); + usleep(kReadPollMs * 1000); + ms_timeout -= kReadPollMs; + continue; + } else { + ALOGD("in data %zu/%zu overflow %d ms", totalRead, bytes, + (kFmqReceiveTimeoutMs - ms_timeout)); + return totalRead; + } + } while (totalRead < bytes); + return totalRead; +} + std::unique_ptr BluetoothAudioSessionInstance::instance_ptr = std::unique_ptr( diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.h b/bluetooth/audio/utils/session/BluetoothAudioSession.h index 838d1ccad0..8d02387d83 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession.h +++ b/bluetooth/audio/utils/session/BluetoothAudioSession.h @@ -153,6 +153,8 @@ class BluetoothAudioSession { // The control function writes stream to FMQ size_t OutWritePcmData(const void* buffer, size_t bytes); + // The control function read stream from FMQ + size_t InReadPcmData(void* buffer, size_t bytes); static constexpr PcmParameters kInvalidPcmParameters = { .sampleRate = SampleRate::RATE_UNKNOWN, diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h index 86af4680a5..168de488d7 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h +++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h @@ -141,6 +141,17 @@ class BluetoothAudioSessionControl_2_1 { } return 0; } + + // The control API reads stream from FMQ + static size_t InReadPcmData(const SessionType_2_1& session_type, void* buffer, + size_t bytes) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->InReadPcmData(buffer, bytes); + } + return 0; + } }; } // namespace audio