Loading system/bta/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -807,7 +807,7 @@ cc_test { "liblog", // __android_log_print ], static_libs: [ "bluetooth_flags_c_lib", "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", Loading system/bta/le_audio/codec_manager.cc +64 −8 Original line number Diff line number Diff line Loading @@ -168,9 +168,12 @@ public: bluetooth::le_audio::types::kLeAudioDirectionSource}) { auto& stream_map = offloader_stream_maps.get(direction); if (!stream_map.has_changed && !stream_map.is_initial) { log::warn("unexpected call for direction {}, stream_map.has_changed {}", direction, stream_map.has_changed, stream_map.is_initial); continue; } if (stream_params.get(direction).stream_locations.empty()) { log::warn("unexpected call, stream is empty for direction {}, ", direction); continue; } Loading Loading @@ -675,7 +678,7 @@ public: stream_map.streams_map_current.clear(); } static uint32_t AdjustAllocationForOffloader(uint32_t allocation) { static int AdjustAllocationForOffloader(uint32_t allocation) { if ((allocation & codec_spec_conf::kLeAudioLocationAnyLeft) && (allocation & codec_spec_conf::kLeAudioLocationAnyRight)) { return codec_spec_conf::kLeAudioLocationStereo; Loading @@ -686,20 +689,70 @@ public: if (allocation & codec_spec_conf::kLeAudioLocationAnyRight) { return codec_spec_conf::kLeAudioLocationFrontRight; } return 0; if (allocation == codec_spec_conf::kLeAudioLocationMonoAudio) { return codec_spec_conf::kLeAudioLocationMonoAudio; } return -1; } void UpdateCisConfiguration(const std::vector<struct types::cis>& cises, bool UpdateCisMonoConfiguration(const std::vector<struct types::cis>& cises, uint8_t direction) { if (!LeAudioHalVerifier::SupportsStreamActiveApi() || !com::android::bluetooth::flags::leaudio_mono_location_errata()) { log::error( "SupportsStreamActiveApi() not supported or leaudio_mono_location_errata flag is not " "enabled. Mono stream cannot be enabled"); return false; } auto& stream_map = offloader_stream_maps.get(direction); stream_map.has_changed = true; stream_map.streams_map_target.clear(); stream_map.streams_map_current.clear(); const std::string tag = types::BidirectionalPair<std::string>({.sink = "Sink", .source = "Source"}) .get(direction); constexpr types::BidirectionalPair<types::CisType> cis_types = { .sink = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SINK, .source = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE}; auto cis_type = cis_types.get(direction); for (auto const& cis_entry : cises) { if ((cis_entry.type == types::CisType::CIS_TYPE_BIDIRECTIONAL || cis_entry.type == cis_type) && cis_entry.conn_handle != 0) { bool is_active = cis_entry.addr != RawAddress::kEmpty; log::info("{}: {}, Cis handle {:#x}, allocation {:#x}, active: {}", tag, cis_entry.addr, cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active); stream_map.streams_map_target.emplace_back(stream_map_info( cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active)); stream_map.streams_map_current.emplace_back(stream_map_info( cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active)); } } return true; } bool UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { if (GetCodecLocation() != bluetooth::le_audio::types::CodecLocation::ADSP) { return; return false; } auto available_allocations = AdjustAllocationForOffloader(stream_params.audio_channel_allocation); if (available_allocations == 0) { log::error("There is no CIS connected"); return; if (available_allocations == -1) { log::error("Unsupported allocation {:#x}", stream_params.audio_channel_allocation); return false; } if (available_allocations == codec_spec_conf::kLeAudioLocationMonoAudio) { return UpdateCisMonoConfiguration(cises, direction); } auto& stream_map = offloader_stream_maps.get(direction); Loading Loading @@ -770,6 +823,8 @@ public: stream_map_info(cis_entry.conn_handle, current_allocation, is_active)); } } return true; } private: Loading Loading @@ -1233,12 +1288,13 @@ void CodecManager::UpdateBroadcastConnHandle( } } void CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, bool CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { if (pimpl_->IsRunning()) { return pimpl_->codec_manager_impl_->UpdateCisConfiguration(cises, stream_params, direction); } return false; } void CodecManager::ClearCisConfiguration(uint8_t direction) { Loading system/bta/le_audio/codec_manager.h +1 −1 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public: void Stop(void); virtual types::CodecLocation GetCodecLocation(void) const; virtual bool IsDualBiDirSwbSupported(void) const; virtual void UpdateCisConfiguration(const std::vector<struct types::cis>& cises, virtual bool UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction); virtual void ClearCisConfiguration(uint8_t direction); virtual bool IsUsingCodecExtensibility() const; Loading system/bta/le_audio/codec_manager_test.cc +137 −0 Original line number Diff line number Diff line Loading @@ -269,10 +269,17 @@ static constexpr char kPropLeAudioOffloadDisabled[] = "persist.bluetooth.leaudio static constexpr char kPropLeAudioBidirSwbSupported[] = "bluetooth.leaudio.dual_bidirection_swb.supported"; RawAddress GetTestAddress(uint8_t index) { EXPECT_LT(index, UINT8_MAX); RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}}; return result; } class CodecManagerTestBase : public Test { public: virtual void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); com::android::bluetooth::flags::provider_->reset_flags(); set_mock_offload_capabilities(offload_capabilities_none); bluetooth::legacy::hci::testing::SetMock(legacy_hci_mock_); Loading Loading @@ -506,6 +513,136 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationAdspDownMix) { } } TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) { com::android::bluetooth::flags::provider_->leaudio_mono_location_errata(true); const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> offloading_preference(0); codec_manager->Start(offloading_preference); // Current CIS configuration for two earbuds std::vector<struct types::cis> cises{ { .id = 0x00, .type = types::CisType::CIS_TYPE_BIDIRECTIONAL, .conn_handle = 96, .addr = RawAddress::kEmpty, // Disconnected }, { .id = 0x01, .type = types::CisType::CIS_TYPE_BIDIRECTIONAL, .conn_handle = 97, .addr = GetTestAddress(1), }, }; // Stream parameters types::BidirectionalPair<stream_parameters> stream_params{ .sink = { .sample_frequency_hz = 16000, .frame_duration_us = 10000, .octets_per_codec_frame = 40, .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, .codec_frames_blocks_per_sdu = 1, .num_of_channels = 1, .num_of_devices = 1, .stream_locations = { std::pair<uint16_t, uint32_t>{ 97 /*conn_handle*/, codec_spec_conf::kLeAudioLocationMonoAudio}, }, }, .source = { .sample_frequency_hz = 16000, .frame_duration_us = 10000, .octets_per_codec_frame = 40, .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, .codec_frames_blocks_per_sdu = 1, .num_of_channels = 1, .num_of_devices = 1, { std::pair<uint16_t, uint32_t>{ 97 /*conn_handle*/, codec_spec_conf::kLeAudioLocationMonoAudio}, }, }, }; ASSERT_TRUE( codec_manager->UpdateCisConfiguration(cises, stream_params.sink, kLeAudioDirectionSink)); ASSERT_TRUE(codec_manager->UpdateCisConfiguration(cises, stream_params.source, kLeAudioDirectionSource)); // Verify the offloader config content 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, uint8_t direction) { out_offload_configs.get(direction) = config; }); // Expect the same configuration for sink and source ASSERT_TRUE(out_offload_configs.sink.has_value()); ASSERT_TRUE(out_offload_configs.source.has_value()); for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink, bluetooth::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) { ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); // The disconnected should be inactive ASSERT_FALSE(info.is_stream_active); } else if (info.stream_handle == 97) { ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); // The connected should be active ASSERT_TRUE(info.is_stream_active); } else { ASSERT_EQ(97, info.stream_handle); } allocation |= info.audio_channel_allocation; } ASSERT_EQ(16, config.bits_per_sample); ASSERT_EQ(16000u, config.sampling_rate); ASSERT_EQ(10000u, config.frame_duration); ASSERT_EQ(40u, config.octets_per_frame); ASSERT_EQ(1, config.blocks_per_sdu); ASSERT_EQ(44, config.peer_delay_ms); ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, allocation); } // Clear the CIS configuration map (no active CISes). codec_manager->ClearCisConfiguration(kLeAudioDirectionSink); codec_manager->ClearCisConfiguration(kLeAudioDirectionSource); 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, uint8_t direction) { out_offload_configs.get(direction) = config; }); // Expect sink & source configurations with empty CIS channel allocation map. ASSERT_TRUE(out_offload_configs.sink.has_value()); ASSERT_TRUE(out_offload_configs.source.has_value()); for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink, bluetooth::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); ASSERT_EQ(10000u, config.frame_duration); ASSERT_EQ(40u, config.octets_per_frame); ASSERT_EQ(1, config.blocks_per_sdu); ASSERT_EQ(44, config.peer_delay_ms); } } TEST_F(CodecManagerTestAdsp, test_capabilities_none) { const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> offloading_preference(0); codec_manager->Start(offloading_preference); Loading system/bta/le_audio/mock_codec_manager.cc +2 −1 Original line number Diff line number Diff line Loading @@ -160,12 +160,13 @@ void CodecManager::Stop() { mock_codec_manager_pimpl_ = nullptr; } void CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, bool CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { if (pimpl_) { return pimpl_->UpdateCisConfiguration(cises, stream_params, direction); } return false; } void CodecManager::ClearCisConfiguration(uint8_t direction) { Loading Loading
system/bta/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -807,7 +807,7 @@ cc_test { "liblog", // __android_log_print ], static_libs: [ "bluetooth_flags_c_lib", "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", Loading
system/bta/le_audio/codec_manager.cc +64 −8 Original line number Diff line number Diff line Loading @@ -168,9 +168,12 @@ public: bluetooth::le_audio::types::kLeAudioDirectionSource}) { auto& stream_map = offloader_stream_maps.get(direction); if (!stream_map.has_changed && !stream_map.is_initial) { log::warn("unexpected call for direction {}, stream_map.has_changed {}", direction, stream_map.has_changed, stream_map.is_initial); continue; } if (stream_params.get(direction).stream_locations.empty()) { log::warn("unexpected call, stream is empty for direction {}, ", direction); continue; } Loading Loading @@ -675,7 +678,7 @@ public: stream_map.streams_map_current.clear(); } static uint32_t AdjustAllocationForOffloader(uint32_t allocation) { static int AdjustAllocationForOffloader(uint32_t allocation) { if ((allocation & codec_spec_conf::kLeAudioLocationAnyLeft) && (allocation & codec_spec_conf::kLeAudioLocationAnyRight)) { return codec_spec_conf::kLeAudioLocationStereo; Loading @@ -686,20 +689,70 @@ public: if (allocation & codec_spec_conf::kLeAudioLocationAnyRight) { return codec_spec_conf::kLeAudioLocationFrontRight; } return 0; if (allocation == codec_spec_conf::kLeAudioLocationMonoAudio) { return codec_spec_conf::kLeAudioLocationMonoAudio; } return -1; } void UpdateCisConfiguration(const std::vector<struct types::cis>& cises, bool UpdateCisMonoConfiguration(const std::vector<struct types::cis>& cises, uint8_t direction) { if (!LeAudioHalVerifier::SupportsStreamActiveApi() || !com::android::bluetooth::flags::leaudio_mono_location_errata()) { log::error( "SupportsStreamActiveApi() not supported or leaudio_mono_location_errata flag is not " "enabled. Mono stream cannot be enabled"); return false; } auto& stream_map = offloader_stream_maps.get(direction); stream_map.has_changed = true; stream_map.streams_map_target.clear(); stream_map.streams_map_current.clear(); const std::string tag = types::BidirectionalPair<std::string>({.sink = "Sink", .source = "Source"}) .get(direction); constexpr types::BidirectionalPair<types::CisType> cis_types = { .sink = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SINK, .source = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE}; auto cis_type = cis_types.get(direction); for (auto const& cis_entry : cises) { if ((cis_entry.type == types::CisType::CIS_TYPE_BIDIRECTIONAL || cis_entry.type == cis_type) && cis_entry.conn_handle != 0) { bool is_active = cis_entry.addr != RawAddress::kEmpty; log::info("{}: {}, Cis handle {:#x}, allocation {:#x}, active: {}", tag, cis_entry.addr, cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active); stream_map.streams_map_target.emplace_back(stream_map_info( cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active)); stream_map.streams_map_current.emplace_back(stream_map_info( cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active)); } } return true; } bool UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { if (GetCodecLocation() != bluetooth::le_audio::types::CodecLocation::ADSP) { return; return false; } auto available_allocations = AdjustAllocationForOffloader(stream_params.audio_channel_allocation); if (available_allocations == 0) { log::error("There is no CIS connected"); return; if (available_allocations == -1) { log::error("Unsupported allocation {:#x}", stream_params.audio_channel_allocation); return false; } if (available_allocations == codec_spec_conf::kLeAudioLocationMonoAudio) { return UpdateCisMonoConfiguration(cises, direction); } auto& stream_map = offloader_stream_maps.get(direction); Loading Loading @@ -770,6 +823,8 @@ public: stream_map_info(cis_entry.conn_handle, current_allocation, is_active)); } } return true; } private: Loading Loading @@ -1233,12 +1288,13 @@ void CodecManager::UpdateBroadcastConnHandle( } } void CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, bool CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { if (pimpl_->IsRunning()) { return pimpl_->codec_manager_impl_->UpdateCisConfiguration(cises, stream_params, direction); } return false; } void CodecManager::ClearCisConfiguration(uint8_t direction) { Loading
system/bta/le_audio/codec_manager.h +1 −1 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public: void Stop(void); virtual types::CodecLocation GetCodecLocation(void) const; virtual bool IsDualBiDirSwbSupported(void) const; virtual void UpdateCisConfiguration(const std::vector<struct types::cis>& cises, virtual bool UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction); virtual void ClearCisConfiguration(uint8_t direction); virtual bool IsUsingCodecExtensibility() const; Loading
system/bta/le_audio/codec_manager_test.cc +137 −0 Original line number Diff line number Diff line Loading @@ -269,10 +269,17 @@ static constexpr char kPropLeAudioOffloadDisabled[] = "persist.bluetooth.leaudio static constexpr char kPropLeAudioBidirSwbSupported[] = "bluetooth.leaudio.dual_bidirection_swb.supported"; RawAddress GetTestAddress(uint8_t index) { EXPECT_LT(index, UINT8_MAX); RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}}; return result; } class CodecManagerTestBase : public Test { public: virtual void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); com::android::bluetooth::flags::provider_->reset_flags(); set_mock_offload_capabilities(offload_capabilities_none); bluetooth::legacy::hci::testing::SetMock(legacy_hci_mock_); Loading Loading @@ -506,6 +513,136 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationAdspDownMix) { } } TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) { com::android::bluetooth::flags::provider_->leaudio_mono_location_errata(true); const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> offloading_preference(0); codec_manager->Start(offloading_preference); // Current CIS configuration for two earbuds std::vector<struct types::cis> cises{ { .id = 0x00, .type = types::CisType::CIS_TYPE_BIDIRECTIONAL, .conn_handle = 96, .addr = RawAddress::kEmpty, // Disconnected }, { .id = 0x01, .type = types::CisType::CIS_TYPE_BIDIRECTIONAL, .conn_handle = 97, .addr = GetTestAddress(1), }, }; // Stream parameters types::BidirectionalPair<stream_parameters> stream_params{ .sink = { .sample_frequency_hz = 16000, .frame_duration_us = 10000, .octets_per_codec_frame = 40, .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, .codec_frames_blocks_per_sdu = 1, .num_of_channels = 1, .num_of_devices = 1, .stream_locations = { std::pair<uint16_t, uint32_t>{ 97 /*conn_handle*/, codec_spec_conf::kLeAudioLocationMonoAudio}, }, }, .source = { .sample_frequency_hz = 16000, .frame_duration_us = 10000, .octets_per_codec_frame = 40, .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, .codec_frames_blocks_per_sdu = 1, .num_of_channels = 1, .num_of_devices = 1, { std::pair<uint16_t, uint32_t>{ 97 /*conn_handle*/, codec_spec_conf::kLeAudioLocationMonoAudio}, }, }, }; ASSERT_TRUE( codec_manager->UpdateCisConfiguration(cises, stream_params.sink, kLeAudioDirectionSink)); ASSERT_TRUE(codec_manager->UpdateCisConfiguration(cises, stream_params.source, kLeAudioDirectionSource)); // Verify the offloader config content 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, uint8_t direction) { out_offload_configs.get(direction) = config; }); // Expect the same configuration for sink and source ASSERT_TRUE(out_offload_configs.sink.has_value()); ASSERT_TRUE(out_offload_configs.source.has_value()); for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink, bluetooth::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) { ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); // The disconnected should be inactive ASSERT_FALSE(info.is_stream_active); } else if (info.stream_handle == 97) { ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); // The connected should be active ASSERT_TRUE(info.is_stream_active); } else { ASSERT_EQ(97, info.stream_handle); } allocation |= info.audio_channel_allocation; } ASSERT_EQ(16, config.bits_per_sample); ASSERT_EQ(16000u, config.sampling_rate); ASSERT_EQ(10000u, config.frame_duration); ASSERT_EQ(40u, config.octets_per_frame); ASSERT_EQ(1, config.blocks_per_sdu); ASSERT_EQ(44, config.peer_delay_ms); ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, allocation); } // Clear the CIS configuration map (no active CISes). codec_manager->ClearCisConfiguration(kLeAudioDirectionSink); codec_manager->ClearCisConfiguration(kLeAudioDirectionSource); 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, uint8_t direction) { out_offload_configs.get(direction) = config; }); // Expect sink & source configurations with empty CIS channel allocation map. ASSERT_TRUE(out_offload_configs.sink.has_value()); ASSERT_TRUE(out_offload_configs.source.has_value()); for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink, bluetooth::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); ASSERT_EQ(10000u, config.frame_duration); ASSERT_EQ(40u, config.octets_per_frame); ASSERT_EQ(1, config.blocks_per_sdu); ASSERT_EQ(44, config.peer_delay_ms); } } TEST_F(CodecManagerTestAdsp, test_capabilities_none) { const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> offloading_preference(0); codec_manager->Start(offloading_preference); Loading
system/bta/le_audio/mock_codec_manager.cc +2 −1 Original line number Diff line number Diff line Loading @@ -160,12 +160,13 @@ void CodecManager::Stop() { mock_codec_manager_pimpl_ = nullptr; } void CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, bool CodecManager::UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { if (pimpl_) { return pimpl_->UpdateCisConfiguration(cises, stream_params, direction); } return false; } void CodecManager::ClearCisConfiguration(uint8_t direction) { Loading