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

Commit ac6927f0 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk
Browse files

audio: Introduce read PCM from FMQ session functionality

This is required for audio input direction HAL session support.

Bug:
Tag: #feature
Test: vts-tradefed run vts -m VtsHalBluetoothAudioV2_1TargetTest
Sponsor: jpawlowski@
Change-Id: I3cd25f4af0c5c16074b17dd128de95dd53978379
parent 64f7fc8d
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -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<long>(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<std::recursive_mutex> lock(mutex_);
    if (!IsSessionReady()) break;
    size_t availableToRead = mDataMQ->availableToRead();
    if (availableToRead) {
      if (availableToRead > (bytes - totalRead)) {
        availableToRead = bytes - totalRead;
      }
      if (!mDataMQ->read(static_cast<uint8_t*>(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>
    BluetoothAudioSessionInstance::instance_ptr =
        std::unique_ptr<BluetoothAudioSessionInstance>(
+2 −0
Original line number Diff line number Diff line
@@ -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,
+11 −0
Original line number Diff line number Diff line
@@ -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<BluetoothAudioSession_2_1> session_ptr =
        BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->InReadPcmData(buffer, bytes);
    }
    return 0;
  }
};

}  // namespace audio