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

Commit 00391605 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Extend the codec requirements

This extends the Codec Manager interface to allow passing the
requirements needed for the AIDL codec config provider.
Additionally unit tests are parametrized to run with the vendor
codec configurations.

Bug: 308428860
Bug: 295972694
Test: atest --host bluetooth_le_audio_test bluetooth_le_audio_client_test  bluetooth_test_broadcaster bluetooth_test_broadcaster_state_machine bluetooth_le_audio_codec_manager_test
Flags: EXEMPT; Vendor codec boilerplate - not in the execution path yet
Change-Id: Idaee57b9085503ebdea20dbe53e43ed0364dd95f
parent e0c0aef0
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -62,6 +62,17 @@ class CodecManager {
 public:
  struct UnicastConfigurationRequirements {
    ::bluetooth::le_audio::types::LeAudioContextType audio_context_type;
    std::optional<std::vector<types::acs_ac_record>> sink_pacs;
    std::optional<std::vector<types::acs_ac_record>> source_pacs;

    struct DeviceDirectionRequirements {
      uint8_t target_latency = types::kTargetLatencyUndefined;
      uint8_t target_Phy = types::kTargetPhyUndefined;
      types::LeAudioLtvMap params;
    };

    std::optional<std::vector<DeviceDirectionRequirements>> sink_requirements;
    std::optional<std::vector<DeviceDirectionRequirements>> source_requirements;
  };

  /* The verifier function checks each possible configuration (from the set of
+86 −4
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "hci/controller_interface.h"
#include "internal_include/bt_trace.h"
#include "le_audio/codec_manager.h"
#include "le_audio/devices.h"
#include "le_audio/le_audio_types.h"
#include "le_audio_set_configuration_provider.h"
#include "le_audio_utils.h"
@@ -783,11 +784,90 @@ bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) {
  return old_contexts != GetAvailableContexts();
}

CodecManager::UnicastConfigurationRequirements
LeAudioDeviceGroup::GetAudioSetConfigurationRequirements(
    types::LeAudioContextType ctx_type) const {
  auto new_req = CodecManager::UnicastConfigurationRequirements{
      .audio_context_type = ctx_type,
  };

  // Define a requirement for each location. Knowing codec specific
  // capabilities (i.e. multiplexing capability) the config provider can
  // determine the number of ASEs to activate.
  for (auto const& weak_dev_ptr : leAudioDevices_) {
    auto device = weak_dev_ptr.lock();
    BidirectionalPair<bool> has_location = {false, false};

    for (auto direction :
         {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) {
      if (device->GetAseCount(direction) == 0) {
        log::warn("Device {} has no ASEs for direction: {}", device->address_,
                  (int)direction);
        continue;
      }

      auto& dev_locations = (direction == types::kLeAudioDirectionSink)
                                ? device->snk_audio_locations_
                                : device->src_audio_locations_;
      if (dev_locations.none()) {
        log::warn("Device {} has no locations for direction: {}",
                  device->address_, (int)direction);
        continue;
      }

      has_location.get(direction) = true;
      auto& direction_req = (direction == types::kLeAudioDirectionSink)
                                ? new_req.sink_requirements
                                : new_req.source_requirements;
      if (!direction_req) {
        direction_req =
            std::vector<CodecManager::UnicastConfigurationRequirements::
                            DeviceDirectionRequirements>();
      }

      // Pass the audio channel allocation requirement
      auto locations = dev_locations.to_ulong();
      CodecManager::UnicastConfigurationRequirements::
          DeviceDirectionRequirements config_req;
      config_req.params.Add(
          codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
          (uint32_t)locations);
      log::warn("Device {} pushes requirement, location: {}, direction: {}",
                device->address_, (int)locations, (int)direction);
      direction_req->push_back(std::move(config_req));
    }

    // Push sink PACs if there are some sink requirements
    if (has_location.sink && !device->snk_pacs_.empty()) {
      if (!new_req.sink_pacs) {
        new_req.sink_pacs = std::vector<types::acs_ac_record>{};
      }
      for (auto const& [_, pac_char] : device->snk_pacs_) {
        for (auto const& pac_record : pac_char) {
          new_req.sink_pacs->push_back(pac_record);
        }
      }
    }

    // Push source PACs if there are some source requirements
    if (has_location.source && !device->src_pacs_.empty()) {
      if (!new_req.source_pacs) {
        new_req.source_pacs = std::vector<types::acs_ac_record>{};
      }
      for (auto& [_, pac_char] : device->src_pacs_) {
        for (auto const& pac_record : pac_char) {
          new_req.source_pacs->push_back(pac_record);
        }
      }
    }
  }

  return new_req;
}

bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache(
    LeAudioContextType ctx_type) const {
  CodecManager::UnicastConfigurationRequirements requirements = {
      .audio_context_type = ctx_type};

  auto requirements = GetAudioSetConfigurationRequirements(ctx_type);
  auto new_conf = CodecManager::GetInstance()->GetCodecConfig(
      requirements,
      std::bind(&LeAudioDeviceGroup::FindFirstSupportedConfiguration, this,
@@ -1375,10 +1455,12 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
                   static_cast<int>(ase_cnt - active_ase_cnt));

      for (auto const& ent : ase_confs) {
        // Verify PACS only if this is transparent LTV format
        auto const& pacs = (direction == types::kLeAudioDirectionSink)
                               ? device->snk_pacs_
                               : device->src_pacs_;
        if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
        if (utils::IsCodecUsingLtvFormat(ent.codec.id) &&
            !utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
          log::debug(
              "Insufficient PAC for {}",
              direction == types::kLeAudioDirectionSink ? "sink" : "source");
+3 −0
Original line number Diff line number Diff line
@@ -211,6 +211,9 @@ class LeAudioDeviceGroup {
  bool UpdateAudioContextAvailability(void);
  bool UpdateAudioSetConfigurationCache(
      types::LeAudioContextType ctx_type) const;
  CodecManager::UnicastConfigurationRequirements
  GetAudioSetConfigurationRequirements(
      types::LeAudioContextType ctx_type) const;
  bool ReloadAudioLocations(void);
  bool ReloadAudioDirections(void);
  std::shared_ptr<const set_configurations::AudioSetConfiguration>
+9 −3
Original line number Diff line number Diff line
@@ -257,6 +257,7 @@ bool LeAudioDevice::ConfigureAses(

  if (!ase) {
    log::error("Unable to find an ASE to configure");
    PrintDebugState();
    return false;
  }

@@ -265,7 +266,8 @@ bool LeAudioDevice::ConfigureAses(
      (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;
  for (size_t i = 0; i < ase_configs.size() && ase; ++i) {
    auto const& ase_cfg = ase_configs.at(i);
    if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
    if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) &&
        !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
      return false;
    }
  }
@@ -283,13 +285,15 @@ bool LeAudioDevice::ConfigureAses(
                             : src_audio_locations_;

  // Before we activate the ASEs, make sure we have the right configuration
  // Check for matching PACs only if we know that the LTV format is being used.
  uint8_t max_required_ase_per_dev = ase_configs.size() / num_of_devices +
                                     (ase_configs.size() % num_of_devices);
  int needed_ase = std::min((int)(max_required_ase_per_dev),
                            (int)(ase_configs.size() - active_ases));
  for (int i = 0; i < needed_ase; ++i) {
    auto const& ase_cfg = ase_configs.at(i);
    if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
    if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) &&
        !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
      log::error("No matching PAC found. Stop the activation.");
      return false;
    }
@@ -331,6 +335,7 @@ bool LeAudioDevice::ConfigureAses(
      ase->target_latency = ase_cfg.qos.target_latency;
      ase->codec_id = ase_cfg.codec.id;
      ase->codec_config = ase_cfg.codec.params;
      ase->vendor_codec_config = ase_cfg.codec.vendor_params;
      ase->channel_count = ase_cfg.codec.channel_count_per_iso_stream;

      /* Let's choose audio channel allocation if not set */
@@ -341,7 +346,8 @@ bool LeAudioDevice::ConfigureAses(

      /* Get default value if no requirement for specific frame blocks per sdu
       */
      if (!ase->codec_config.Find(
      if (utils::IsCodecUsingLtvFormat(ase->codec_id) &&
          !ase->codec_config.Find(
              codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu)) {
        ase->codec_config.Add(
            codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
+391 −97

File changed.

Preview size limit exceeded, changes collapsed.

Loading