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

Commit 0d8b97ec authored by Patty's avatar Patty
Browse files

Use offload capability to select a proper codec configuration.

1. Store the offload configuration in the codec manager.
2. Use the software config priority to determine the offload
   capability order.
3. When offload is enabled, use the offload configuration to
   negotiate with remote devices.

Tag: #feature
Bug: 203535499
Bug: 150670922
Test: When offloading the codec configuration could be selected based on the offload capability
Change-Id: I47f1bec68eaebaea517f78fc71a0769e10775950
parent ed3c3b15
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -385,6 +385,7 @@ bool hal_ucast_capability_to_stack_format(
  auto sample_rate_hz = hal_lc3_capability.samplingFrequencyHz[0];
  auto frame_duration_us = hal_lc3_capability.frameDurationUs[0];
  auto octets_per_frame = hal_lc3_capability.octetsPerFrame[0];
  auto channel_count = hal_capability.channelCountPerDevice;

  if (sampling_freq_map.find(sample_rate_hz) == sampling_freq_map.end() ||
      frame_duration_map.find(frame_duration_us) == frame_duration_map.end() ||
@@ -406,8 +407,8 @@ bool hal_ucast_capability_to_stack_format(
          {.sampling_frequency = sampling_freq_map[sample_rate_hz],
           .frame_duration = frame_duration_map[frame_duration_us],
           .octets_per_codec_frame = octets_per_frame_map[octets_per_frame],
           .audio_channel_allocation = audio_location_map[supportedChannel]})};

           .audio_channel_allocation = audio_location_map[supportedChannel],
           .channel_count = static_cast<uint8_t>(channel_count)})};
  return true;
}

+2 −0
Original line number Diff line number Diff line
@@ -580,6 +580,7 @@ cc_test {
        "le_audio/broadcaster/state_machine_test.cc",
        "le_audio/le_audio_types.cc",
        "le_audio/mock_iso_manager.cc",
        "le_audio/mock_codec_manager.cc",
    ],
    shared_libs: [
        "libprotobuf-cpp-lite",
@@ -631,6 +632,7 @@ cc_test {
        "le_audio/mock_iso_manager.cc",
        "le_audio/mock_le_audio_client_audio.cc",
        "test/common/mock_controller.cc",
        "le_audio/mock_codec_manager.cc",
    ],
    shared_libs: [
        "libprotobuf-cpp-lite",
+1 −1
Original line number Diff line number Diff line
@@ -3339,7 +3339,7 @@ void LeAudioClient::Initialize(
  instance = new LeAudioClientImpl(callbacks_, stateMachineCallbacks, initCb);

  IsoManager::GetInstance()->RegisterCigCallbacks(stateMachineHciCallbacks);
  CodecManager::GetInstance()->Start();
  CodecManager::GetInstance()->Start(offloading_preference, capabilities);
}

void LeAudioClient::DebugDump(int fd) {
+163 −5
Original line number Diff line number Diff line
@@ -29,13 +29,22 @@ using bluetooth::hci::iso_manager::kIsoDataPathHci;
using bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
using le_audio::CodecManager;
using le_audio::types::CodecLocation;

using bluetooth::le_audio::btle_audio_codec_config_t;
using bluetooth::le_audio::btle_audio_codec_index_t;
using le_audio::set_configurations::AudioSetConfiguration;
using le_audio::set_configurations::AudioSetConfigurations;
using le_audio::set_configurations::SetConfiguration;

}  // namespace

namespace le_audio {

struct codec_manager_impl {
 public:
  codec_manager_impl() {
  codec_manager_impl(
      const std::vector<btle_audio_codec_config_t>& offloading_preference,
      const std::vector<AudioSetConfiguration>& adsp_capabilities) {
    offload_enable_ = osi_property_get_bool(
                          "ro.bluetooth.leaudio_offload.supported", false) &&
                      osi_property_get_bool(
@@ -60,6 +69,7 @@ struct codec_manager_impl {
                            kIsoDataPathPlatformDefault, {});
    btm_configure_data_path(btm_data_direction::CONTROLLER_TO_HOST,
                            kIsoDataPathPlatformDefault, {});
    UpdateOffloadCapability(offloading_preference, adsp_capabilities);
    SetCodecLocation(CodecLocation::ADSP);
  }
  ~codec_manager_impl() {
@@ -108,23 +118,158 @@ struct codec_manager_impl {
    LeAudioClientAudioSink::UpdateAudioConfigToHal(source_config);
  }

  const AudioSetConfigurations* GetOffloadCodecConfig(
      types::LeAudioContextType ctx_type) {
    return &context_type_offload_config_map_[ctx_type];
  }

 private:
  void SetCodecLocation(CodecLocation location) {
    if (offload_enable_ == false) return;
    codec_location_ = location;
  }

  bool IsLc3ConfigMatched(
      const set_configurations::CodecCapabilitySetting& adsp_config,
      const set_configurations::CodecCapabilitySetting& target_config) {
    if (adsp_config.id.coding_format != types::kLeAudioCodingFormatLC3 ||
        target_config.id.coding_format != types::kLeAudioCodingFormatLC3) {
      return false;
    }

    const types::LeAudioLc3Config adsp_lc3_config =
        std::get<types::LeAudioLc3Config>(adsp_config.config);
    const types::LeAudioLc3Config target_lc3_config =
        std::get<types::LeAudioLc3Config>(target_config.config);

    if (adsp_lc3_config.sampling_frequency !=
            target_lc3_config.sampling_frequency ||
        adsp_lc3_config.frame_duration != target_lc3_config.frame_duration ||
        adsp_lc3_config.channel_count != target_lc3_config.channel_count ||
        adsp_lc3_config.octets_per_codec_frame !=
            target_lc3_config.octets_per_codec_frame) {
      return false;
    }

    return true;
  }

  bool IsSetConfigurationMatched(const SetConfiguration& software_set_config,
                                 const SetConfiguration& adsp_set_config) {
    // Skip the check of stategry and ase_cnt due to ADSP doesn't have the info
    return (
        software_set_config.direction == adsp_set_config.direction &&
        software_set_config.device_cnt == adsp_set_config.device_cnt &&
        IsLc3ConfigMatched(software_set_config.codec, adsp_set_config.codec));
  }

  bool IsAudioSetConfigurationMatched(
      const AudioSetConfiguration* software_audio_set_conf,
      std::unordered_set<uint8_t>& offload_preference_set,
      const std::vector<AudioSetConfiguration>& adsp_capabilities) {
    if (software_audio_set_conf->confs.empty()) {
      return false;
    }

    std::unordered_map<uint8_t, const SetConfiguration&>
        software_set_conf_direction_map;

    for (auto& software_set_conf : software_audio_set_conf->confs) {
      // Checks offload preference supports the codec
      if (offload_preference_set.find(
              software_set_conf.codec.id.coding_format) ==
          offload_preference_set.end()) {
        return false;
      }
      software_set_conf_direction_map.emplace(software_set_conf.direction,
                                              software_set_conf);
    }

    // Checks any of offload config matches the input audio set config
    for (const auto& adsp_audio_set_conf : adsp_capabilities) {
      if (adsp_audio_set_conf.confs.size() !=
          software_audio_set_conf->confs.size()) {
        continue;
      }

      size_t match_cnt = 0;

      for (auto& adsp_set_conf : adsp_audio_set_conf.confs) {
        auto it = software_set_conf_direction_map.find(adsp_set_conf.direction);

        if (it == software_set_conf_direction_map.end()) {
          continue;
        }

        if (IsSetConfigurationMatched(it->second, adsp_set_conf)) {
          match_cnt++;
        }
      }

      if (match_cnt == software_set_conf_direction_map.size()) {
        return true;
      }
    }

    return false;
  }

  void UpdateOffloadCapability(
      const std::vector<btle_audio_codec_config_t>& offloading_preference,
      const std::vector<AudioSetConfiguration>& adsp_capabilities) {
    LOG(INFO) << __func__;
    std::unordered_set<uint8_t> offload_preference_set;

    for (auto codec : offloading_preference) {
      auto it = btle_audio_codec_type_map_.find(codec.codec_type);

      if (it != btle_audio_codec_type_map_.end()) {
        offload_preference_set.insert(it->second);
      }
    }

    for (types::LeAudioContextType ctx_type :
         types::kLeAudioContextAllTypesArray) {
      // Gets the software supported context type and the corresponding config
      // priority
      const AudioSetConfigurations* software_audio_set_confs =
          set_configurations::get_confs_by_type(ctx_type);

      for (const auto& software_audio_set_conf : *software_audio_set_confs) {
        if (IsAudioSetConfigurationMatched(software_audio_set_conf,
                                           offload_preference_set,
                                           adsp_capabilities)) {
          LOG(INFO) << "Offload supported conf, context type: " << (int)ctx_type
                    << ", settings -> " << software_audio_set_conf->name;
          context_type_offload_config_map_[ctx_type].push_back(
              software_audio_set_conf);
        }
      }
    }
  }

  CodecLocation codec_location_ = CodecLocation::HOST;
  bool offload_enable_ = false;
  le_audio::offload_config sink_config;
  le_audio::offload_config source_config;
  std::unordered_map<types::LeAudioContextType, AudioSetConfigurations>
      context_type_offload_config_map_;
  std::unordered_map<btle_audio_codec_index_t, uint8_t>
      btle_audio_codec_type_map_ = {
          {::bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
           types::kLeAudioCodingFormatLC3}};
};

struct CodecManager::impl {
  impl(const CodecManager& codec_manager) : codec_manager_(codec_manager) {}

  void Start() {
  void Start(
      const std::vector<btle_audio_codec_config_t>& offloading_preference,
      const std::vector<set_configurations::AudioSetConfiguration>&
          adsp_capabilities) {
    LOG_ASSERT(!codec_manager_impl_);
    codec_manager_impl_ = std::make_unique<codec_manager_impl>();
    codec_manager_impl_ = std::make_unique<codec_manager_impl>(
        offloading_preference, adsp_capabilities);
  }

  void Stop() {
@@ -140,8 +285,12 @@ struct CodecManager::impl {

CodecManager::CodecManager() : pimpl_(std::make_unique<impl>(*this)) {}

void CodecManager::Start() {
  if (!pimpl_->IsRunning()) pimpl_->Start();
void CodecManager::Start(
    const std::vector<btle_audio_codec_config_t>& offloading_preference,
    const std::vector<set_configurations::AudioSetConfiguration>&
        adsp_capabilities) {
  if (!pimpl_->IsRunning())
    pimpl_->Start(offloading_preference, adsp_capabilities);
}

void CodecManager::Stop() {
@@ -170,4 +319,13 @@ void CodecManager::UpdateActiveSinkAudioConfig(
                                                             delay);
}

const AudioSetConfigurations* CodecManager::GetOffloadCodecConfig(
    types::LeAudioContextType ctx_type) {
  if (pimpl_->IsRunning()) {
    return pimpl_->codec_manager_impl_->GetOffloadCodecConfig(ctx_type);
  }

  return nullptr;
}

}  // namespace le_audio
+7 −1
Original line number Diff line number Diff line
@@ -38,13 +38,19 @@ class CodecManager {
    static CodecManager* instance = new CodecManager();
    return instance;
  }
  void Start(void);
  void Start(
      const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>&
          offloading_preference,
      const std::vector<::le_audio::set_configurations::AudioSetConfiguration>&
          adsp_capabilities);
  void Stop(void);
  virtual types::CodecLocation GetCodecLocation(void) const;
  virtual void UpdateActiveSourceAudioConfig(
      const stream_configuration& stream_conf, uint16_t delay);
  virtual void UpdateActiveSinkAudioConfig(
      const stream_configuration& stream_conf, uint16_t delay);
  const ::le_audio::set_configurations::AudioSetConfigurations*
  GetOffloadCodecConfig(::le_audio::types::LeAudioContextType ctx_type);

 private:
  struct impl;
Loading