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

Commit f91b34c2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "LeAudio: Fix updating config for wrong audio session" into main

parents 85915d19 fac6c22f
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -3411,8 +3411,9 @@ class LeAudioClientImpl : public LeAudioClient {
              group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource)};
      CodecManager::GetInstance()->UpdateActiveAudioConfig(
          group->stream_conf.stream_params, delays_pair,
          std::bind(&LeAudioSourceAudioHalClient::UpdateAudioConfigToHal,
                    le_audio_source_hal_client_.get(), std::placeholders::_1));
          std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal,
                    weak_factory_.GetWeakPtr(), std::placeholders::_1,
                    std::placeholders::_2));
    }

    return true;
@@ -3481,8 +3482,9 @@ class LeAudioClientImpl : public LeAudioClient {
              group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource)};
      CodecManager::GetInstance()->UpdateActiveAudioConfig(
          group->stream_conf.stream_params, delays_pair,
          std::bind(&LeAudioSourceAudioHalClient::UpdateAudioConfigToHal,
                    le_audio_source_hal_client_.get(), std::placeholders::_1));
          std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal,
                    weak_factory_.GetWeakPtr(), std::placeholders::_1,
                    std::placeholders::_2));
    }
  }

@@ -5031,6 +5033,18 @@ class LeAudioClientImpl : public LeAudioClient {
    }
  }

  void UpdateAudioConfigToHal(const ::le_audio::offload_config& config,
                              uint8_t remote_direction) {
    if ((remote_direction & le_audio::types::kLeAudioDirectionSink) &&
        le_audio_source_hal_client_) {
      le_audio_source_hal_client_->UpdateAudioConfigToHal(config);
    }
    if ((remote_direction & le_audio::types::kLeAudioDirectionSource) &&
        le_audio_sink_hal_client_) {
      le_audio_sink_hal_client_->UpdateAudioConfigToHal(config);
    }
  }

  void NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id) {
    if (!osi_property_get_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall,
                               false)) {
@@ -5103,9 +5117,9 @@ class LeAudioClientImpl : public LeAudioClient {
                  le_audio::types::kLeAudioDirectionSource)};
          CodecManager::GetInstance()->UpdateActiveAudioConfig(
              group->stream_conf.stream_params, delays_pair,
              std::bind(&LeAudioSourceAudioHalClient::UpdateAudioConfigToHal,
                        le_audio_source_hal_client_.get(),
                        std::placeholders::_1));
              std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal,
                        weak_factory_.GetWeakPtr(), std::placeholders::_1,
                        std::placeholders::_2));
          if (reconnection_mode_ ==
              BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS) {
            group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
+5 −3
Original line number Diff line number Diff line
@@ -130,7 +130,8 @@ struct codec_manager_impl {
  void UpdateActiveAudioConfig(
      const types::BidirectionalPair<stream_parameters>& stream_params,
      types::BidirectionalPair<uint16_t> delays_ms,
      std::function<void(const offload_config& config)> update_receiver) {
      std::function<void(const offload_config& config, uint8_t direction)>
          update_receiver) {
    if (GetCodecLocation() != le_audio::types::CodecLocation::ADSP) {
      return;
    }
@@ -161,7 +162,7 @@ struct codec_manager_impl {
              stream_params.get(direction).codec_frames_blocks_per_sdu,
          .peer_delay_ms = delays_ms.get(direction),
      };
      update_receiver(unicast_cfg);
      update_receiver(unicast_cfg, direction);
      stream_map.is_initial = false;
    }
  }
@@ -568,7 +569,8 @@ types::CodecLocation CodecManager::GetCodecLocation(void) const {
void CodecManager::UpdateActiveAudioConfig(
    const types::BidirectionalPair<stream_parameters>& stream_params,
    types::BidirectionalPair<uint16_t> delays_ms,
    std::function<void(const offload_config& config)> update_receiver) {
    std::function<void(const offload_config& config, uint8_t direction)>
        update_receiver) {
  if (pimpl_->IsRunning())
    pimpl_->codec_manager_impl_->UpdateActiveAudioConfig(
        stream_params, delays_ms, update_receiver);
+2 −1
Original line number Diff line number Diff line
@@ -72,7 +72,8 @@ class CodecManager {
  virtual void UpdateActiveAudioConfig(
      const types::BidirectionalPair<stream_parameters>& stream_params,
      types::BidirectionalPair<uint16_t> delays_ms,
      std::function<void(const offload_config& config)> update_receiver);
      std::function<void(const offload_config& config, uint8_t direction)>
          update_receiver);
  virtual const ::le_audio::set_configurations::AudioSetConfigurations*
  GetOffloadCodecConfig(::le_audio::types::LeAudioContextType ctx_type);
  virtual const ::le_audio::broadcast_offload_config*
+22 −10
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ using le_audio::types::kLeAudioDirectionSource;

void osi_property_set_bool(const char* key, bool value);

template <typename T>
T& le_audio::types::BidirectionalPair<T>::get(uint8_t direction) {
  return (direction == le_audio::types::kLeAudioDirectionSink) ? sink : source;
}

std::vector<AudioSetConfiguration> offload_capabilities(0);

const char* test_flags[] = {
@@ -200,17 +205,20 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationAdspDownMix) {
                                        kLeAudioDirectionSource);

  // Verify the offloader config content
  std::vector<offload_config> out_offload_configs;
  types::BidirectionalPair<std::optional<offload_config>> out_offload_configs;
  codec_manager->UpdateActiveAudioConfig(
      stream_params, {.sink = 44, .source = 44},
      [&out_offload_configs](const offload_config& config) {
        out_offload_configs.push_back(config);
      [&out_offload_configs](const offload_config& config, uint8_t direction) {
        out_offload_configs.get(direction) = config;
      });

  // Expect the same configuration for sink and source
  ASSERT_EQ(2lu, out_offload_configs.size());
  for (const auto& config : out_offload_configs) {
  ASSERT_TRUE(out_offload_configs.sink.has_value());
  ASSERT_TRUE(out_offload_configs.source.has_value());
  for (auto direction : {le_audio::types::kLeAudioDirectionSink,
                         le_audio::types::kLeAudioDirectionSource}) {
    uint32_t allocation = 0;
    auto& config = out_offload_configs.get(direction).value();
    ASSERT_EQ(2lu, config.stream_map.size());
    for (const auto& info : config.stream_map) {
      if (info.stream_handle == 96) {
@@ -243,16 +251,20 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationAdspDownMix) {
  // Clear the CIS configuration map (no active CISes).
  codec_manager->ClearCisConfiguration(kLeAudioDirectionSink);
  codec_manager->ClearCisConfiguration(kLeAudioDirectionSource);
  out_offload_configs.clear();
  out_offload_configs.sink = std::nullopt;
  out_offload_configs.source = std::nullopt;
  codec_manager->UpdateActiveAudioConfig(
      stream_params, {.sink = 44, .source = 44},
      [&out_offload_configs](const offload_config& config) {
        out_offload_configs.push_back(config);
      [&out_offload_configs](const offload_config& config, uint8_t direction) {
        out_offload_configs.get(direction) = config;
      });

  // Expect sink & source configurations with empty CIS channel allocation map.
  ASSERT_EQ(2lu, out_offload_configs.size());
  for (const auto& config : out_offload_configs) {
  ASSERT_TRUE(out_offload_configs.sink.has_value());
  ASSERT_TRUE(out_offload_configs.source.has_value());
  for (auto direction : {le_audio::types::kLeAudioDirectionSink,
                         le_audio::types::kLeAudioDirectionSource}) {
    auto& config = out_offload_configs.get(direction).value();
    ASSERT_EQ(0lu, config.stream_map.size());
    ASSERT_EQ(16, config.bits_per_sample);
    ASSERT_EQ(16000u, config.sampling_rate);
+175 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "le_audio_health_status.h"
#include "le_audio_set_configuration_provider.h"
#include "le_audio_types.h"
#include "mock_codec_manager.h"
#include "mock_controller.h"
#include "mock_csis_client.h"
#include "mock_device_groups.h"
@@ -938,6 +939,10 @@ class UnicastTestNoInit : public Test {
              ase.data_path_state =
                  types::AudioStreamDataPathState::DATA_PATH_ESTABLISHED;
              ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
              ase.pres_delay_min = 2500;
              ase.pres_delay_max = 2500;
              ase.preferred_pres_delay_min = 2500;
              ase.preferred_pres_delay_max = 2500;

              uint16_t cis_conn_hdl = ase.cis_conn_hdl;

@@ -1399,19 +1404,35 @@ class UnicastTestNoInit : public Test {
    ON_CALL(*mock_iso_manager_, RegisterCigCallbacks(_))
        .WillByDefault(SaveArg<0>(&cig_callbacks_));

    // Required since we call OnAudioDataReady()
    const auto codec_location = ::le_audio::types::CodecLocation::HOST;

    SetUpMockAudioHal();
    SetUpMockGroups();
    SetUpMockGatt();
    SetUpMockCodecManager(codec_location);

    available_snk_context_types_ = 0xffff;
    available_src_context_types_ = 0xffff;
    supported_snk_context_types_ = 0xffff;
    supported_src_context_types_ = 0xffff;
    le_audio::AudioSetConfigurationProvider::Initialize(
        ::le_audio::types::CodecLocation::ADSP);
    le_audio::AudioSetConfigurationProvider::Initialize(codec_location);
    ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
  }

  void SetUpMockCodecManager(types::CodecLocation location) {
    codec_manager_ = le_audio::CodecManager::GetInstance();
    ASSERT_NE(codec_manager_, nullptr);
    std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
        mock_offloading_preference(0);
    codec_manager_->Start(mock_offloading_preference);
    mock_codec_manager_ = MockCodecManager::GetInstance();
    ASSERT_NE((void*)mock_codec_manager_, (void*)codec_manager_);
    ASSERT_NE(mock_codec_manager_, nullptr);
    ON_CALL(*mock_codec_manager_, GetCodecLocation())
        .WillByDefault(Return(location));
  }

  void TearDown() override {
    if (is_audio_unicast_source_acquired) {
      if (unicast_source_hal_cb_ != nullptr) {
@@ -2493,6 +2514,9 @@ class UnicastTestNoInit : public Test {
  bluetooth::hci::iso_manager::CigCallbacks* cig_callbacks_ = nullptr;
  uint16_t iso_con_counter_ = 1;

  le_audio::CodecManager* codec_manager_;
  MockCodecManager* mock_codec_manager_;

  uint16_t available_snk_context_types_ = 0xffff;
  uint16_t available_src_context_types_ = 0xffff;
  uint16_t supported_snk_context_types_ = 0xffff;
@@ -4732,6 +4756,155 @@ TEST_F(UnicastTest, TwoEarbudsStreaming) {
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
}

TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSource) {
  uint8_t group_size = 2;
  int group_id = 2;

  // Report working CSIS
  ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
      .WillByDefault(Return(true));

  // First earbud
  const RawAddress test_address0 = GetTestAddress(0);
  EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
      .Times(1);
  ConnectCsisDevice(test_address0, 1 /*conn_id*/,
                    codec_spec_conf::kLeAudioLocationFrontLeft,
                    codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
                    group_id, 1 /* rank*/);

  // Second earbud
  const RawAddress test_address1 = GetTestAddress(1);
  EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
      .Times(1);
  ConnectCsisDevice(test_address1, 2 /*conn_id*/,
                    codec_spec_conf::kLeAudioLocationFrontRight,
                    codec_spec_conf::kLeAudioLocationFrontRight, group_size,
                    group_id, 2 /* rank*/, true /*connect_through_csis*/);

  ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
      .WillByDefault(Invoke([&](int group_id) { return 2; }));

  // Set group as active
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
  LeAudioClient::Get()->GroupSetActive(group_id);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Start streaming
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_))
      .Times(1);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_))
      .Times(1);
  EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
      .Times(1)
      .WillOnce(
          [](const types::BidirectionalPair<stream_parameters>& stream_params,
             types::BidirectionalPair<uint16_t> delays_ms,
             std::function<void(const offload_config& config,
                                uint8_t direction)>
                 update_receiver) {
            le_audio::offload_config unicast_cfg;
            if (delays_ms.sink != 0) {
              update_receiver(unicast_cfg,
                              le_audio::types::kLeAudioDirectionSink);
            }
            if (delays_ms.source != 0) {
              update_receiver(unicast_cfg,
                              le_audio::types::kLeAudioDirectionSource);
            }
          });
  StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
                 group_id);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_le_audio_sink_hal_client_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
  Mock::VerifyAndClearExpectations(&mock_codec_manager_);

  // Verify Data transfer on two peer sinks and two sources
  uint8_t cis_count_out = 2;
  uint8_t cis_count_in = 2;
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);

  // Suspend
  LeAudioClient::Get()->GroupSuspend(group_id);
  SyncOnMainLoop();
}

TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSource) {
  uint8_t group_size = 2;
  int group_id = 2;

  // Report working CSIS
  ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
      .WillByDefault(Return(true));

  // First earbud
  const RawAddress test_address0 = GetTestAddress(0);
  EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
      .Times(1);
  ConnectCsisDevice(test_address0, 1 /*conn_id*/,
                    codec_spec_conf::kLeAudioLocationFrontLeft,
                    codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
                    group_id, 1 /* rank*/);

  // Second earbud
  const RawAddress test_address1 = GetTestAddress(1);
  EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
      .Times(1);
  ConnectCsisDevice(test_address1, 2 /*conn_id*/,
                    codec_spec_conf::kLeAudioLocationFrontRight,
                    codec_spec_conf::kLeAudioLocationFrontRight, group_size,
                    group_id, 2 /* rank*/, true /*connect_through_csis*/);

  ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
      .WillByDefault(Invoke([&](int group_id) { return 2; }));

  // Set group as active
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
  LeAudioClient::Get()->GroupSetActive(group_id);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Start streaming
  EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_))
      .Times(1);
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_))
      .Times(0);
  EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
      .Times(1)
      .WillOnce(
          [](const types::BidirectionalPair<stream_parameters>& stream_params,
             types::BidirectionalPair<uint16_t> delays_ms,
             std::function<void(const offload_config& config,
                                uint8_t direction)>
                 update_receiver) {
            le_audio::offload_config unicast_cfg;
            if (delays_ms.sink != 0) {
              update_receiver(unicast_cfg,
                              le_audio::types::kLeAudioDirectionSink);
            }
            if (delays_ms.source != 0) {
              update_receiver(unicast_cfg,
                              le_audio::types::kLeAudioDirectionSource);
            }
          });
  StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
  Mock::VerifyAndClearExpectations(&mock_codec_manager_);

  // Verify Data transfer on two peer sinks and no source
  uint8_t cis_count_out = 2;
  uint8_t cis_count_in = 0;
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);

  // Suspend
  LeAudioClient::Get()->GroupSuspend(group_id);
  SyncOnMainLoop();
}

TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
  uint8_t group_size = 2;
  int group_id = 2;
Loading