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

Commit 5b48727d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I21c970ba,I8fcf2b2c,If28ca02e

* changes:
  leaudio: Fix handling sonifications when conversation is used
  leaudio: Fix possible crash on receiving ISO data
  leaudio: Extend dumpsys
parents 30f15e23 8aa7dbd0
Loading
Loading
Loading
Loading
+143 −40
Original line number Diff line number Diff line
@@ -75,6 +75,31 @@ using le_audio::client_parser::ascs::kCtpResponseCodeSuccess;
using le_audio::client_parser::ascs::kCtpResponseInvalidAseCisMapping;
using le_audio::client_parser::ascs::kCtpResponseNoReason;

/* Enums */
enum class AudioState {
  IDLE = 0x00,
  READY_TO_START,
  STARTED,
};

std::ostream& operator<<(std::ostream& os, const AudioState& audio_state) {
  switch (audio_state) {
    case AudioState::IDLE:
      os << "IDLE";
      break;
    case AudioState::READY_TO_START:
      os << "READY_TO_START";
      break;
    case AudioState::STARTED:
      os << "STARTED";
      break;
    default:
      os << "UNKNOWN";
      break;
  }
  return os;
}

namespace {
void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);

@@ -131,8 +156,8 @@ class LeAudioClientImpl : public LeAudioClient {
        active_group_id_(bluetooth::groups::kGroupUnknown),
        stream_request_started_(false),
        current_context_type_(LeAudioContextType::MEDIA),
        audio_sink_ready_to_receive(false),
        audio_source_ready_to_send(false),
        audio_receiver_state_(AudioState::IDLE),
        audio_sender_state_(AudioState::IDLE),
        current_source_codec_config({0, 0, 0, 0}),
        current_sink_codec_config({0, 0, 0, 0}),
        lc3_encoder_left_mem(nullptr),
@@ -289,14 +314,14 @@ class LeAudioClientImpl : public LeAudioClient {
  }

  void CancelStreamingRequest() {
    if (audio_source_ready_to_send) {
    if (audio_sender_state_ >= AudioState::READY_TO_START) {
      LeAudioClientAudioSource::CancelStreamingRequest();
      audio_source_ready_to_send = false;
      audio_sender_state_ = AudioState::IDLE;
    }

    if (audio_sink_ready_to_receive) {
    if (audio_receiver_state_ >= AudioState::READY_TO_START) {
      LeAudioClientAudioSink::CancelStreamingRequest();
      audio_sink_ready_to_receive = false;
      audio_receiver_state_ = AudioState::IDLE;
    }
  }

@@ -557,8 +582,8 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    audio_source_ready_to_send = false;
    audio_sink_ready_to_receive = false;
    audio_sender_state_ = AudioState::IDLE;
    audio_receiver_state_ = AudioState::IDLE;

    groupStateMachine_->SuspendStream(group);
  }
@@ -2005,8 +2030,8 @@ class LeAudioClientImpl : public LeAudioClient {
  }

  void OnAudioDataReady(const std::vector<uint8_t>& data) {
    if (active_group_id_ == bluetooth::groups::kGroupUnknown ||
        !audio_source_ready_to_send)
    if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
        (audio_sender_state_ != AudioState::STARTED))
      return;

    LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
@@ -2127,6 +2152,7 @@ class LeAudioClientImpl : public LeAudioClient {

    LeAudioClientAudioSource::UpdateRemoteDelay(remote_delay_ms);
    LeAudioClientAudioSource::ConfirmStreamingRequest();
    audio_sender_state_ = AudioState::STARTED;

    return true;
  }
@@ -2196,11 +2222,12 @@ class LeAudioClientImpl : public LeAudioClient {

    LeAudioClientAudioSink::UpdateRemoteDelay(remote_delay_ms);
    LeAudioClientAudioSink::ConfirmStreamingRequest();
    audio_receiver_state_ = AudioState::STARTED;
  }

  void SuspendAudio(void) {
    audio_sink_ready_to_receive = false;
    audio_source_ready_to_send = false;
    audio_receiver_state_ = AudioState::IDLE;
    audio_sender_state_ = AudioState::IDLE;

    if (lc3_encoder_left_mem) {
      free(lc3_encoder_left_mem);
@@ -2227,8 +2254,37 @@ class LeAudioClientImpl : public LeAudioClient {
    ClientAudioIntefraceRelease();
  }

  void printCurrentStreamConfiguration(int fd) {
    std::stringstream stream;
    auto conf = &current_source_codec_config;

    stream << " Speaker codec config "
           << "\n";
    if (conf) {
      stream << "   audio sender state: " << audio_sender_state_ << "\n"
             << "   num_channels " << +conf->num_channels << "\n"
             << "   sample rate " << +conf->sample_rate << "\n"
             << "   bits pers sample " << +conf->bits_per_sample << "\n"
             << "   data_interval_us " << +conf->data_interval_us << "\n";
    }
    stream << " Microphone codec config"
           << "\n";
    conf = &current_sink_codec_config;
    if (conf) {
      stream << "   audio receiver state: " << audio_receiver_state_ << "\n"
             << "   num_channels " << +conf->num_channels << "\n"
             << "   sample rate " << +conf->sample_rate << "\n"
             << "   bits pers sample " << +conf->bits_per_sample << "\n"
             << "   data_interval_us " << +conf->data_interval_us << "\n";
    }
    dprintf(fd, "%s", stream.str().c_str());
  }

  void Dump(int fd) {
    dprintf(fd, "  Active group: %d\n", active_group_id_);
    dprintf(fd, "    current content type: 0x%08hx\n", current_context_type_);
    printCurrentStreamConfiguration(fd);
    dprintf(fd, "  ----------------\n ");
    dprintf(fd, "  LE Audio Groups:\n");
    aseGroups_.Dump(fd);
    dprintf(fd, "  Not grouped devices:\n");
@@ -2377,18 +2433,25 @@ class LeAudioClientImpl : public LeAudioClient {
  void OnAudioSinkSuspend() {
    LOG(INFO) << __func__;

    if (!audio_source_ready_to_send) return;
    /* Note: This callback is from audio hal driver.
     * Bluetooth peer is a Sink for Audio Framework.
     * e.g. Peer is a speaker
     */
    if (audio_sender_state_ == AudioState::IDLE) return;

    audio_source_ready_to_send = false;
    audio_sender_state_ = AudioState::IDLE;

    /* Last suspends group - triggers group stop */
    if (!audio_sink_ready_to_receive && !audio_source_ready_to_send)
      OnAudioSuspend();
    if (audio_receiver_state_ == AudioState::IDLE) OnAudioSuspend();
  }

  void OnAudioSinkResume() {
    LOG(INFO) << __func__;

    /* Note: This callback is from audio hal driver.
     * Bluetooth peer is a Sink for Audio Framework.
     * e.g. Peer is a speaker
     */
    auto group = aseGroups_.FindById(active_group_id_);
    if (!group) {
      LOG(ERROR) << __func__
@@ -2406,16 +2469,18 @@ class LeAudioClientImpl : public LeAudioClient {
    }

    /* First resume request from sink/source triggers group start */
    if (!audio_sink_ready_to_receive && !audio_source_ready_to_send) {
      audio_source_ready_to_send = true;
    if (audio_receiver_state_ == AudioState::IDLE &&
        audio_sender_state_ == AudioState::IDLE) {
      DLOG(INFO) << __func__ << " audio_sender_state_ READY_TO_START";
      audio_sender_state_ = AudioState::READY_TO_START;
      OnAudioResume();

      return;
    }

    if (audio_sink_ready_to_receive) {
      LOG(INFO) << __func__ << " audio_sink_ready_to_receive";
      audio_source_ready_to_send = true;
    if (audio_receiver_state_ >= AudioState::READY_TO_START) {
      LOG(INFO) << __func__ << " audio_receiver_state_ is READY_TO_START";
      audio_sender_state_ = AudioState::READY_TO_START;
      /* If signalling part is completed trigger start reveivin audio here,
       * otherwise it'll be called on group streaming state callback
       */
@@ -2424,10 +2489,8 @@ class LeAudioClientImpl : public LeAudioClient {
    } else {
      /* Ask framework to come back later */
      DLOG(INFO) << __func__ << " active_group_id: " << active_group_id_ << "\n"
                 << " audio_sink_ready_to_receive: "
                 << audio_sink_ready_to_receive << "\n"
                 << " audio_source_ready_to_send:" << audio_source_ready_to_send
                 << "\n"
                 << " audio_receiver_state: " << audio_receiver_state_ << "\n"
                 << " audio_sender_state: " << audio_sender_state_ << "\n"
                 << " current_context_type_: "
                 << static_cast<int>(current_context_type_) << "\n"
                 << " group exist? " << (group ? " yes " : " no ") << "\n";
@@ -2438,18 +2501,25 @@ class LeAudioClientImpl : public LeAudioClient {
  void OnAudioSourceSuspend() {
    LOG(INFO) << __func__;

    if (!audio_sink_ready_to_receive) return;
    /* Note: This callback is from audio hal driver.
     * Bluetooth peer is a Source for Audio Framework.
     * e.g. Peer is microphone.
     */
    if (audio_receiver_state_ == AudioState::IDLE) return;

    audio_sink_ready_to_receive = false;
    audio_receiver_state_ = AudioState::IDLE;

    /* Last suspends group - triggers group stop */
    if (!audio_sink_ready_to_receive && !audio_source_ready_to_send)
      OnAudioSuspend();
    if (audio_sender_state_ == AudioState::IDLE) OnAudioSuspend();
  }

  void OnAudioSourceResume() {
    LOG(INFO) << __func__;

    /* Note: This callback is from audio hal driver.
     * Bluetooth peer is a Source for Audio Framework.
     * e.g. Peer is microphone.
     */
    auto group = aseGroups_.FindById(active_group_id_);
    if (!group) {
      LOG(ERROR) << __func__
@@ -2467,15 +2537,16 @@ class LeAudioClientImpl : public LeAudioClient {
    }

    /* First resume request from sink/source triggers group start */
    if (!audio_sink_ready_to_receive && !audio_source_ready_to_send) {
    if ((audio_receiver_state_ == AudioState::IDLE) &&
        (audio_sender_state_ == AudioState::IDLE)) {
      OnAudioResume();
      audio_sink_ready_to_receive = true;
      audio_receiver_state_ = AudioState::READY_TO_START;

      return;
    }

    if (audio_source_ready_to_send) {
      audio_sink_ready_to_receive = true;
    if (audio_sender_state_ >= AudioState::READY_TO_START) {
      audio_receiver_state_ = AudioState::READY_TO_START;
      /* If signalling part is completed trigger start reveivin audio here,
       * otherwise it'll be called on group streaming state callback
       */
@@ -2485,7 +2556,32 @@ class LeAudioClientImpl : public LeAudioClient {
  }

  LeAudioContextType AudioContentToLeAudioContext(
      LeAudioContextType current_context_type,
      audio_content_type_t content_type, audio_usage_t usage) {
    /* Let's stay on the Conversational context type in case it is already
     * configured to conversational.
     */
    if (current_context_type == LeAudioContextType::CONVERSATIONAL) {
      switch (content_type) {
        case AUDIO_CONTENT_TYPE_SONIFICATION:
        case AUDIO_CONTENT_TYPE_SPEECH:
          return LeAudioContextType::CONVERSATIONAL;
        default:
          break;
      }

      switch (usage) {
        case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
        case AUDIO_USAGE_NOTIFICATION:
        case AUDIO_USAGE_ALARM:
        case AUDIO_USAGE_EMERGENCY:
        case AUDIO_USAGE_VOICE_COMMUNICATION:
          return LeAudioContextType::CONVERSATIONAL;
        default:
          break;
      }
    }

    switch (content_type) {
      case AUDIO_CONTENT_TYPE_SPEECH:
        return LeAudioContextType::CONVERSATIONAL;
@@ -2551,8 +2647,8 @@ class LeAudioClientImpl : public LeAudioClient {
                 << ", content_type=" << tracks->content_type
                 << ", gain=" << tracks->gain;

      auto new_context =
          AudioContentToLeAudioContext(tracks->content_type, tracks->usage);
      auto new_context = AudioContentToLeAudioContext(
          current_context_type_, tracks->content_type, tracks->usage);
      contexts.push_back(new_context);

      --track_count;
@@ -2654,7 +2750,10 @@ class LeAudioClientImpl : public LeAudioClient {
        auto* event =
            static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(data);

        if (!audio_sink_ready_to_receive) break;
        if (audio_receiver_state_ != AudioState::STARTED) {
          LOG(ERROR) << __func__ << " receiver state not ready ";
          break;
          }

        SendAudioData(event->p_msg->data + event->p_msg->offset,
                      event->p_msg->len - event->p_msg->offset);
@@ -2753,8 +2852,10 @@ class LeAudioClientImpl : public LeAudioClient {
    switch (status) {
      case GroupStreamStatus::STREAMING:
        stream_request_started_ = false;
        if (audio_source_ready_to_send) StartSendingAudio(active_group_id_);
        if (audio_sink_ready_to_receive) StartReceivingAudio(active_group_id_);
        if (audio_sender_state_ == AudioState::READY_TO_START)
          StartSendingAudio(active_group_id_);
        if (audio_receiver_state_ == AudioState::READY_TO_START)
          StartReceivingAudio(active_group_id_);
        break;
      case GroupStreamStatus::SUSPENDED:
        /** Stop Audio but don't release all the Audio resources */
@@ -2781,8 +2882,10 @@ class LeAudioClientImpl : public LeAudioClient {
  bool stream_request_started_;
  LeAudioContextType current_context_type_;

  bool audio_sink_ready_to_receive;
  bool audio_source_ready_to_send;
  /* Microphone (s) */
  AudioState audio_receiver_state_;
  /* Speaker(s) */
  AudioState audio_sender_state_;

  LeAudioCodecConfiguration current_source_codec_config;
  LeAudioCodecConfiguration current_sink_codec_config;
+6 −4
Original line number Diff line number Diff line
@@ -962,13 +962,15 @@ class UnicastTestNoInit : public Test {

    UpdateMetadata(usage, content_type);

    EXPECT_CALL(mock_audio_source_, ConfirmStreamingRequest()).Times(1);
    if (reconfigured_sink) {
      audio_sink_receiver_->OnAudioResume();
      SyncOnMainLoop();
    }

    if (reconfigured_sink) {
    EXPECT_CALL(mock_audio_source_, ConfirmStreamingRequest()).Times(1);
    audio_sink_receiver_->OnAudioResume();
    }
    state_machine_callbacks_->StatusReportCb(
              group_id, GroupStreamStatus::STREAMING);

    if (usage == AUDIO_USAGE_VOICE_COMMUNICATION) {
      ASSERT_NE(audio_source_receiver_, nullptr);