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

Commit 49e9a83f authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Improve group config strategy recalculation

Currently the group strategy is always recalculated from the PAC record
LTV map entries. This change adds the strategy caching to avoid recalculations
on each GetGroupStrategy call, and potentially allows for other strategy
recalculation methods, not related to AudioChannelCounts LTV type, which
may be absent in the vendor codec PAC records.

- recalculate group configuration strategy only when the cached
  value is invalidated
- invalidate the group configuration strategy only when needed
  (group configuration is changed)
- properly name the helper function (it is Sink only) to avoid
  misunderstanding and misuse

Bug: 308427707
Test: atest bluetooth_le_audio_test bluetooth_le_audio_client_test
Flag: EXEMPT; refactor for the multi-codec feature, verified with unit tests
Change-Id: Ic72f7d84eabf5e68e6abbb946be2e6fb31ca03d7
parent 07d6b997
Loading
Loading
Loading
Loading
+8 −17
Original line number Diff line number Diff line
@@ -552,6 +552,7 @@ class LeAudioClientImpl : public LeAudioClient {
    if (group_conf_changed) {
      /* All the configurations should be recalculated for the new conditions */
      group->InvalidateCachedConfigurations();
      group->InvalidateGroupStrategy();
      callbacks_->OnAudioConf(group->audio_directions_, group->group_id_,
                              group->snk_audio_locations_.to_ulong(),
                              group->src_audio_locations_.to_ulong(),
@@ -559,13 +560,6 @@ class LeAudioClientImpl : public LeAudioClient {
    }
  }

  void UpdateLocationsAndContextsAvailability(int group_id) {
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    if (group) {
      UpdateLocationsAndContextsAvailability(group);
    }
  }

  void SuspendedForReconfiguration() {
    if (audio_sender_state_ > AudioState::IDLE) {
      LeAudioLogHistory::Get()->AddLogHistory(
@@ -643,7 +637,6 @@ class LeAudioClientImpl : public LeAudioClient {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
    LeAudioDeviceGroup* new_group;
    LeAudioDeviceGroup* old_group = nullptr;
    int old_group_id = bluetooth::groups::kGroupUnknown;

    if (!leAudioDevice) {
      /* TODO This part possible to remove as this is to handle adding device to
@@ -661,7 +654,6 @@ class LeAudioClientImpl : public LeAudioClient {
    } else {
      if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
        old_group = aseGroups_.FindById(leAudioDevice->group_id_);
        old_group_id = old_group->group_id_;
      }
    }

@@ -709,11 +701,6 @@ class LeAudioClientImpl : public LeAudioClient {
    if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID)
      AseInitialStateReadRequest(leAudioDevice);

    /* Group may be destroyed once moved its last node to new group, so don't
     * use `old_group` pointer anymore.
     * Removing node from group requires updating group context availability */
    UpdateLocationsAndContextsAvailability(old_group_id);

    if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
      UpdateLocationsAndContextsAvailability(new_group);
    }
@@ -1782,6 +1769,8 @@ class LeAudioClientImpl : public LeAudioClient {
       * PACs are updated.
       */
      if (group) {
        /* Changes in PAC record channel counts may change the strategy */
        group->InvalidateGroupStrategy();
        group->InvalidateCachedConfigurations();
      }
      if (notify) {
@@ -1808,6 +1797,8 @@ class LeAudioClientImpl : public LeAudioClient {
       * PACs are updated.
       */
      if (group) {
        /* Changes in PAC record channel counts may change the strategy */
        group->InvalidateGroupStrategy();
        group->InvalidateCachedConfigurations();
      }
      if (notify) {
@@ -1844,7 +1835,7 @@ class LeAudioClientImpl : public LeAudioClient {
            leAudioDevice->snk_audio_locations_.to_ulong(),
            leAudioDevice->src_audio_locations_.to_ulong());
        if (group && group->IsReleasingOrIdle()) {
          UpdateLocationsAndContextsAvailability(leAudioDevice->group_id_);
          UpdateLocationsAndContextsAvailability(group);
        }
      }
    } else if (hdl == leAudioDevice->src_audio_locations_hdls_.val_hdl) {
@@ -1872,7 +1863,7 @@ class LeAudioClientImpl : public LeAudioClient {
            leAudioDevice->snk_audio_locations_.to_ulong(),
            leAudioDevice->src_audio_locations_.to_ulong());
        if (group && group->IsReleasingOrIdle()) {
          UpdateLocationsAndContextsAvailability(leAudioDevice->group_id_);
          UpdateLocationsAndContextsAvailability(group);
        }
      }
    } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) {
@@ -5673,7 +5664,7 @@ class LeAudioClientImpl : public LeAudioClient {

        if (group) {
          handleAsymmetricPhyForUnicast(group);
          UpdateLocationsAndContextsAvailability(group->group_id_);
          UpdateLocationsAndContextsAvailability(group);
          if (group->IsPendingConfiguration()) {
            SuspendedForReconfiguration();
            auto remote_direction =
+30 −4
Original line number Diff line number Diff line
@@ -895,7 +895,8 @@ uint8_t LeAudioDeviceGroup::CigConfiguration::GetFirstFreeCisId(
  return kInvalidCisId;
}

types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupStrategy(
types::LeAudioConfigurationStrategy
LeAudioDeviceGroup::GetGroupSinkStrategyFromPacs(
    int expected_group_size) const {
  /* Simple strategy picker */
  LOG_DEBUG(" Group %d size %d", group_id_, expected_group_size);
@@ -912,6 +913,7 @@ types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupStrategy(
  }

  auto device = GetFirstDevice();
  /* 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 %d (device %s) is %d",
@@ -924,6 +926,31 @@ types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupStrategy(
  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: %s", [](types::LeAudioConfigurationStrategy
                                                 strategy) {
      switch (strategy) {
        case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
          return "MONO_ONE_CIS_PER_DEVICE";
        case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
          return "STEREO_TWO_CISES_PER_DEVICE";
        case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
          return "STEREO_ONE_CIS_PER_DEVICE";
        default:
          return "RFU";
      }
    }(*strategy_));
  }
  return *strategy_;
}

int LeAudioDeviceGroup::GetAseCount(uint8_t direction) const {
  int result = 0;
  for (const auto& device_iter : leAudioDevices_) {
@@ -958,7 +985,7 @@ void LeAudioDeviceGroup::CigConfiguration::GenerateCisIds(
  int group_size = csis_group_size > 0 ? csis_group_size : 1;

  set_configurations::get_cis_count(
      context_type, group_size, group_->GetGroupStrategy(group_size),
      context_type, group_size, group_->GetGroupSinkStrategy(),
      group_->GetAseCount(types::kLeAudioDirectionSink),
      group_->GetAseCount(types::kLeAudioDirectionSource), cis_count_bidir,
      cis_count_unidir_sink, cis_count_unidir_source);
@@ -1845,8 +1872,7 @@ LeAudioDeviceGroup::FindFirstSupportedConfiguration(
  }

  /* Filter out device set for each end every scenario */

  auto required_snk_strategy = GetGroupStrategy(Size());
  auto required_snk_strategy = GetGroupSinkStrategy();
  for (const auto& conf : *confs) {
    if (IsAudioSetConfigurationSupported(conf, context_type,
                                         required_snk_strategy)) {
+7 −1
Original line number Diff line number Diff line
@@ -73,6 +73,10 @@ class LeAudioDeviceGroup {
    types::CigState state_;
  } cig;

  /* Current configuration strategy - recalculated on demand */
  mutable std::optional<types::LeAudioConfigurationStrategy> strategy_ =
      std::nullopt;

  /* Current audio stream configuration */
  struct stream_configuration stream_conf;
  bool notify_streaming_when_cises_are_ready_;
@@ -151,8 +155,10 @@ class LeAudioDeviceGroup {
  LeAudioDevice* GetFirstDevice(void) const;
  LeAudioDevice* GetFirstDeviceWithAvailableContext(
      types::LeAudioContextType context_type) const;
  bluetooth::le_audio::types::LeAudioConfigurationStrategy GetGroupStrategy(
  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;
  LeAudioDevice* GetNextDevice(LeAudioDevice* leAudioDevice) const;
  LeAudioDevice* GetNextDeviceWithAvailableContext(
+1 −1
Original line number Diff line number Diff line
@@ -758,7 +758,7 @@ class LeAudioAseConfigurationTest : public Test {

          /* Make sure the strategy is the expected one */
          if (entry.direction == kLeAudioDirectionSink &&
              group_->GetGroupStrategy(group_->Size()) != entry.strategy) {
              group_->GetGroupSinkStrategy() != entry.strategy) {
            interesting_configuration = false;
          }

+71 −71

File changed.

Preview size limit exceeded, changes collapsed.