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

Commit 10ae78fb authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Move the SWB support toggle handling to Codec Manager

The json config provider is just the data source, from where the
configurations are loaded at the stack initalization. SWB toggle handling
should be handled by the higher level CodecManager at run time, to filter
out the SWB configuration when support is not currently enabled.

This simplifies the SWB filtering and hides it inside the CodecManager.
This is aligned with the expected behavior for the AIDL configuration provider.

Bug: 308428860
Test: atest bluetooth_le_audio_test bluetooth_le_audio_client_test  bluetooth_test_broadcaster bluetooth_test_broadcaster_state_machine bluetooth_le_audio_codec_manager_test
Flag: EXEMPT; no functional change - moved functionality verified with the unit tests
Change-Id: I96d0deb2f910a68f55ac85c214f7e0875df3d2df
parent 64ecda51
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 = {
+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,
+300 −5

File changed.

Preview size limit exceeded, changes collapsed.