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

Commit 16cee82f authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "LeAudio: Decouple BAP logic from Audio HAL client type" into main

parents ffac08f5 cca2f4b1
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -23,9 +23,8 @@
#include "audio_hal_interface/le_audio_software.h"

namespace bluetooth::le_audio {
/* Represents configuration of audio codec, as exchanged between le audio and
 * phone.
 * It can also be passed to the audio source to configure its parameters.
/* Represents configuration used to configure the local audio sessions and
 * the software codecs in case of a software coding sessions.
 */
struct LeAudioCodecConfiguration {
  static constexpr uint8_t kChannelNumberMono =
@@ -57,13 +56,13 @@ struct LeAudioCodecConfiguration {
  static constexpr uint32_t kInterval10000Us = 10000;

  /** number of channels */
  uint8_t num_channels;
  uint8_t num_channels = 0;

  /** sampling rate that the codec expects to receive from audio framework */
  uint32_t sample_rate;
  uint32_t sample_rate = 0;

  /** bits per sample that codec expects to receive from audio framework */
  uint8_t bits_per_sample;
  uint8_t bits_per_sample = 0;

  /** Data interval determines how often we send samples to the remote. This
   * should match how often we grab data from audio source, optionally we can
@@ -71,7 +70,7 @@ struct LeAudioCodecConfiguration {
   *
   * Value is provided in us.
   */
  uint32_t data_interval_us;
  uint32_t data_interval_us = 0;

  bool operator!=(const LeAudioCodecConfiguration& other) {
    return !((num_channels == other.num_channels) &&
+65 −136
Original line number Diff line number Diff line
@@ -249,8 +249,6 @@ class LeAudioClientImpl : public LeAudioClient {
        sink_monitor_mode_(false),
        sink_monitor_notified_status_(std::nullopt),
        source_monitor_mode_(false),
        current_source_codec_config({0, 0, 0, 0}),
        current_sink_codec_config({0, 0, 0, 0}),
        le_audio_source_hal_client_(nullptr),
        le_audio_sink_hal_client_(nullptr),
        close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")),
@@ -1111,9 +1109,7 @@ class LeAudioClientImpl : public LeAudioClient {
    group->is_duplex_preference_le_audio = is_duplex_preference_le_audio;
  }

  void StartAudioSession(LeAudioDeviceGroup* group,
                         const LeAudioCodecConfiguration* source_config,
                         const LeAudioCodecConfiguration* sink_config) {
  void StartAudioSession(LeAudioDeviceGroup* group) {
    /* This function is called when group is not yet set to active.
     * This is why we don't have to check if session is started already.
     * Just check if it is acquired.
@@ -1132,10 +1128,10 @@ class LeAudioClientImpl : public LeAudioClient {

    /* We assume that peer device always use same frame duration */
    uint32_t frame_duration_us = 0;
    if (!source_config->IsInvalid()) {
      frame_duration_us = source_config->data_interval_us;
    } else if (!sink_config->IsInvalid()) {
      frame_duration_us = sink_config->data_interval_us;
    if (!current_encoder_config_.IsInvalid()) {
      frame_duration_us = current_encoder_config_.data_interval_us;
    } else if (!current_decoder_config_.IsInvalid()) {
      frame_duration_us = current_decoder_config_.data_interval_us;
    } else {
      log::assert_that(true, "Both configs are invalid");
    }
@@ -1150,14 +1146,13 @@ class LeAudioClientImpl : public LeAudioClient {
    /* If group supports more than 16kHz for the microphone in converstional
     * case let's use that also for Audio Framework.
     */
    std::optional<LeAudioCodecConfiguration> sink_configuration =
        group->GetCodecConfigurationByDirection(
    auto sink_configuration = group->GetAudioSessionCodecConfigForDirection(
        LeAudioContextType::CONVERSATIONAL,
        bluetooth::le_audio::types::kLeAudioDirectionSource);
    if (sink_configuration &&
        sink_configuration->sample_rate >
    if (!sink_configuration.IsInvalid() &&
        sink_configuration.sample_rate >
            bluetooth::audio::le_audio::kSampleRate16000) {
      audio_framework_sink_config.sample_rate = sink_configuration->sample_rate;
      audio_framework_sink_config.sample_rate = sink_configuration.sample_rate;
    }

    le_audio_sink_hal_client_->Start(audio_framework_sink_config,
@@ -1289,14 +1284,12 @@ class LeAudioClientImpl : public LeAudioClient {
        }
      }
    }
    UpdateConfigAndCheckIfReconfigurationIsNeeded(group_id,
                                                  default_context_type);
    if (current_source_codec_config.IsInvalid() &&
        current_sink_codec_config.IsInvalid()) {
      log::error("Unsupported device configurations");

    /* Only update the configuration audio context and audio coding session
     * parameters if needed.
     */
    UpdateConfigAndCheckIfReconfigurationIsNeeded(group, default_context_type);
    callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
      return;
    }

    auto previous_active_group = active_group_id_;
    log::info("Active group_id changed {} -> {}", previous_active_group,
@@ -1304,8 +1297,7 @@ class LeAudioClientImpl : public LeAudioClient {

    if (previous_active_group == bluetooth::groups::kGroupUnknown) {
      /* Expose audio sessions if there was no previous active group */
      StartAudioSession(group, &current_source_codec_config,
                        &current_sink_codec_config);
      StartAudioSession(group);
      active_group_id_ = group_id;
    } else {
      /* In case there was an active group. Stop the stream, but before that, set
@@ -3678,7 +3670,7 @@ class LeAudioClientImpl : public LeAudioClient {
      sw_enc_left = bluetooth::le_audio::CodecInterface::CreateInstance(
          stream_conf->codec_id);
      auto codec_status = sw_enc_left->InitEncoder(
          audio_framework_source_config, current_source_codec_config);
          audio_framework_source_config, current_encoder_config_);
      if (codec_status !=
          bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
        log::error("Left channel codec setup failed with err: {}",
@@ -3690,7 +3682,7 @@ class LeAudioClientImpl : public LeAudioClient {
      sw_enc_right = bluetooth::le_audio::CodecInterface::CreateInstance(
          stream_conf->codec_id);
      codec_status = sw_enc_right->InitEncoder(audio_framework_source_config,
                                               current_source_codec_config);
                                               current_encoder_config_);
      if (codec_status !=
          bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
        log::error("Right channel codec setup failed with err: {}",
@@ -3757,7 +3749,7 @@ class LeAudioClientImpl : public LeAudioClient {
      }
      sw_dec_left = bluetooth::le_audio::CodecInterface::CreateInstance(
          stream_conf->codec_id);
      auto codec_status = sw_dec_left->InitDecoder(current_sink_codec_config,
      auto codec_status = sw_dec_left->InitDecoder(current_decoder_config_,
                                                   audio_framework_sink_config);
      if (codec_status !=
          bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
@@ -3769,7 +3761,7 @@ class LeAudioClientImpl : public LeAudioClient {

      sw_dec_right = bluetooth::le_audio::CodecInterface::CreateInstance(
          stream_conf->codec_id);
      codec_status = sw_dec_right->InitDecoder(current_sink_codec_config,
      codec_status = sw_dec_right->InitDecoder(current_decoder_config_,
                                               audio_framework_sink_config);
      if (codec_status !=
          bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
@@ -3810,49 +3802,30 @@ class LeAudioClientImpl : public LeAudioClient {

  void StopAudio(void) { SuspendAudio(); }

  void printSingleConfiguration(int fd, LeAudioCodecConfiguration* conf,
                                bool print_audio_state, bool sender = false) {
  void printCurrentStreamConfiguration(int fd) {
    std::stringstream stream;
    if (print_audio_state) {
      if (sender) {
        stream << "\taudio sender state: " << audio_sender_state_ << "\n";
      } else {
        stream << "\taudio receiver state: " << audio_receiver_state_ << "\n";
      }
    }

    stream << "\tsample rate: " << +conf->sample_rate
           << ",\tchan: " << +conf->num_channels
           << ",\tbits: " << +conf->bits_per_sample
           << ",\tdata_interval_us: " << +conf->data_interval_us << "\n";
    auto config_printer = [&stream](LeAudioCodecConfiguration& conf) {
      stream << "\tsample rate: " << +conf.sample_rate
             << ",\tchan: " << +conf.num_channels
             << ",\tbits: " << +conf.bits_per_sample
             << ",\tdata_interval_us: " << +conf.data_interval_us << "\n";
    };

    dprintf(fd, "%s", stream.str().c_str());
  }
    stream << " Speaker codec config (audio framework) \n";
    stream << "\taudio sender state: " << audio_sender_state_ << "\n";
    config_printer(audio_framework_source_config);

  void printCurrentStreamConfiguration(int fd) {
    auto conf = &audio_framework_source_config;
    dprintf(fd, " Speaker codec config (audio framework) \n");
    if (conf) {
      printSingleConfiguration(fd, conf, false);
    }
    stream << " Microphone codec config (audio framework) \n";
    stream << "\taudio receiver state: " << audio_receiver_state_ << "\n";
    config_printer(audio_framework_sink_config);

    dprintf(fd, " Microphone codec config (audio framework) \n");
    conf = &audio_framework_sink_config;
    if (conf) {
      printSingleConfiguration(fd, conf, false);
    }
    stream << " Speaker codec config (SW encoder)\n";
    config_printer(current_encoder_config_);

    conf = &current_source_codec_config;
    dprintf(fd, " Speaker codec config (Bluetooth)\n");
    if (conf) {
      printSingleConfiguration(fd, conf, true, true);
    }
    stream << " Microphone codec config (SW decoder)\n";
    config_printer(current_decoder_config_);

    conf = &current_sink_codec_config;
    dprintf(fd, " Microphone codec config (Bluetooth)\n");
    if (conf) {
      printSingleConfiguration(fd, conf, true, false);
    }
    dprintf(fd, "%s", stream.str().c_str());
  }

  void Dump(int fd) {
@@ -3924,65 +3897,17 @@ class LeAudioClientImpl : public LeAudioClient {
  }

  AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded(
      int group_id, LeAudioContextType context_type) {
    bool reconfiguration_needed = false;
    bool sink_cfg_available = true;
    bool source_cfg_available = true;

      LeAudioDeviceGroup* group, LeAudioContextType context_type) {
    log::debug("Checking whether to reconfigure from {} to {}",
               ToString(configuration_context_type_), ToString(context_type));

    auto group = aseGroups_.FindById(group_id);
    if (!group) {
      log::error("Invalid group: {}", static_cast<int>(group_id));
      return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
    }

    std::optional<LeAudioCodecConfiguration> source_configuration =
        group->GetCodecConfigurationByDirection(
            context_type, bluetooth::le_audio::types::kLeAudioDirectionSink);
    std::optional<LeAudioCodecConfiguration> sink_configuration =
        group->GetCodecConfigurationByDirection(
            context_type, bluetooth::le_audio::types::kLeAudioDirectionSource);

    if (source_configuration) {
      if (*source_configuration != current_source_codec_config) {
        current_source_codec_config = *source_configuration;
        reconfiguration_needed = true;
      }
    } else {
      if (!current_source_codec_config.IsInvalid()) {
        current_source_codec_config = {0, 0, 0, 0};
        reconfiguration_needed = true;
      }
      source_cfg_available = false;
    }

    if (sink_configuration) {
      if (*sink_configuration != current_sink_codec_config) {
        current_sink_codec_config = *sink_configuration;
        reconfiguration_needed = true;
      }
    } else {
      if (!current_sink_codec_config.IsInvalid()) {
        current_sink_codec_config = {0, 0, 0, 0};
        reconfiguration_needed = true;
      }

      sink_cfg_available = false;
    }

    if (DsaReconfigureNeeded(group, context_type)) {
      reconfiguration_needed = true;
    auto audio_set_conf = group->GetConfiguration(context_type);
    if (!audio_set_conf) {
      return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE;
    }

    log::debug(
        "Context: {} Reconfiguration_needed = {}, sink_cfg_available = {}, "
        "source_cfg_available = {}",
        ToString(context_type), reconfiguration_needed, sink_cfg_available,
        source_cfg_available);

    if (!reconfiguration_needed) {
    if (group->IsGroupConfiguredTo(*audio_set_conf) &&
        !DsaReconfigureNeeded(group, context_type)) {
      // Assign the new configuration context as it reprents the current
      // use case even when it eventually ends up being the exact same
      // codec and qos configuration.
@@ -3993,14 +3918,17 @@ class LeAudioClientImpl : public LeAudioClient {
      return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
    }

    if (!sink_cfg_available && !source_cfg_available) {
      return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE;
    }

    log::info("Session reconfiguration needed group: {} for context type: {}",
              group->group_id_, ToHexString(context_type));

    configuration_context_type_ = context_type;

    // Note: The local sink config is based on remote device's source config
    //       and vice versa.
    current_decoder_config_ = group->GetAudioSessionCodecConfigForDirection(
        context_type, bluetooth::le_audio::types::kLeAudioDirectionSource);
    current_encoder_config_ = group->GetAudioSessionCodecConfigForDirection(
        context_type, bluetooth::le_audio::types::kLeAudioDirectionSink);
    return AudioReconfigurationResult::RECONFIGURATION_NEEDED;
  }

@@ -4143,7 +4071,7 @@ class LeAudioClientImpl : public LeAudioClient {
    }

    /* Check if the device resume is allowed */
    if (!group->GetCodecConfigurationByDirection(
    if (!group->HasCodecConfigurationForDirection(
            configuration_context_type_,
            bluetooth::le_audio::types::kLeAudioDirectionSink)) {
      log::error("invalid resume request for context type: {}",
@@ -4358,10 +4286,11 @@ class LeAudioClientImpl : public LeAudioClient {

  inline bool IsDirectionAvailableForCurrentConfiguration(
      const LeAudioDeviceGroup* group, uint8_t direction) const {
    return group
        ->GetCachedCodecConfigurationByDirection(configuration_context_type_,
                                                 direction)
        .has_value();
    auto current_config =
        group->GetCachedConfiguration(configuration_context_type_);
    if (current_config)
      return (current_config->confs.get(direction).size() != 0);
    return false;
  }

  void notifyAudioLocalSink(UnicastMonitorModeStatus status) {
@@ -4418,7 +4347,7 @@ class LeAudioClientImpl : public LeAudioClient {
    }

    /* Check if the device resume is allowed */
    if (!group->GetCodecConfigurationByDirection(
    if (!group->HasCodecConfigurationForDirection(
            configuration_context_type_,
            bluetooth::le_audio::types::kLeAudioDirectionSource)) {
      log::error("invalid resume request for context type: {}",
@@ -4639,8 +4568,8 @@ class LeAudioClientImpl : public LeAudioClient {

  bool SetConfigurationAndStopStreamWhenNeeded(
      LeAudioDeviceGroup* group, LeAudioContextType new_context_type) {
    auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded(
        group->group_id_, new_context_type);
    auto reconfig_result =
        UpdateConfigAndCheckIfReconfigurationIsNeeded(group, new_context_type);
    /* Even though the reconfiguration may not be needed, this has
     * to be set here as it might be the initial configuration.
     */
@@ -5821,9 +5750,9 @@ class LeAudioClientImpl : public LeAudioClient {

  static constexpr uint16_t kBapMinimumAttMtu = 64;

  /* Current stream configuration */
  LeAudioCodecConfiguration current_source_codec_config;
  LeAudioCodecConfiguration current_sink_codec_config;
  /* Current stream configuration - used to set up the software codecs */
  LeAudioCodecConfiguration current_encoder_config_;
  LeAudioCodecConfiguration current_decoder_config_;

  /* Static Audio Framework session configuration.
   *  Resampling will be done inside the bt stack
+22 −57
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

#include <bluetooth/log.h>

#include <optional>

#include "bta/include/bta_gatt_api.h"
#include "bta_csis_api.h"
#include "btif/include/btif_profile_storage.h"
@@ -28,6 +30,7 @@
#include "internal_include/bt_trace.h"
#include "le_audio/le_audio_types.h"
#include "le_audio_set_configuration_provider.h"
#include "le_audio_utils.h"
#include "main/shim/entry.h"
#include "metrics_collector.h"
#include "os/log.h"
@@ -760,7 +763,7 @@ bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) {
}

bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache(
    LeAudioContextType ctx_type) {
    LeAudioContextType ctx_type) const {
  CodecManager::UnicastConfigurationRequirements requirements = {
      .audio_context_type = ctx_type};
  auto new_conf = CodecManager::GetInstance()->GetCodecConfig(
@@ -1550,7 +1553,7 @@ LeAudioDeviceGroup::GetActiveConfiguration(void) const {
}

std::shared_ptr<const set_configurations::AudioSetConfiguration>
LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) {
LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) const {
  if (context_type == LeAudioContextType::UNINITIALIZED) {
    return nullptr;
  }
@@ -1572,60 +1575,9 @@ LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) {
  return GetCachedConfiguration(context_type);
}

std::optional<LeAudioCodecConfiguration>
LeAudioDeviceGroup::GetCachedCodecConfigurationByDirection(
LeAudioCodecConfiguration
LeAudioDeviceGroup::GetAudioSessionCodecConfigForDirection(
    LeAudioContextType context_type, uint8_t direction) const {
  auto audio_set_conf = GetCachedConfiguration(context_type);
  if (!audio_set_conf) return std::nullopt;

  LeAudioCodecConfiguration group_config = {0, 0, 0, 0};
  for (const auto& conf : audio_set_conf->confs.get(direction)) {
    if (group_config.sample_rate != 0 &&
        conf.codec.GetSamplingFrequencyHz() != group_config.sample_rate) {
      log::warn(
          "stream configuration could not be determined (sampling frequency "
          "differs) for direction: {}",
          loghex(direction));
      return std::nullopt;
    }
    group_config.sample_rate = conf.codec.GetSamplingFrequencyHz();

    if (group_config.data_interval_us != 0 &&
        conf.codec.GetDataIntervalUs() != group_config.data_interval_us) {
      log::warn(
          "stream configuration could not be determined (data interval "
          "differs) for direction: {}",
          loghex(direction));
      return std::nullopt;
    }
    group_config.data_interval_us = conf.codec.GetDataIntervalUs();

    if (group_config.bits_per_sample != 0 &&
        conf.codec.GetBitsPerSample() != group_config.bits_per_sample) {
      log::warn(
          "stream configuration could not be determined (bits per sample "
          "differs) for direction: {}",
          loghex(direction));
      return std::nullopt;
    }
    group_config.bits_per_sample = conf.codec.GetBitsPerSample();

    log::assert_that(
        audio_set_conf->topology_info.has_value(),
        "No topology info, which is required to properly configure the ASEs");
    group_config.num_channels +=
        conf.codec.GetChannelCountPerIsoStream() *
        audio_set_conf->topology_info->device_count.get(direction);
  }

  if (group_config.IsInvalid()) return std::nullopt;

  return group_config;
}

std::optional<LeAudioCodecConfiguration>
LeAudioDeviceGroup::GetCodecConfigurationByDirection(
    LeAudioContextType context_type, uint8_t direction) {
  const set_configurations::AudioSetConfiguration* conf = nullptr;
  bool is_valid = false;

@@ -1640,8 +1592,19 @@ LeAudioDeviceGroup::GetCodecConfigurationByDirection(
    UpdateAudioSetConfigurationCache(context_type);
  }

  /* Return the cached value */
  return GetCachedCodecConfigurationByDirection(context_type, direction);
  auto audio_set_conf = GetCachedConfiguration(context_type);
  if (!audio_set_conf) return {0, 0, 0, 0};

  auto group_config =
      utils::GetAudioSessionCodecConfigFromAudioSetConfiguration(
          *audio_set_conf.get(), direction);
  return group_config;
}

bool LeAudioDeviceGroup::HasCodecConfigurationForDirection(
    types::LeAudioContextType context_type, uint8_t direction) const {
  auto audio_set_conf = GetConfiguration(context_type);
  return audio_set_conf ? !audio_set_conf->confs.get(direction).empty() : false;
}

bool LeAudioDeviceGroup::IsAudioSetConfigurationAvailable(
@@ -1864,6 +1827,8 @@ bool LeAudioDeviceGroup::IsConfiguredForContext(
    return false;
  }

  if (!stream_conf.conf) return false;

  /* Check if used configuration is same as the active one.*/
  return (stream_conf.conf.get() == GetActiveConfiguration().get());
}
+16 −9
Original line number Diff line number Diff line
@@ -76,6 +76,12 @@ class LeAudioDeviceGroup {
    types::CigState state_;
  } cig;

  bool IsGroupConfiguredTo(
      const set_configurations::AudioSetConfiguration& cfg) {
    if (!stream_conf.conf) return false;
    return cfg == *stream_conf.conf;
  }

  /* Current configuration strategy - recalculated on demand */
  mutable std::optional<types::LeAudioConfigurationStrategy> strategy_ =
      std::nullopt;
@@ -204,14 +210,15 @@ class LeAudioDeviceGroup {
  bool GetPresentationDelay(uint32_t* delay, uint8_t direction) const;
  uint16_t GetRemoteDelay(uint8_t direction) const;
  bool UpdateAudioContextAvailability(void);
  bool UpdateAudioSetConfigurationCache(types::LeAudioContextType ctx_type);
  bool UpdateAudioSetConfigurationCache(
      types::LeAudioContextType ctx_type) const;
  bool ReloadAudioLocations(void);
  bool ReloadAudioDirections(void);
  std::shared_ptr<const set_configurations::AudioSetConfiguration>
  GetActiveConfiguration(void) const;
  bool IsPendingConfiguration(void) const;
  std::shared_ptr<const set_configurations::AudioSetConfiguration>
  GetConfiguration(types::LeAudioContextType ctx_type);
  GetConfiguration(types::LeAudioContextType ctx_type) const;
  std::shared_ptr<const set_configurations::AudioSetConfiguration>
  GetCachedConfiguration(types::LeAudioContextType ctx_type) const;
  void InvalidateCachedConfigurations(void);
@@ -225,10 +232,9 @@ class LeAudioDeviceGroup {
  bool IsAudioSetConfigurationSupported(
      LeAudioDevice* leAudioDevice,
      const set_configurations::AudioSetConfiguration* audio_set_conf) const;
  std::optional<LeAudioCodecConfiguration> GetCodecConfigurationByDirection(
      types::LeAudioContextType group_context_type, uint8_t direction);
  std::optional<LeAudioCodecConfiguration>
  GetCachedCodecConfigurationByDirection(
  LeAudioCodecConfiguration GetAudioSessionCodecConfigForDirection(
      types::LeAudioContextType group_context_type, uint8_t direction) const;
  bool HasCodecConfigurationForDirection(
      types::LeAudioContextType group_context_type, uint8_t direction) const;
  bool IsAudioSetConfigurationAvailable(
      types::LeAudioContextType group_context_type);
@@ -432,7 +438,8 @@ class LeAudioDeviceGroup {
   * change. Stored as a pair of (is_valid_cache, configuration*). `pair.first`
   * being `false` means that the cached value should be refreshed.
   */
  std::map<types::LeAudioContextType,
  mutable std::map<
      types::LeAudioContextType,
      std::pair<bool, const std::shared_ptr<
                          set_configurations::AudioSetConfiguration>>>
      context_to_configuration_cache_map;
+50 −70

File changed.

Preview size limit exceeded, changes collapsed.

Loading