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

Commit 79ef6b42 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski Committed by Gerrit Code Review
Browse files

Merge changes I96d0deb2,Ie12c0331 into main

* changes:
  LeAudio: Move the SWB support toggle handling to Codec Manager
  LeAudio: Minor NumOfConnected() method cleanup
parents 8752dbc5 10ae78fb
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ struct codec_manager_impl {
    }
  }

  const AudioSetConfigurations* GetSupportedCodecConfigurations(
  AudioSetConfigurations GetSupportedCodecConfigurations(
      const CodecManager::UnicastConfigurationRequirements& requirements)
      const {
    if (GetCodecLocation() == le_audio::types::CodecLocation::ADSP) {
@@ -215,14 +215,14 @@ struct codec_manager_impl {
      // doesn't support.
      return context_type_offload_config_map_.count(
                 requirements.audio_context_type)
                 ? &context_type_offload_config_map_.at(
                 ? context_type_offload_config_map_.at(
                       requirements.audio_context_type)
                 : nullptr;
                 : AudioSetConfigurations();
    }

    log::verbose("Get software config for the context type: {}",
                 (int)requirements.audio_context_type);
    return AudioSetConfigurationProvider::Get()->GetConfigurations(
    return *AudioSetConfigurationProvider::Get()->GetConfigurations(
        requirements.audio_context_type);
  }

@@ -248,18 +248,31 @@ struct codec_manager_impl {
      const CodecManager::UnicastConfigurationRequirements& requirements,
      CodecManager::UnicastConfigurationVerifier verifier) {
    auto configs = GetSupportedCodecConfigurations(requirements);
    if (configs == nullptr) {
    if (configs.empty()) {
      log::error("No valid configuration matching the requirements: {}",
                 requirements);
      PrintDebugState();
      return nullptr;
    }

    // Remove the dual bidir SWB config if not supported
    if (!IsDualBiDirSwbSupported()) {
      configs.erase(
          std::remove_if(configs.begin(), configs.end(),
                         [](auto const& el) {
                           if (el->confs.source.empty()) return false;
                           return AudioSetConfigurationProvider::Get()
                               ->CheckConfigurationIsDualBiDirSwb(*el);
                         }),
          configs.end());
    }

    // Note: For the only supported right now legacy software configuration
    //       provider, we use the device group logic to match the proper
    //       configuration with group capabilities. Note that this path only
    //       supports the LC3 codec format. For the multicodec support we should
    //       rely on the configuration matcher behind the AIDL interface.
    auto conf = verifier(requirements, configs);
    auto conf = verifier(requirements, &configs);
    return conf ? std::make_unique<AudioSetConfiguration>(*conf) : nullptr;
  }

+202 −4
Original line number Diff line number Diff line
@@ -184,6 +184,8 @@ static constexpr char kPropLeAudioOffloadSupported[] =
    "ro.bluetooth.leaudio_offload.supported";
static constexpr char kPropLeAudioOffloadDisabled[] =
    "persist.bluetooth.leaudio_offload.disabled";
static constexpr char kPropLeAudioBidirSwbSupported[] =
    "bluetooth.leaudio.dual_bidirection_swb.supported";

class CodecManagerTestBase : public Test {
 public:
@@ -218,6 +220,23 @@ class CodecManagerTestAdsp : public CodecManagerTestBase {
    osi_property_set_bool(kPropLeAudioOffloadSupported, true);
    osi_property_set_bool(kPropLeAudioOffloadDisabled, false);

    // Allow for bidir SWB configurations
    osi_property_set_bool(kPropLeAudioBidirSwbSupported, true);

    CodecManagerTestBase::SetUp();
  }
};

class CodecManagerTestAdspNoSwb : public CodecManagerTestBase {
 public:
  virtual void SetUp() override {
    // Enable the HW offloader
    osi_property_set_bool(kPropLeAudioOffloadSupported, true);
    osi_property_set_bool(kPropLeAudioOffloadDisabled, false);

    // Allow for bidir SWB configurations
    osi_property_set_bool(kPropLeAudioBidirSwbSupported, false);

    CodecManagerTestBase::SetUp();
  }
};
@@ -541,6 +560,23 @@ class CodecManagerTestHost : public CodecManagerTestBase {
    osi_property_set_bool(kPropLeAudioOffloadSupported, false);
    osi_property_set_bool(kPropLeAudioOffloadDisabled, false);

    // Allow for bidir SWB configurations
    osi_property_set_bool(kPropLeAudioBidirSwbSupported, true);

    CodecManagerTestBase::SetUp();
  }
};

class CodecManagerTestHostNoSwb : public CodecManagerTestBase {
 public:
  virtual void SetUp() override {
    // Enable the HW offloader
    osi_property_set_bool(kPropLeAudioOffloadSupported, true);
    osi_property_set_bool(kPropLeAudioOffloadDisabled, false);

    // Do not allow for bidir SWB configurations
    osi_property_set_bool(kPropLeAudioBidirSwbSupported, false);

    CodecManagerTestBase::SetUp();
  }
};
@@ -582,10 +618,6 @@ TEST_F(CodecManagerTestHost, test_non_bidir_swb) {
          {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
  codec_manager->Start(offloading_preference);

  std::vector<AudioSetConfiguration> offload_capabilities = {
      {.confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2)},
                 .source = {}}}};

  // NON-SWB configs
  ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb(
      {.confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
@@ -705,6 +737,172 @@ TEST_F(CodecManagerTestHost, test_bidir_swb) {
       .topology_info = {{{1, 1}}}}));
}

TEST_F(CodecManagerTestHost, test_dual_bidir_swb_supported) {
  const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
      offloading_preference = {
          {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
  codec_manager->Start(offloading_preference);

  int num_of_dual_bidir_swb_configs = 0;
  for (auto context : types::kLeAudioContextAllTypesArray) {
    bool got_null_cfgs_container = false;
    auto ptr = codec_manager->GetCodecConfig(
        {.audio_context_type = context},
        [&](const CodecManager::UnicastConfigurationRequirements& requirements,
            const set_configurations::AudioSetConfigurations* confs)
            -> const set_configurations::AudioSetConfiguration* {
          if (confs == nullptr) {
            got_null_cfgs_container = true;
          } else {
            num_of_dual_bidir_swb_configs += std::count_if(
                confs->begin(), confs->end(), [&](auto const& cfg) {
                  bool is_bidir = AudioSetConfigurationProvider::Get()
                                      ->CheckConfigurationIsDualBiDirSwb(*cfg);
                  return AudioSetConfigurationProvider::Get()
                      ->CheckConfigurationIsDualBiDirSwb(*cfg);
                });
          }
          // In this case the chosen configuration doesn't matter - select none
          return nullptr;
        });
    ASSERT_FALSE(got_null_cfgs_container);
  }

  // Make sure some dual bidir SWB configs were returned
  ASSERT_NE(0, num_of_dual_bidir_swb_configs);
}

TEST_F(CodecManagerTestAdsp, test_dual_bidir_swb_supported) {
  // Set the offloader capabilities
  std::vector<AudioSetConfiguration> offload_capabilities = {
      {.name = "Test_Bidir_SWB_Config_No_Dev_lc3_32_2",
       .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2)},
                 .source = {set_configurations::AseConfiguration(lc3_32_2)}},
       .topology_info = {{{0, 0}}}},
      {
          .name = "Test_Bidir_Non_SWB_Config_No_Dev_lc3_16_2",
          .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2)},
                    .source = {set_configurations::AseConfiguration(lc3_16_2)}},
          .topology_info = {{{0, 0}}},
      },
  };
  set_mock_offload_capabilities(offload_capabilities);

  const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
      offloading_preference = {
          {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
  codec_manager->Start(offloading_preference);

  int num_of_dual_bidir_swb_configs = 0;
  for (auto context : types::kLeAudioContextAllTypesArray) {
    bool got_null_cfgs_container = false;
    auto ptr = codec_manager->GetCodecConfig(
        {.audio_context_type = context},
        [&](const CodecManager::UnicastConfigurationRequirements& requirements,
            const set_configurations::AudioSetConfigurations* confs)
            -> const set_configurations::AudioSetConfiguration* {
          if (confs == nullptr) {
            got_null_cfgs_container = true;
          } else {
            num_of_dual_bidir_swb_configs += std::count_if(
                confs->begin(), confs->end(), [&](auto const& cfg) {
                  bool is_bidir = AudioSetConfigurationProvider::Get()
                                      ->CheckConfigurationIsDualBiDirSwb(*cfg);
                  return AudioSetConfigurationProvider::Get()
                      ->CheckConfigurationIsDualBiDirSwb(*cfg);
                });
          }
          // In this case the chosen configuration doesn't matter - select none
          return nullptr;
        });
    ASSERT_FALSE(got_null_cfgs_container);
  }

  // Make sure some dual bidir SWB configs were returned
  ASSERT_NE(0, num_of_dual_bidir_swb_configs);
}

TEST_F(CodecManagerTestHostNoSwb, test_dual_bidir_swb_not_supported) {
  const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
      offloading_preference = {
          {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
  codec_manager->Start(offloading_preference);

  int num_of_dual_bidir_swb_configs = 0;
  for (auto context : types::kLeAudioContextAllTypesArray) {
    bool got_null_cfgs_container = false;
    auto ptr = codec_manager->GetCodecConfig(
        {.audio_context_type = context},
        [&](const CodecManager::UnicastConfigurationRequirements& requirements,
            const set_configurations::AudioSetConfigurations* confs)
            -> const set_configurations::AudioSetConfiguration* {
          if (confs == nullptr) {
            got_null_cfgs_container = true;
          } else {
            num_of_dual_bidir_swb_configs += std::count_if(
                confs->begin(), confs->end(), [&](auto const& cfg) {
                  return AudioSetConfigurationProvider::Get()
                      ->CheckConfigurationIsDualBiDirSwb(*cfg);
                });
          }
          // In this case the chosen configuration doesn't matter - select none
          return nullptr;
        });
    ASSERT_FALSE(got_null_cfgs_container);
  }

  // Make sure no dual bidir SWB configs were returned
  ASSERT_EQ(0, num_of_dual_bidir_swb_configs);
}

TEST_F(CodecManagerTestAdspNoSwb, test_dual_bidir_swb_not_supported) {
  // Set the offloader capabilities
  std::vector<AudioSetConfiguration> offload_capabilities = {
      {.name = "Test_Bidir_SWB_Config_No_Dev_lc3_32_2",
       .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2)},
                 .source = {set_configurations::AseConfiguration(lc3_32_2)}},
       .topology_info = {{{0, 0}}}},
      {
          .name = "Test_Bidir_Non_SWB_Config_No_Dev_lc3_16_2",
          .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2)},
                    .source = {set_configurations::AseConfiguration(lc3_16_2)}},
          .topology_info = {{{0, 0}}},
      },
  };
  set_mock_offload_capabilities(offload_capabilities);

  const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
      offloading_preference = {
          {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
  codec_manager->Start(offloading_preference);

  int num_of_dual_bidir_swb_configs = 0;
  for (auto context : types::kLeAudioContextAllTypesArray) {
    bool got_null_cfgs_container = false;
    auto ptr = codec_manager->GetCodecConfig(
        {.audio_context_type = context},
        [&](const CodecManager::UnicastConfigurationRequirements& requirements,
            const set_configurations::AudioSetConfigurations* confs)
            -> const set_configurations::AudioSetConfiguration* {
          if (confs == nullptr) {
            got_null_cfgs_container = true;
          } else {
            num_of_dual_bidir_swb_configs += std::count_if(
                confs->begin(), confs->end(), [&](auto const& cfg) {
                  return AudioSetConfigurationProvider::Get()
                      ->CheckConfigurationIsDualBiDirSwb(*cfg);
                });
          }
          // In this case the chosen configuration doesn't matter - select none
          return nullptr;
        });
    ASSERT_FALSE(got_null_cfgs_container);
  }

  // Make sure no dual bidir SWB configs were returned
  ASSERT_EQ(0, num_of_dual_bidir_swb_configs);
}

TEST_F(CodecManagerTestHost, test_dont_update_broadcast_offloader) {
  const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
      offloading_preference = {
+18 −13
Original line number Diff line number Diff line
@@ -83,23 +83,28 @@ bool LeAudioDeviceGroup::IsAnyDeviceConnected(void) const {

int LeAudioDeviceGroup::Size(void) const { return leAudioDevices_.size(); }

int LeAudioDeviceGroup::NumOfConnected(LeAudioContextType context_type) const {
  if (leAudioDevices_.empty()) return 0;

  bool check_context_type = (context_type != LeAudioContextType::RFU);
  AudioContexts type_set(context_type);

int LeAudioDeviceGroup::NumOfConnected() const {
  /* return number of connected devices from the set*/
  return std::count_if(
      leAudioDevices_.begin(), leAudioDevices_.end(),
      [type_set, check_context_type](auto& iter) {
      leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& iter) {
        auto dev = iter.lock();
        if (dev) {
          if (dev->conn_id_ == GATT_INVALID_CONN_ID) return false;
          if (dev->GetConnectionState() != DeviceConnectState::CONNECTED)
          return (dev->conn_id_ != GATT_INVALID_CONN_ID) &&
                 (dev->GetConnectionState() == DeviceConnectState::CONNECTED);
        }
        return false;
          if (!check_context_type) return true;
          return dev->GetSupportedContexts().test_any(type_set);
      });
}

int LeAudioDeviceGroup::NumOfConnected(LeAudioContextType context_type) const {
  /* return number of connected devices from the set with supported context */
  return std::count_if(
      leAudioDevices_.begin(), leAudioDevices_.end(), [&](auto& iter) {
        auto dev = iter.lock();
        if (dev) {
          return (dev->conn_id_ != GATT_INVALID_CONN_ID) &&
                 (dev->GetConnectionState() == DeviceConnectState::CONNECTED) &&
                 dev->GetSupportedContexts().test(context_type);
        }
        return false;
      });
+2 −2
Original line number Diff line number Diff line
@@ -151,8 +151,8 @@ class LeAudioDeviceGroup {
  bool IsEmpty(void) const;
  bool IsAnyDeviceConnected(void) const;
  int Size(void) const;
  int NumOfConnected(types::LeAudioContextType context_type =
                         types::LeAudioContextType::RFU) const;
  int NumOfConnected() const;
  int NumOfConnected(types::LeAudioContextType context_type) const;
  bool Activate(types::LeAudioContextType context_type,
                const types::BidirectionalPair<types::AudioContexts>&
                    metadata_context_types,
+4 −44
Original line number Diff line number Diff line
@@ -83,8 +83,6 @@ struct AudioSetConfigurationProviderJson {
  static constexpr auto kDefaultScenario = "Media";

  AudioSetConfigurationProviderJson(types::CodecLocation location) {
    dual_bidirection_swb_supported_ = osi_property_get_bool(
        "bluetooth.leaudio.dual_bidirection_swb.supported", false);
    log::assert_that(
        LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios, location),
        ": Unable to load le audio set configuration files.");
@@ -176,11 +174,6 @@ struct AudioSetConfigurationProviderJson {
           AudioSetConfigurations>
      context_configurations_;

  /* property to check if bidirectional sampling frequency >= 32k dual mic is
   * supported or not
   */
  bool dual_bidirection_swb_supported_;

  static const fbs::le_audio::CodecSpecificConfiguration*
  LookupCodecSpecificParam(
      const flatbuffers::Vector<
@@ -239,9 +232,7 @@ struct AudioSetConfigurationProviderJson {

  void SetConfigurationFromFlatSubconfig(
      const fbs::le_audio::AudioSetSubConfiguration* flat_subconfig,
      QosConfigSetting qos, bool& dual_dev_one_chan_stereo_swb,
      bool& single_dev_one_chan_stereo_swb,
      std::vector<AseConfiguration>& subconfigs,
      QosConfigSetting qos, std::vector<AseConfiguration>& subconfigs,
      types::CodecLocation location) {
    auto config = AseConfiguration(
        CodecConfigSettingFromFlat(flat_subconfig->codec_id(),
@@ -267,17 +258,6 @@ struct AudioSetConfigurationProviderJson {
        break;
    }

    // Check for SWB support
    if (config.codec.GetSamplingFrequencyHz() >=
        le_audio::LeAudioCodecConfiguration::kSampleRate32000) {
      if (flat_subconfig->device_cnt() == 2 && flat_subconfig->ase_cnt() == 2) {
        dual_dev_one_chan_stereo_swb |= true;
      }
      if (flat_subconfig->device_cnt() == 1 && flat_subconfig->ase_cnt() == 2) {
        single_dev_one_chan_stereo_swb |= true;
      }
    }

    // Store each ASE configuration
    for (auto i = flat_subconfig->ase_cnt(); i; --i) {
      subconfigs.push_back(std::move(config));
@@ -373,8 +353,6 @@ struct AudioSetConfigurationProviderJson {
    }

    types::BidirectionalPair<std::vector<AseConfiguration>> subconfigs;
    types::BidirectionalPair<bool> dual_dev_one_chan_stereo_swb;
    types::BidirectionalPair<bool> single_dev_one_chan_stereo_swb;
    types::BidirectionalPair<uint8_t> device_cnt;
    types::BidirectionalPair<types::LeAudioConfigurationStrategy> strategy = {
        le_audio::types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE,
@@ -399,8 +377,6 @@ struct AudioSetConfigurationProviderJson {
        device_cnt.get(direction) = subconfig->device_cnt();

        processSubconfig(*subconfig, qos.get(direction),
                         dual_dev_one_chan_stereo_swb.get(direction),
                         single_dev_one_chan_stereo_swb.get(direction),
                         subconfigs.get(direction), location);
      }
    } else {
@@ -412,20 +388,6 @@ struct AudioSetConfigurationProviderJson {
      }
    }

    if (!dual_bidirection_swb_supported_) {
      if ((dual_dev_one_chan_stereo_swb.sink &&
           dual_dev_one_chan_stereo_swb.source) ||
          (single_dev_one_chan_stereo_swb.sink &&
           single_dev_one_chan_stereo_swb.source)) {
        return {
            .name = flat_cfg->name()->c_str(),
            .packing = bluetooth::hci::kIsoCigPackingSequential,
            .confs = {},
            .topology_info = {{device_cnt, strategy}},
        };
      }
    }

    return {
        .name = flat_cfg->name()->c_str(),
        .packing = bluetooth::hci::kIsoCigPackingSequential,
@@ -436,13 +398,11 @@ struct AudioSetConfigurationProviderJson {

  void processSubconfig(
      const fbs::le_audio::AudioSetSubConfiguration& subconfig,
      const QosConfigSetting& qos_setting, bool& dual_dev_one_chan_stereo_swb,
      bool& single_dev_one_chan_stereo_swb,
      const QosConfigSetting& qos_setting,
      std::vector<AseConfiguration>& subconfigs,
      types::CodecLocation location) {
    SetConfigurationFromFlatSubconfig(
        &subconfig, qos_setting, dual_dev_one_chan_stereo_swb,
        single_dev_one_chan_stereo_swb, subconfigs, location);
    SetConfigurationFromFlatSubconfig(&subconfig, qos_setting, subconfigs,
                                      location);
  }

  bool LoadConfigurationsFromFiles(const char* schema_file,
Loading