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

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

LeAudio: Decouple helper functions

This extracts, move or strips the argument lists of certain functions
from the redundant parameters in order to reduce the dependencies,
and to reduce the already inflated device and group class interfaces
at least a little bit. It will also allow us later to use the extracted
utility functions outside these classes (e.g. by the Codec Manager).

Bug: 308428860
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
Flag: EXEMPT; mechanical refactor; no functional change, confirmed with unit tests
Change-Id: I1482180ea2fd8a8f96f0047e1624b50bb108321f
parent 9bfd8965
Loading
Loading
Loading
Loading
+27 −10
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ using bluetooth::le_audio::types::kLeAudioContextAllRemoteSinkOnly;
using bluetooth::le_audio::types::kLeAudioContextAllRemoteSource;
using bluetooth::le_audio::types::kLeAudioContextAllTypesArray;
using bluetooth::le_audio::types::LeAudioContextType;
using bluetooth::le_audio::types::PublishedAudioCapabilities;
using bluetooth::le_audio::utils::GetAudioContextsFromSinkMetadata;
using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata;

@@ -3152,17 +3153,33 @@ class LeAudioClientImpl : public LeAudioClient {
    auto num_of_devices =
        get_num_of_devices_in_configuration(stream_conf->conf.get());

    if (num_of_devices < group->NumOfConnected() &&
        !group->IsAudioSetConfigurationSupported(leAudioDevice,
                                                 stream_conf->conf.get())) {
      /* Reconfigure if newly connected member device cannot support current
       * codec configuration */
    if (num_of_devices < group->NumOfConnected()) {
      for (auto direction :
           {bluetooth::le_audio::types::kLeAudioDirectionSink,
            bluetooth::le_audio::types::kLeAudioDirectionSource}) {
        log::info("Looking for requirements: {} - {}", stream_conf->conf->name,
                  ((direction == 1 ? "snk" : "src")));
        const auto& pacs =
            (direction == bluetooth::le_audio::types::kLeAudioDirectionSink)
                ? leAudioDevice->snk_pacs_
                : leAudioDevice->src_pacs_;
        for (const auto& ent : stream_conf->conf->confs.get(direction)) {
          if (!bluetooth::le_audio::utils::GetConfigurationSupportedPac(
                  pacs, ent.codec)) {
            log::info("Configuration is not supported by device %s",
                      ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));

            /* Reconfigure if newly connected member device cannot support
             * current codec configuration */
            group->SetPendingConfiguration();
            groupStateMachine_->StopStream(group);
            stream_setup_start_timestamp_ =
                bluetooth::common::time_get_os_boottime_us();
            return;
          }
        }
      }
    }

    /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
    auto ccid_contexts = group->GetMetadataContexts();
+41 −65
Original line number Diff line number Diff line
@@ -910,9 +910,14 @@ uint8_t LeAudioDeviceGroup::CigConfiguration::GetFirstFreeCisId(
  return kInvalidCisId;
}

types::LeAudioConfigurationStrategy
LeAudioDeviceGroup::GetGroupSinkStrategyFromPacs(
    int expected_group_size) const {
types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupSinkStrategy()
    const {
  /* Update the strategy if not set yet or was invalidated */
  if (!strategy_) {
    /* Choose the group configuration strategy based on PAC records */
    strategy_ = [this]() {
      int expected_group_size = Size();

      /* Simple strategy picker */
      log::debug("Group {} size {}", group_id_, expected_group_size);
      if (expected_group_size > 1) {
@@ -928,7 +933,8 @@ LeAudioDeviceGroup::GetGroupSinkStrategyFromPacs(
      }

      auto device = GetFirstDevice();
  /* Note: Currently, the audio channel counts LTV is only mandatory for LC3. */
      /* Note: Currently, the audio channel counts LTV is only mandatory for
       * LC3. */
      auto channel_count_bitmap =
          device->GetSupportedAudioChannelCounts(types::kLeAudioDirectionSink);
      log::debug("Supported channel counts for group {} (device {}) is {}",
@@ -939,15 +945,7 @@ LeAudioDeviceGroup::GetGroupSinkStrategyFromPacs(
      }

      return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE;
}

types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupSinkStrategy()
    const {
  /* Update the strategy if not set yet or was invalidated */
  if (!strategy_) {
    int expected_group_size = Size();
    /* Choose the group configuration strategy based on PAC records */
    strategy_ = GetGroupSinkStrategyFromPacs(expected_group_size);
    }();

    log::info(
        "Group strategy set to: {}",
@@ -1291,9 +1289,8 @@ bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,
 * (no matter on the ASE state) and for given context type
 */
bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
    const set_configurations::AudioSetConfiguration* audio_set_conf,
    const CodecManager::UnicastConfigurationRequirements& requirements,
    types::LeAudioConfigurationStrategy required_snk_strategy) const {
    const set_configurations::AudioSetConfiguration* audio_set_conf) const {
  /* When at least one device supports the configuration context, configure
   * for these devices only. Otherwise configure for all devices - we will
   * not put this context into the metadata if not supported.
@@ -1317,6 +1314,7 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
   *    scenarion will be covered.
   * 3) ASEs should be filled according to performance profile.
   */
  auto required_snk_strategy = GetGroupSinkStrategy();
  for (auto direction :
       {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) {
    log::debug("Looking for configuration: {} - {}", audio_set_conf->name,
@@ -1374,8 +1372,13 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
                   static_cast<int>(ase_cnt - active_ase_cnt));

      for (auto const& ent : ase_confs) {
        if (!device->GetCodecConfigurationSupportedPac(direction, ent.codec)) {
          log::debug("Insufficient PAC");
        auto const& pacs = (direction == types::kLeAudioDirectionSink)
                               ? device->snk_pacs_
                               : device->src_pacs_;
        if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
          log::debug(
              "Insufficient PAC for {}",
              (direction == types::kLeAudioDirectionSink ? "sink" : "source"));
          continue;
        }

@@ -1833,31 +1836,6 @@ bool LeAudioDeviceGroup::IsConfiguredForContext(
  return (stream_conf.conf.get() == GetActiveConfiguration().get());
}

bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
    LeAudioDevice* leAudioDevice,
    const set_configurations::AudioSetConfiguration* audio_set_conf) const {
  for (auto direction : {le_audio::types::kLeAudioDirectionSink,
                         le_audio::types::kLeAudioDirectionSource}) {
    const auto& confs = audio_set_conf->confs.get(direction);
    if (confs.size() == 0) continue;

    log::info("Looking for requirements: {} - {}", audio_set_conf->name,
              (direction == 1 ? "snk" : "src"));
    for (const auto& ent : confs) {
      if (!leAudioDevice->GetCodecConfigurationSupportedPac(direction,
                                                            ent.codec)) {
        log::info("Configuration is NOT supported by device {}",
                  ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
        return false;
      }
    }
  }

  log::info("Configuration is supported by device {}",
            ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
  return true;
}

const set_configurations::AudioSetConfiguration*
LeAudioDeviceGroup::FindFirstSupportedConfiguration(
    const CodecManager::UnicastConfigurationRequirements& requirements,
@@ -1880,11 +1858,9 @@ LeAudioDeviceGroup::FindFirstSupportedConfiguration(
  }

  /* Filter out device set for each end every scenario */
  auto required_snk_strategy = GetGroupSinkStrategy();
  for (const auto& conf : *confs) {
    log::assert_that(conf != nullptr, "confs should not be null");
    if (IsAudioSetConfigurationSupported(conf, requirements,
                                         required_snk_strategy)) {
    if (IsAudioSetConfigurationSupported(requirements, conf)) {
      log::debug("found: {}", conf->name);
      return conf;
    }
+2 −7
Original line number Diff line number Diff line
@@ -164,8 +164,6 @@ class LeAudioDeviceGroup {
  LeAudioDevice* GetFirstDevice(void) const;
  LeAudioDevice* GetFirstDeviceWithAvailableContext(
      types::LeAudioContextType context_type) const;
  types::LeAudioConfigurationStrategy GetGroupSinkStrategyFromPacs(
      int expected_group_size) const;
  types::LeAudioConfigurationStrategy GetGroupSinkStrategy(void) const;
  inline void InvalidateGroupStrategy(void) { strategy_ = std::nullopt; }
  int GetAseCount(uint8_t direction) const;
@@ -229,9 +227,6 @@ class LeAudioDeviceGroup {
  void Disable(int gatt_if);
  void Enable(int gatt_if, tBTM_BLE_CONN_TYPE reconnection_mode);
  bool IsEnabled(void) const;
  bool IsAudioSetConfigurationSupported(
      LeAudioDevice* leAudioDevice,
      const set_configurations::AudioSetConfiguration* audio_set_conf) const;
  LeAudioCodecConfiguration GetAudioSessionCodecConfigForDirection(
      types::LeAudioContextType group_context_type, uint8_t direction) const;
  bool HasCodecConfigurationForDirection(
@@ -412,9 +407,9 @@ class LeAudioDeviceGroup {
          metadata_context_types,
      const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists);
  bool IsAudioSetConfigurationSupported(
      const set_configurations::AudioSetConfiguration* audio_set_configuration,
      const CodecManager::UnicastConfigurationRequirements& requirements,
      types::LeAudioConfigurationStrategy required_snk_strategy) const;
      const set_configurations::AudioSetConfiguration* audio_set_configuration)
      const;
  uint32_t GetTransportLatencyUs(uint8_t direction) const;
  bool IsCisPartOfCurrentStream(uint16_t cis_conn_hdl) const;

+37 −32
Original line number Diff line number Diff line
@@ -214,6 +214,32 @@ uint32_t PickAudioLocation(types::LeAudioConfigurationStrategy strategy,
  return left_device_loc ? left_device_loc : right_device_loc;
}

bool LeAudioDevice::IsAudioSetConfigurationSupported(
    const set_configurations::AudioSetConfiguration* audio_set_conf) const {
  for (auto direction : {le_audio::types::kLeAudioDirectionSink,
                         le_audio::types::kLeAudioDirectionSource}) {
    const auto& confs = audio_set_conf->confs.get(direction);
    if (confs.size() == 0) continue;

    log::info("Looking for requirements: {} - {}", audio_set_conf->name,
              (direction == 1 ? "snk" : "src"));

    auto const& pacs =
        (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;
    for (const auto& ent : confs) {
      if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
        log::info("Configuration is NOT supported by device {}",
                  ADDRESS_TO_LOGGABLE_CSTR(address_));
        return false;
      }
    }
  }

  log::info("Configuration is supported by device {}",
            ADDRESS_TO_LOGGABLE_CSTR(address_));
  return true;
}

bool LeAudioDevice::ConfigureAses(
    const set_configurations::AudioSetConfiguration* audio_set_conf,
    uint8_t direction, LeAudioContextType context_type,
@@ -252,11 +278,18 @@ bool LeAudioDevice::ConfigureAses(
  uint8_t max_required_ase_per_dev =
      ents.size() / device_cnt + (ents.size() % device_cnt);

  auto pac = GetCodecConfigurationSupportedPac(direction, ents[0].codec);
  if (!pac) return false;
  auto const& pacs =
      (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;

  // Before we activate the ASEs, make sure we have the right configuration
  int needed_ase = std::min((int)(max_required_ase_per_dev),
                            (int)(ents.size() - active_ases));
  for (int i = 0; i < needed_ase; ++i) {
    auto const& ase_cfg = ents.at(i);
    if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
      return false;
    }
  }

  AudioLocations audio_locations = 0;

@@ -299,7 +332,8 @@ bool LeAudioDevice::ConfigureAses(
              codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu)) {
        ase->codec_config.Add(
            codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
            GetMaxCodecFramesPerSduFromPac(pac));
            GetMaxCodecFramesPerSduFromPac(
                utils::GetConfigurationSupportedPac(pacs, ents.at(i).codec)));
      }

      /* Recalculate Max SDU size from the Core codec config */
@@ -747,35 +781,6 @@ uint8_t LeAudioDevice::GetSupportedAudioChannelCounts(uint8_t direction) const {
  return 0;
}

const struct types::acs_ac_record*
LeAudioDevice::GetCodecConfigurationSupportedPac(
    uint8_t direction, const CodecConfigSetting& codec_capability_setting) {
  auto& pacs =
      direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;

  if (pacs.size() == 0) {
    log::error("missing PAC for direction {}", direction);
    return nullptr;
  }

  /* TODO: Validate channel locations */

  for (const auto& pac_tuple : pacs) {
    /* Get PAC records from tuple as second element from tuple */
    auto& pac_recs = std::get<1>(pac_tuple);

    for (const auto& pac : pac_recs) {
      if (!IsCodecConfigSettingSupported(pac, codec_capability_setting))
        continue;

      return &pac;
    };
  }

  /* Doesn't match required configuration with any PAC */
  return nullptr;
}

/**
 * Returns supported PHY's bitfield
 */
+2 −3
Original line number Diff line number Diff line
@@ -173,12 +173,11 @@ class LeAudioDevice {
  bool IsReadyToSuspendStream(void);
  bool HaveAllActiveAsesCisEst(void) const;
  bool HaveAnyCisConnected(void);
  const struct types::acs_ac_record* GetCodecConfigurationSupportedPac(
      uint8_t direction,
      const set_configurations::CodecConfigSetting& codec_capability_setting);
  uint8_t GetSupportedAudioChannelCounts(uint8_t direction) const;
  uint8_t GetPhyBitmask(void) const;
  uint8_t GetPreferredPhyBitmask(uint8_t preferred_phy) const;
  bool IsAudioSetConfigurationSupported(
      const set_configurations::AudioSetConfiguration* audio_set_conf) const;
  bool ConfigureAses(
      const set_configurations::AudioSetConfiguration* audio_set_conf,
      uint8_t direction, types::LeAudioContextType context_type,
Loading