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

Commit 36fb8ceb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "le_audio: Implement voice back channel support" into tm-dev

parents a3af6f98 a151708d
Loading
Loading
Loading
Loading
+2892 −0

File changed.

Preview size limit exceeded, changes collapsed.

+48 −1
Original line number Diff line number Diff line
@@ -131,6 +131,53 @@
                "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1"
            ]
        },
        {
            "name": "VoiceAssistants",
            "configurations": [
                "DualDev_OneChanStereoSnk_48_4_1_OneChanStereoSrc_32_2_1_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_2_OneChanStereoSrc_32_2_2_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_1_OneChanStereoSrc_24_2_1_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_2_OneChanStereoSrc_24_2_2_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_1_OneChanStereoSrc_16_2_1_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_2_OneChanStereoSrc_16_2_2_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_32_2_1_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_2_OneChanMonoSrc_32_2_2_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_1_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_2_OneChanMonoSrc_24_2_2_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_1_Server_Preferred",
                "DualDev_OneChanStereoSnk_48_4_2_OneChanMonoSrc_16_2_2_Server_Preferred",
                "DualDev_OneChanDoubleStereoSnk_48_4_1_OneChanMonoSrc_32_2_1_Server_Preferred",
                "DualDev_OneChanDoubleStereoSnk_48_4_2_OneChanMonoSrc_32_2_2_Server_Preferred",
                "DualDev_OneChanDoubleStereoSnk_48_4_1_OneChanMonoSrc_24_2_1_Server_Preferred",
                "DualDev_OneChanDoubleStereoSnk_48_4_2_OneChanMonoSrc_24_2_2_Server_Preferred",
                "DualDev_OneChanDoubleStereoSnk_48_4_1_OneChanMonoSrc_16_2_1_Server_Preferred",
                "DualDev_OneChanDoubleStereoSnk_48_4_2_OneChanMonoSrc_16_2_2_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_1_TwoChanStereoSrc_32_2_1_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_2_TwoChanStereoSrc_32_2_2_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_1_TwoChanStereoSrc_24_2_1_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_2_TwoChanStereoSrc_24_2_2_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_1_TwoChanStereoSrc_16_2_1_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_2_TwoChanStereoSrc_16_2_2_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_32_2_1_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_2_OneChanMonoSrc_32_2_2_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_1_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_2_OneChanMonoSrc_24_2_2_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_1_Server_Preferred",
                "SingleDev_TwoChanStereoSnk_48_4_2_OneChanMonoSrc_16_2_2_Server_Preferred",
                "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_32_2_1_Server_Preferred",
                "SingleDev_OneChanStereoSnk_48_4_2_OneChanMonoSrc_32_2_2_Server_Preferred",
                "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_1_Server_Preferred",
                "SingleDev_OneChanStereoSnk_48_4_2_OneChanMonoSrc_24_2_2_Server_Preferred",
                "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_1_Server_Preferred",
                "SingleDev_OneChanStereoSnk_48_4_2_OneChanMonoSrc_16_2_2_Server_Preferred",
                "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_32_2_1_Server_Preferred",
                "SingleDev_OneChanMonoSnk_48_4_2_OneChanMonoSrc_32_2_2_Server_Preferred",
                "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_24_2_1_Server_Preferred",
                "SingleDev_OneChanMonoSnk_48_4_2_OneChanMonoSrc_24_2_2_Server_Preferred",
                "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_16_2_1_Server_Preferred",
                "SingleDev_OneChanMonoSnk_48_4_2_OneChanMonoSrc_16_2_2_Server_Preferred"
            ]
        },
        {
            "name": "Recording",
            "configurations": [
+73 −0
Original line number Diff line number Diff line
@@ -2922,6 +2922,15 @@ class LeAudioClientImpl : public LeAudioClient {
               << " audio_sender_state_: " << audio_sender_state_;
  }

  bool IsAudioSourceAvailableForCurrentContentType() {
    if (current_context_type_ == LeAudioContextType::CONVERSATIONAL ||
        current_context_type_ == LeAudioContextType::VOICEASSISTANTS) {
      return true;
    }

    return false;
  }

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

@@ -2973,6 +2982,11 @@ class LeAudioClientImpl : public LeAudioClient {
             */
            if (group->GetState() ==
                AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
              if (!IsAudioSourceAvailableForCurrentContentType()) {
                StopStreamIfNeeded(group, LeAudioContextType::VOICEASSISTANTS);
                break;
              }

              StartReceivingAudio(active_group_id_);
            }
            break;
@@ -3155,6 +3169,59 @@ class LeAudioClientImpl : public LeAudioClient {
    }
  }

  void OnAudioSourceMetadataUpdate(const sink_metadata_t& sink_metadata) {
    auto tracks = sink_metadata.tracks;
    auto track_count = sink_metadata.track_count;
    bool is_audio_source_invalid = true;

    while (track_count) {
      LOG_INFO(
          "%s: source=%d, gain=%f, destination device=%d, "
          "destination device address=%.32s",
          __func__, tracks->source, tracks->gain, tracks->dest_device,
          tracks->dest_device_address);

      /* Don't differentiate source types, just check if it's valid */
      if (is_audio_source_invalid && tracks->source != AUDIO_SOURCE_INVALID)
        is_audio_source_invalid = false;

      --track_count;
      ++tracks;
    }

    auto group = aseGroups_.FindById(active_group_id_);
    if (!group) {
      LOG(ERROR) << __func__
                 << ", Invalid group: " << static_cast<int>(active_group_id_);
      return;
    }

    /* Do nothing, since audio source is not valid and if voice assistant
     * scenario is currently not supported by group
     */
    if (is_audio_source_invalid ||
        !group->IsContextSupported(LeAudioContextType::VOICEASSISTANTS) ||
        IsAudioSourceAvailableForCurrentContentType()) {
      return;
    }

    auto new_context = LeAudioContextType::VOICEASSISTANTS;

    if (StopStreamIfNeeded(group, new_context)) return;

    if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
      /* Configuration is the same for new context, just will do update
       * metadata of stream
       */
      GroupStream(active_group_id_, static_cast<uint16_t>(new_context));
    }

    /* Audio sessions are not resumed yet and not streaming, let's pick voice
     * assistant as possible current context type.
     */
    current_context_type_ = new_context;
  }

  static void OnGattReadRspStatic(uint16_t conn_id, tGATT_STATUS status,
                                  uint16_t hdl, uint16_t len, uint8_t* value,
                                  void* data) {
@@ -3621,6 +3688,12 @@ class LeAudioClientAudioSourceReceiverImpl
  void OnAudioResume(void) override {
    if (instance) instance->OnAudioSourceResume();
  }

  void OnAudioMetadataUpdate(std::promise<void> do_metadata_update_promise,
                             const sink_metadata_t& sink_metadata) override {
    if (instance) instance->OnAudioSourceMetadataUpdate(sink_metadata);
    do_metadata_update_promise.set_value();
  }
};

LeAudioClientAudioSinkReceiverImpl audioSinkReceiverImpl;
+30 −1
Original line number Diff line number Diff line
@@ -255,6 +255,33 @@ bool LeAudioUnicastClientAudioSink::SourceOnSuspendReq() {
  return false;
}

bool LeAudioUnicastClientAudioSink::SourceOnMetadataUpdateReq(
    const sink_metadata_t& sink_metadata) {
  if (audioSourceReceiver_ == nullptr) {
    LOG(ERROR) << __func__ << ", audio receiver not started";
    return false;
  }

  // Call OnAudioSuspend and block till it returns.
  std::promise<void> do_update_metadata_promise;
  std::future<void> do_update_metadata_future =
      do_update_metadata_promise.get_future();
  bt_status_t status = do_in_main_thread(
      FROM_HERE,
      base::BindOnce(&LeAudioClientAudioSourceReceiver::OnAudioMetadataUpdate,
                     base::Unretained(audioSourceReceiver_),
                     std::move(do_update_metadata_promise), sink_metadata));

  if (status == BT_STATUS_SUCCESS) {
    do_update_metadata_future.wait();
    return true;
  }

  LOG(ERROR) << __func__ << ", do_in_main_thread err=" << status;

  return false;
}

bool LeAudioClientAudioSource::Start(
    const LeAudioCodecConfiguration& codec_configuration,
    LeAudioClientAudioSinkReceiver* audioReceiver) {
@@ -550,7 +577,9 @@ const void* LeAudioUnicastClientAudioSink::Acquire() {
                              this, std::placeholders::_1),
      .on_suspend_ =
          std::bind(&LeAudioUnicastClientAudioSink::SourceOnSuspendReq, this),
      .on_sink_metadata_update_ = le_audio_source_on_metadata_update_req,
      .on_sink_metadata_update_ =
          std::bind(&LeAudioUnicastClientAudioSink::SourceOnMetadataUpdateReq,
                    this, std::placeholders::_1),
  };

  sourceClientInterface_ =
+4 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ class LeAudioClientAudioSourceReceiver {
  virtual ~LeAudioClientAudioSourceReceiver() = default;
  virtual void OnAudioSuspend(std::promise<void> do_suspend_promise) = 0;
  virtual void OnAudioResume(void) = 0;
  virtual void OnAudioMetadataUpdate(
      std::promise<void> do_update_metadata_promise,
      const sink_metadata_t& sink_metadata) = 0;
};

/* Represents configuration of audio codec, as exchanged between le audio and
@@ -173,6 +176,7 @@ class LeAudioUnicastClientAudioSink {
 private:
  bool SourceOnResumeReq(bool start_media_task);
  bool SourceOnSuspendReq();
  bool SourceOnMetadataUpdateReq(const sink_metadata_t& sink_metadata);

  LeAudioClientAudioSourceReceiver* audioSourceReceiver_;
  bluetooth::audio::le_audio::LeAudioClientInterface::Source*
Loading