Loading system/bta/le_audio/codec_manager.h +11 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,17 @@ class CodecManager { public: struct UnicastConfigurationRequirements { ::bluetooth::le_audio::types::LeAudioContextType audio_context_type; std::optional<std::vector<types::acs_ac_record>> sink_pacs; std::optional<std::vector<types::acs_ac_record>> source_pacs; struct DeviceDirectionRequirements { uint8_t target_latency = types::kTargetLatencyUndefined; uint8_t target_Phy = types::kTargetPhyUndefined; types::LeAudioLtvMap params; }; std::optional<std::vector<DeviceDirectionRequirements>> sink_requirements; std::optional<std::vector<DeviceDirectionRequirements>> source_requirements; }; /* The verifier function checks each possible configuration (from the set of Loading system/bta/le_audio/device_groups.cc +86 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "hci/controller_interface.h" #include "internal_include/bt_trace.h" #include "le_audio/codec_manager.h" #include "le_audio/devices.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "le_audio_utils.h" Loading Loading @@ -783,11 +784,90 @@ bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) { return old_contexts != GetAvailableContexts(); } CodecManager::UnicastConfigurationRequirements LeAudioDeviceGroup::GetAudioSetConfigurationRequirements( types::LeAudioContextType ctx_type) const { auto new_req = CodecManager::UnicastConfigurationRequirements{ .audio_context_type = ctx_type, }; // Define a requirement for each location. Knowing codec specific // capabilities (i.e. multiplexing capability) the config provider can // determine the number of ASEs to activate. for (auto const& weak_dev_ptr : leAudioDevices_) { auto device = weak_dev_ptr.lock(); BidirectionalPair<bool> has_location = {false, false}; for (auto direction : {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) { if (device->GetAseCount(direction) == 0) { log::warn("Device {} has no ASEs for direction: {}", device->address_, (int)direction); continue; } auto& dev_locations = (direction == types::kLeAudioDirectionSink) ? device->snk_audio_locations_ : device->src_audio_locations_; if (dev_locations.none()) { log::warn("Device {} has no locations for direction: {}", device->address_, (int)direction); continue; } has_location.get(direction) = true; auto& direction_req = (direction == types::kLeAudioDirectionSink) ? new_req.sink_requirements : new_req.source_requirements; if (!direction_req) { direction_req = std::vector<CodecManager::UnicastConfigurationRequirements:: DeviceDirectionRequirements>(); } // Pass the audio channel allocation requirement auto locations = dev_locations.to_ulong(); CodecManager::UnicastConfigurationRequirements:: DeviceDirectionRequirements config_req; config_req.params.Add( codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, (uint32_t)locations); log::warn("Device {} pushes requirement, location: {}, direction: {}", device->address_, (int)locations, (int)direction); direction_req->push_back(std::move(config_req)); } // Push sink PACs if there are some sink requirements if (has_location.sink && !device->snk_pacs_.empty()) { if (!new_req.sink_pacs) { new_req.sink_pacs = std::vector<types::acs_ac_record>{}; } for (auto const& [_, pac_char] : device->snk_pacs_) { for (auto const& pac_record : pac_char) { new_req.sink_pacs->push_back(pac_record); } } } // Push source PACs if there are some source requirements if (has_location.source && !device->src_pacs_.empty()) { if (!new_req.source_pacs) { new_req.source_pacs = std::vector<types::acs_ac_record>{}; } for (auto& [_, pac_char] : device->src_pacs_) { for (auto const& pac_record : pac_char) { new_req.source_pacs->push_back(pac_record); } } } } return new_req; } bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache( LeAudioContextType ctx_type) const { CodecManager::UnicastConfigurationRequirements requirements = { .audio_context_type = ctx_type}; auto requirements = GetAudioSetConfigurationRequirements(ctx_type); auto new_conf = CodecManager::GetInstance()->GetCodecConfig( requirements, std::bind(&LeAudioDeviceGroup::FindFirstSupportedConfiguration, this, Loading Loading @@ -1375,10 +1455,12 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( static_cast<int>(ase_cnt - active_ase_cnt)); for (auto const& ent : ase_confs) { // Verify PACS only if this is transparent LTV format auto const& pacs = (direction == types::kLeAudioDirectionSink) ? device->snk_pacs_ : device->src_pacs_; if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) { if (utils::IsCodecUsingLtvFormat(ent.codec.id) && !utils::GetConfigurationSupportedPac(pacs, ent.codec)) { log::debug( "Insufficient PAC for {}", direction == types::kLeAudioDirectionSink ? "sink" : "source"); Loading system/bta/le_audio/device_groups.h +3 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,9 @@ class LeAudioDeviceGroup { bool UpdateAudioContextAvailability(void); bool UpdateAudioSetConfigurationCache( types::LeAudioContextType ctx_type) const; CodecManager::UnicastConfigurationRequirements GetAudioSetConfigurationRequirements( types::LeAudioContextType ctx_type) const; bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); std::shared_ptr<const set_configurations::AudioSetConfiguration> Loading system/bta/le_audio/devices.cc +9 −3 Original line number Diff line number Diff line Loading @@ -257,6 +257,7 @@ bool LeAudioDevice::ConfigureAses( if (!ase) { log::error("Unable to find an ASE to configure"); PrintDebugState(); return false; } Loading @@ -265,7 +266,8 @@ bool LeAudioDevice::ConfigureAses( (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_; for (size_t i = 0; i < ase_configs.size() && ase; ++i) { auto const& ase_cfg = ase_configs.at(i); if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) && !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { return false; } } Loading @@ -283,13 +285,15 @@ bool LeAudioDevice::ConfigureAses( : src_audio_locations_; // Before we activate the ASEs, make sure we have the right configuration // Check for matching PACs only if we know that the LTV format is being used. uint8_t max_required_ase_per_dev = ase_configs.size() / num_of_devices + (ase_configs.size() % num_of_devices); int needed_ase = std::min((int)(max_required_ase_per_dev), (int)(ase_configs.size() - active_ases)); for (int i = 0; i < needed_ase; ++i) { auto const& ase_cfg = ase_configs.at(i); if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) && !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { log::error("No matching PAC found. Stop the activation."); return false; } Loading Loading @@ -331,6 +335,7 @@ bool LeAudioDevice::ConfigureAses( ase->target_latency = ase_cfg.qos.target_latency; ase->codec_id = ase_cfg.codec.id; ase->codec_config = ase_cfg.codec.params; ase->vendor_codec_config = ase_cfg.codec.vendor_params; ase->channel_count = ase_cfg.codec.channel_count_per_iso_stream; /* Let's choose audio channel allocation if not set */ Loading @@ -341,7 +346,8 @@ bool LeAudioDevice::ConfigureAses( /* Get default value if no requirement for specific frame blocks per sdu */ if (!ase->codec_config.Find( if (utils::IsCodecUsingLtvFormat(ase->codec_id) && !ase->codec_config.Find( codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu)) { ase->codec_config.Add( codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu, Loading system/bta/le_audio/devices_test.cc +391 −97 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
system/bta/le_audio/codec_manager.h +11 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,17 @@ class CodecManager { public: struct UnicastConfigurationRequirements { ::bluetooth::le_audio::types::LeAudioContextType audio_context_type; std::optional<std::vector<types::acs_ac_record>> sink_pacs; std::optional<std::vector<types::acs_ac_record>> source_pacs; struct DeviceDirectionRequirements { uint8_t target_latency = types::kTargetLatencyUndefined; uint8_t target_Phy = types::kTargetPhyUndefined; types::LeAudioLtvMap params; }; std::optional<std::vector<DeviceDirectionRequirements>> sink_requirements; std::optional<std::vector<DeviceDirectionRequirements>> source_requirements; }; /* The verifier function checks each possible configuration (from the set of Loading
system/bta/le_audio/device_groups.cc +86 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "hci/controller_interface.h" #include "internal_include/bt_trace.h" #include "le_audio/codec_manager.h" #include "le_audio/devices.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "le_audio_utils.h" Loading Loading @@ -783,11 +784,90 @@ bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) { return old_contexts != GetAvailableContexts(); } CodecManager::UnicastConfigurationRequirements LeAudioDeviceGroup::GetAudioSetConfigurationRequirements( types::LeAudioContextType ctx_type) const { auto new_req = CodecManager::UnicastConfigurationRequirements{ .audio_context_type = ctx_type, }; // Define a requirement for each location. Knowing codec specific // capabilities (i.e. multiplexing capability) the config provider can // determine the number of ASEs to activate. for (auto const& weak_dev_ptr : leAudioDevices_) { auto device = weak_dev_ptr.lock(); BidirectionalPair<bool> has_location = {false, false}; for (auto direction : {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) { if (device->GetAseCount(direction) == 0) { log::warn("Device {} has no ASEs for direction: {}", device->address_, (int)direction); continue; } auto& dev_locations = (direction == types::kLeAudioDirectionSink) ? device->snk_audio_locations_ : device->src_audio_locations_; if (dev_locations.none()) { log::warn("Device {} has no locations for direction: {}", device->address_, (int)direction); continue; } has_location.get(direction) = true; auto& direction_req = (direction == types::kLeAudioDirectionSink) ? new_req.sink_requirements : new_req.source_requirements; if (!direction_req) { direction_req = std::vector<CodecManager::UnicastConfigurationRequirements:: DeviceDirectionRequirements>(); } // Pass the audio channel allocation requirement auto locations = dev_locations.to_ulong(); CodecManager::UnicastConfigurationRequirements:: DeviceDirectionRequirements config_req; config_req.params.Add( codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, (uint32_t)locations); log::warn("Device {} pushes requirement, location: {}, direction: {}", device->address_, (int)locations, (int)direction); direction_req->push_back(std::move(config_req)); } // Push sink PACs if there are some sink requirements if (has_location.sink && !device->snk_pacs_.empty()) { if (!new_req.sink_pacs) { new_req.sink_pacs = std::vector<types::acs_ac_record>{}; } for (auto const& [_, pac_char] : device->snk_pacs_) { for (auto const& pac_record : pac_char) { new_req.sink_pacs->push_back(pac_record); } } } // Push source PACs if there are some source requirements if (has_location.source && !device->src_pacs_.empty()) { if (!new_req.source_pacs) { new_req.source_pacs = std::vector<types::acs_ac_record>{}; } for (auto& [_, pac_char] : device->src_pacs_) { for (auto const& pac_record : pac_char) { new_req.source_pacs->push_back(pac_record); } } } } return new_req; } bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache( LeAudioContextType ctx_type) const { CodecManager::UnicastConfigurationRequirements requirements = { .audio_context_type = ctx_type}; auto requirements = GetAudioSetConfigurationRequirements(ctx_type); auto new_conf = CodecManager::GetInstance()->GetCodecConfig( requirements, std::bind(&LeAudioDeviceGroup::FindFirstSupportedConfiguration, this, Loading Loading @@ -1375,10 +1455,12 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( static_cast<int>(ase_cnt - active_ase_cnt)); for (auto const& ent : ase_confs) { // Verify PACS only if this is transparent LTV format auto const& pacs = (direction == types::kLeAudioDirectionSink) ? device->snk_pacs_ : device->src_pacs_; if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) { if (utils::IsCodecUsingLtvFormat(ent.codec.id) && !utils::GetConfigurationSupportedPac(pacs, ent.codec)) { log::debug( "Insufficient PAC for {}", direction == types::kLeAudioDirectionSink ? "sink" : "source"); Loading
system/bta/le_audio/device_groups.h +3 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,9 @@ class LeAudioDeviceGroup { bool UpdateAudioContextAvailability(void); bool UpdateAudioSetConfigurationCache( types::LeAudioContextType ctx_type) const; CodecManager::UnicastConfigurationRequirements GetAudioSetConfigurationRequirements( types::LeAudioContextType ctx_type) const; bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); std::shared_ptr<const set_configurations::AudioSetConfiguration> Loading
system/bta/le_audio/devices.cc +9 −3 Original line number Diff line number Diff line Loading @@ -257,6 +257,7 @@ bool LeAudioDevice::ConfigureAses( if (!ase) { log::error("Unable to find an ASE to configure"); PrintDebugState(); return false; } Loading @@ -265,7 +266,8 @@ bool LeAudioDevice::ConfigureAses( (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_; for (size_t i = 0; i < ase_configs.size() && ase; ++i) { auto const& ase_cfg = ase_configs.at(i); if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) && !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { return false; } } Loading @@ -283,13 +285,15 @@ bool LeAudioDevice::ConfigureAses( : src_audio_locations_; // Before we activate the ASEs, make sure we have the right configuration // Check for matching PACs only if we know that the LTV format is being used. uint8_t max_required_ase_per_dev = ase_configs.size() / num_of_devices + (ase_configs.size() % num_of_devices); int needed_ase = std::min((int)(max_required_ase_per_dev), (int)(ase_configs.size() - active_ases)); for (int i = 0; i < needed_ase; ++i) { auto const& ase_cfg = ase_configs.at(i); if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) && !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { log::error("No matching PAC found. Stop the activation."); return false; } Loading Loading @@ -331,6 +335,7 @@ bool LeAudioDevice::ConfigureAses( ase->target_latency = ase_cfg.qos.target_latency; ase->codec_id = ase_cfg.codec.id; ase->codec_config = ase_cfg.codec.params; ase->vendor_codec_config = ase_cfg.codec.vendor_params; ase->channel_count = ase_cfg.codec.channel_count_per_iso_stream; /* Let's choose audio channel allocation if not set */ Loading @@ -341,7 +346,8 @@ bool LeAudioDevice::ConfigureAses( /* Get default value if no requirement for specific frame blocks per sdu */ if (!ase->codec_config.Find( if (utils::IsCodecUsingLtvFormat(ase->codec_id) && !ase->codec_config.Find( codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu)) { ase->codec_config.Add( codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu, Loading
system/bta/le_audio/devices_test.cc +391 −97 File changed.Preview size limit exceeded, changes collapsed. Show changes