Loading system/bta/le_audio/client.cc +21 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); } } Loading Loading @@ -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)) { Loading Loading @@ -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_); Loading system/bta/le_audio/codec_manager.cc +5 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; } } Loading Loading @@ -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); Loading system/bta/le_audio/codec_manager.h +2 −1 Original line number Diff line number Diff line Loading @@ -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* Loading system/bta/le_audio/codec_manager_test.cc +22 −10 Original line number Diff line number Diff line Loading @@ -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[] = { Loading Loading @@ -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) { Loading Loading @@ -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); Loading system/bta/le_audio/le_audio_client_test.cc +175 −2 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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 Loading
system/bta/le_audio/client.cc +21 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); } } Loading Loading @@ -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)) { Loading Loading @@ -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_); Loading
system/bta/le_audio/codec_manager.cc +5 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; } } Loading Loading @@ -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); Loading
system/bta/le_audio/codec_manager.h +2 −1 Original line number Diff line number Diff line Loading @@ -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* Loading
system/bta/le_audio/codec_manager_test.cc +22 −10 Original line number Diff line number Diff line Loading @@ -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[] = { Loading Loading @@ -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) { Loading Loading @@ -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); Loading
system/bta/le_audio/le_audio_client_test.cc +175 −2 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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