Loading system/bta/le_audio/audio_hal_client/audio_hal_client.h +6 −7 Original line number Diff line number Diff line Loading @@ -23,9 +23,8 @@ #include "audio_hal_interface/le_audio_software.h" namespace bluetooth::le_audio { /* Represents configuration of audio codec, as exchanged between le audio and * phone. * It can also be passed to the audio source to configure its parameters. /* Represents configuration used to configure the local audio sessions and * the software codecs in case of a software coding sessions. */ struct LeAudioCodecConfiguration { static constexpr uint8_t kChannelNumberMono = Loading Loading @@ -57,13 +56,13 @@ struct LeAudioCodecConfiguration { static constexpr uint32_t kInterval10000Us = 10000; /** number of channels */ uint8_t num_channels; uint8_t num_channels = 0; /** sampling rate that the codec expects to receive from audio framework */ uint32_t sample_rate; uint32_t sample_rate = 0; /** bits per sample that codec expects to receive from audio framework */ uint8_t bits_per_sample; uint8_t bits_per_sample = 0; /** Data interval determines how often we send samples to the remote. This * should match how often we grab data from audio source, optionally we can Loading @@ -71,7 +70,7 @@ struct LeAudioCodecConfiguration { * * Value is provided in us. */ uint32_t data_interval_us; uint32_t data_interval_us = 0; bool operator!=(const LeAudioCodecConfiguration& other) { return !((num_channels == other.num_channels) && Loading system/bta/le_audio/client.cc +65 −136 Original line number Diff line number Diff line Loading @@ -249,8 +249,6 @@ class LeAudioClientImpl : public LeAudioClient { sink_monitor_mode_(false), sink_monitor_notified_status_(std::nullopt), source_monitor_mode_(false), current_source_codec_config({0, 0, 0, 0}), current_sink_codec_config({0, 0, 0, 0}), le_audio_source_hal_client_(nullptr), le_audio_sink_hal_client_(nullptr), close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")), Loading Loading @@ -1111,9 +1109,7 @@ class LeAudioClientImpl : public LeAudioClient { group->is_duplex_preference_le_audio = is_duplex_preference_le_audio; } void StartAudioSession(LeAudioDeviceGroup* group, const LeAudioCodecConfiguration* source_config, const LeAudioCodecConfiguration* sink_config) { void StartAudioSession(LeAudioDeviceGroup* group) { /* This function is called when group is not yet set to active. * This is why we don't have to check if session is started already. * Just check if it is acquired. Loading @@ -1132,10 +1128,10 @@ class LeAudioClientImpl : public LeAudioClient { /* We assume that peer device always use same frame duration */ uint32_t frame_duration_us = 0; if (!source_config->IsInvalid()) { frame_duration_us = source_config->data_interval_us; } else if (!sink_config->IsInvalid()) { frame_duration_us = sink_config->data_interval_us; if (!current_encoder_config_.IsInvalid()) { frame_duration_us = current_encoder_config_.data_interval_us; } else if (!current_decoder_config_.IsInvalid()) { frame_duration_us = current_decoder_config_.data_interval_us; } else { log::assert_that(true, "Both configs are invalid"); } Loading @@ -1150,14 +1146,13 @@ class LeAudioClientImpl : public LeAudioClient { /* If group supports more than 16kHz for the microphone in converstional * case let's use that also for Audio Framework. */ std::optional<LeAudioCodecConfiguration> sink_configuration = group->GetCodecConfigurationByDirection( auto sink_configuration = group->GetAudioSessionCodecConfigForDirection( LeAudioContextType::CONVERSATIONAL, bluetooth::le_audio::types::kLeAudioDirectionSource); if (sink_configuration && sink_configuration->sample_rate > if (!sink_configuration.IsInvalid() && sink_configuration.sample_rate > bluetooth::audio::le_audio::kSampleRate16000) { audio_framework_sink_config.sample_rate = sink_configuration->sample_rate; audio_framework_sink_config.sample_rate = sink_configuration.sample_rate; } le_audio_sink_hal_client_->Start(audio_framework_sink_config, Loading Loading @@ -1289,14 +1284,12 @@ class LeAudioClientImpl : public LeAudioClient { } } } UpdateConfigAndCheckIfReconfigurationIsNeeded(group_id, default_context_type); if (current_source_codec_config.IsInvalid() && current_sink_codec_config.IsInvalid()) { log::error("Unsupported device configurations"); /* Only update the configuration audio context and audio coding session * parameters if needed. */ UpdateConfigAndCheckIfReconfigurationIsNeeded(group, default_context_type); callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE); return; } auto previous_active_group = active_group_id_; log::info("Active group_id changed {} -> {}", previous_active_group, Loading @@ -1304,8 +1297,7 @@ class LeAudioClientImpl : public LeAudioClient { if (previous_active_group == bluetooth::groups::kGroupUnknown) { /* Expose audio sessions if there was no previous active group */ StartAudioSession(group, ¤t_source_codec_config, ¤t_sink_codec_config); StartAudioSession(group); active_group_id_ = group_id; } else { /* In case there was an active group. Stop the stream, but before that, set Loading Loading @@ -3678,7 +3670,7 @@ class LeAudioClientImpl : public LeAudioClient { sw_enc_left = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); auto codec_status = sw_enc_left->InitEncoder( audio_framework_source_config, current_source_codec_config); audio_framework_source_config, current_encoder_config_); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { log::error("Left channel codec setup failed with err: {}", Loading @@ -3690,7 +3682,7 @@ class LeAudioClientImpl : public LeAudioClient { sw_enc_right = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); codec_status = sw_enc_right->InitEncoder(audio_framework_source_config, current_source_codec_config); current_encoder_config_); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { log::error("Right channel codec setup failed with err: {}", Loading Loading @@ -3757,7 +3749,7 @@ class LeAudioClientImpl : public LeAudioClient { } sw_dec_left = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); auto codec_status = sw_dec_left->InitDecoder(current_sink_codec_config, auto codec_status = sw_dec_left->InitDecoder(current_decoder_config_, audio_framework_sink_config); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { Loading @@ -3769,7 +3761,7 @@ class LeAudioClientImpl : public LeAudioClient { sw_dec_right = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); codec_status = sw_dec_right->InitDecoder(current_sink_codec_config, codec_status = sw_dec_right->InitDecoder(current_decoder_config_, audio_framework_sink_config); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { Loading Loading @@ -3810,49 +3802,30 @@ class LeAudioClientImpl : public LeAudioClient { void StopAudio(void) { SuspendAudio(); } void printSingleConfiguration(int fd, LeAudioCodecConfiguration* conf, bool print_audio_state, bool sender = false) { void printCurrentStreamConfiguration(int fd) { std::stringstream stream; if (print_audio_state) { if (sender) { stream << "\taudio sender state: " << audio_sender_state_ << "\n"; } else { stream << "\taudio receiver state: " << audio_receiver_state_ << "\n"; } } stream << "\tsample rate: " << +conf->sample_rate << ",\tchan: " << +conf->num_channels << ",\tbits: " << +conf->bits_per_sample << ",\tdata_interval_us: " << +conf->data_interval_us << "\n"; auto config_printer = [&stream](LeAudioCodecConfiguration& conf) { stream << "\tsample rate: " << +conf.sample_rate << ",\tchan: " << +conf.num_channels << ",\tbits: " << +conf.bits_per_sample << ",\tdata_interval_us: " << +conf.data_interval_us << "\n"; }; dprintf(fd, "%s", stream.str().c_str()); } stream << " Speaker codec config (audio framework) \n"; stream << "\taudio sender state: " << audio_sender_state_ << "\n"; config_printer(audio_framework_source_config); void printCurrentStreamConfiguration(int fd) { auto conf = &audio_framework_source_config; dprintf(fd, " Speaker codec config (audio framework) \n"); if (conf) { printSingleConfiguration(fd, conf, false); } stream << " Microphone codec config (audio framework) \n"; stream << "\taudio receiver state: " << audio_receiver_state_ << "\n"; config_printer(audio_framework_sink_config); dprintf(fd, " Microphone codec config (audio framework) \n"); conf = &audio_framework_sink_config; if (conf) { printSingleConfiguration(fd, conf, false); } stream << " Speaker codec config (SW encoder)\n"; config_printer(current_encoder_config_); conf = ¤t_source_codec_config; dprintf(fd, " Speaker codec config (Bluetooth)\n"); if (conf) { printSingleConfiguration(fd, conf, true, true); } stream << " Microphone codec config (SW decoder)\n"; config_printer(current_decoder_config_); conf = ¤t_sink_codec_config; dprintf(fd, " Microphone codec config (Bluetooth)\n"); if (conf) { printSingleConfiguration(fd, conf, true, false); } dprintf(fd, "%s", stream.str().c_str()); } void Dump(int fd) { Loading Loading @@ -3924,65 +3897,17 @@ class LeAudioClientImpl : public LeAudioClient { } AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded( int group_id, LeAudioContextType context_type) { bool reconfiguration_needed = false; bool sink_cfg_available = true; bool source_cfg_available = true; LeAudioDeviceGroup* group, LeAudioContextType context_type) { log::debug("Checking whether to reconfigure from {} to {}", ToString(configuration_context_type_), ToString(context_type)); auto group = aseGroups_.FindById(group_id); if (!group) { log::error("Invalid group: {}", static_cast<int>(group_id)); return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED; } std::optional<LeAudioCodecConfiguration> source_configuration = group->GetCodecConfigurationByDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSink); std::optional<LeAudioCodecConfiguration> sink_configuration = group->GetCodecConfigurationByDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSource); if (source_configuration) { if (*source_configuration != current_source_codec_config) { current_source_codec_config = *source_configuration; reconfiguration_needed = true; } } else { if (!current_source_codec_config.IsInvalid()) { current_source_codec_config = {0, 0, 0, 0}; reconfiguration_needed = true; } source_cfg_available = false; } if (sink_configuration) { if (*sink_configuration != current_sink_codec_config) { current_sink_codec_config = *sink_configuration; reconfiguration_needed = true; } } else { if (!current_sink_codec_config.IsInvalid()) { current_sink_codec_config = {0, 0, 0, 0}; reconfiguration_needed = true; } sink_cfg_available = false; } if (DsaReconfigureNeeded(group, context_type)) { reconfiguration_needed = true; auto audio_set_conf = group->GetConfiguration(context_type); if (!audio_set_conf) { return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE; } log::debug( "Context: {} Reconfiguration_needed = {}, sink_cfg_available = {}, " "source_cfg_available = {}", ToString(context_type), reconfiguration_needed, sink_cfg_available, source_cfg_available); if (!reconfiguration_needed) { if (group->IsGroupConfiguredTo(*audio_set_conf) && !DsaReconfigureNeeded(group, context_type)) { // Assign the new configuration context as it reprents the current // use case even when it eventually ends up being the exact same // codec and qos configuration. Loading @@ -3993,14 +3918,17 @@ class LeAudioClientImpl : public LeAudioClient { return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED; } if (!sink_cfg_available && !source_cfg_available) { return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE; } log::info("Session reconfiguration needed group: {} for context type: {}", group->group_id_, ToHexString(context_type)); configuration_context_type_ = context_type; // Note: The local sink config is based on remote device's source config // and vice versa. current_decoder_config_ = group->GetAudioSessionCodecConfigForDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSource); current_encoder_config_ = group->GetAudioSessionCodecConfigForDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSink); return AudioReconfigurationResult::RECONFIGURATION_NEEDED; } Loading Loading @@ -4143,7 +4071,7 @@ class LeAudioClientImpl : public LeAudioClient { } /* Check if the device resume is allowed */ if (!group->GetCodecConfigurationByDirection( if (!group->HasCodecConfigurationForDirection( configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSink)) { log::error("invalid resume request for context type: {}", Loading Loading @@ -4358,10 +4286,11 @@ class LeAudioClientImpl : public LeAudioClient { inline bool IsDirectionAvailableForCurrentConfiguration( const LeAudioDeviceGroup* group, uint8_t direction) const { return group ->GetCachedCodecConfigurationByDirection(configuration_context_type_, direction) .has_value(); auto current_config = group->GetCachedConfiguration(configuration_context_type_); if (current_config) return (current_config->confs.get(direction).size() != 0); return false; } void notifyAudioLocalSink(UnicastMonitorModeStatus status) { Loading Loading @@ -4418,7 +4347,7 @@ class LeAudioClientImpl : public LeAudioClient { } /* Check if the device resume is allowed */ if (!group->GetCodecConfigurationByDirection( if (!group->HasCodecConfigurationForDirection( configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSource)) { log::error("invalid resume request for context type: {}", Loading Loading @@ -4639,8 +4568,8 @@ class LeAudioClientImpl : public LeAudioClient { bool SetConfigurationAndStopStreamWhenNeeded( LeAudioDeviceGroup* group, LeAudioContextType new_context_type) { auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded( group->group_id_, new_context_type); auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded(group, new_context_type); /* Even though the reconfiguration may not be needed, this has * to be set here as it might be the initial configuration. */ Loading Loading @@ -5821,9 +5750,9 @@ class LeAudioClientImpl : public LeAudioClient { static constexpr uint16_t kBapMinimumAttMtu = 64; /* Current stream configuration */ LeAudioCodecConfiguration current_source_codec_config; LeAudioCodecConfiguration current_sink_codec_config; /* Current stream configuration - used to set up the software codecs */ LeAudioCodecConfiguration current_encoder_config_; LeAudioCodecConfiguration current_decoder_config_; /* Static Audio Framework session configuration. * Resampling will be done inside the bt stack Loading system/bta/le_audio/device_groups.cc +22 −57 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <bluetooth/log.h> #include <optional> #include "bta/include/bta_gatt_api.h" #include "bta_csis_api.h" #include "btif/include/btif_profile_storage.h" Loading @@ -28,6 +30,7 @@ #include "internal_include/bt_trace.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "le_audio_utils.h" #include "main/shim/entry.h" #include "metrics_collector.h" #include "os/log.h" Loading Loading @@ -760,7 +763,7 @@ bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) { } bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache( LeAudioContextType ctx_type) { LeAudioContextType ctx_type) const { CodecManager::UnicastConfigurationRequirements requirements = { .audio_context_type = ctx_type}; auto new_conf = CodecManager::GetInstance()->GetCodecConfig( Loading Loading @@ -1550,7 +1553,7 @@ LeAudioDeviceGroup::GetActiveConfiguration(void) const { } std::shared_ptr<const set_configurations::AudioSetConfiguration> LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) { LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) const { if (context_type == LeAudioContextType::UNINITIALIZED) { return nullptr; } Loading @@ -1572,60 +1575,9 @@ LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) { return GetCachedConfiguration(context_type); } std::optional<LeAudioCodecConfiguration> LeAudioDeviceGroup::GetCachedCodecConfigurationByDirection( LeAudioCodecConfiguration LeAudioDeviceGroup::GetAudioSessionCodecConfigForDirection( LeAudioContextType context_type, uint8_t direction) const { auto audio_set_conf = GetCachedConfiguration(context_type); if (!audio_set_conf) return std::nullopt; LeAudioCodecConfiguration group_config = {0, 0, 0, 0}; for (const auto& conf : audio_set_conf->confs.get(direction)) { if (group_config.sample_rate != 0 && conf.codec.GetSamplingFrequencyHz() != group_config.sample_rate) { log::warn( "stream configuration could not be determined (sampling frequency " "differs) for direction: {}", loghex(direction)); return std::nullopt; } group_config.sample_rate = conf.codec.GetSamplingFrequencyHz(); if (group_config.data_interval_us != 0 && conf.codec.GetDataIntervalUs() != group_config.data_interval_us) { log::warn( "stream configuration could not be determined (data interval " "differs) for direction: {}", loghex(direction)); return std::nullopt; } group_config.data_interval_us = conf.codec.GetDataIntervalUs(); if (group_config.bits_per_sample != 0 && conf.codec.GetBitsPerSample() != group_config.bits_per_sample) { log::warn( "stream configuration could not be determined (bits per sample " "differs) for direction: {}", loghex(direction)); return std::nullopt; } group_config.bits_per_sample = conf.codec.GetBitsPerSample(); log::assert_that( audio_set_conf->topology_info.has_value(), "No topology info, which is required to properly configure the ASEs"); group_config.num_channels += conf.codec.GetChannelCountPerIsoStream() * audio_set_conf->topology_info->device_count.get(direction); } if (group_config.IsInvalid()) return std::nullopt; return group_config; } std::optional<LeAudioCodecConfiguration> LeAudioDeviceGroup::GetCodecConfigurationByDirection( LeAudioContextType context_type, uint8_t direction) { const set_configurations::AudioSetConfiguration* conf = nullptr; bool is_valid = false; Loading @@ -1640,8 +1592,19 @@ LeAudioDeviceGroup::GetCodecConfigurationByDirection( UpdateAudioSetConfigurationCache(context_type); } /* Return the cached value */ return GetCachedCodecConfigurationByDirection(context_type, direction); auto audio_set_conf = GetCachedConfiguration(context_type); if (!audio_set_conf) return {0, 0, 0, 0}; auto group_config = utils::GetAudioSessionCodecConfigFromAudioSetConfiguration( *audio_set_conf.get(), direction); return group_config; } bool LeAudioDeviceGroup::HasCodecConfigurationForDirection( types::LeAudioContextType context_type, uint8_t direction) const { auto audio_set_conf = GetConfiguration(context_type); return audio_set_conf ? !audio_set_conf->confs.get(direction).empty() : false; } bool LeAudioDeviceGroup::IsAudioSetConfigurationAvailable( Loading Loading @@ -1864,6 +1827,8 @@ bool LeAudioDeviceGroup::IsConfiguredForContext( return false; } if (!stream_conf.conf) return false; /* Check if used configuration is same as the active one.*/ return (stream_conf.conf.get() == GetActiveConfiguration().get()); } Loading system/bta/le_audio/device_groups.h +16 −9 Original line number Diff line number Diff line Loading @@ -76,6 +76,12 @@ class LeAudioDeviceGroup { types::CigState state_; } cig; bool IsGroupConfiguredTo( const set_configurations::AudioSetConfiguration& cfg) { if (!stream_conf.conf) return false; return cfg == *stream_conf.conf; } /* Current configuration strategy - recalculated on demand */ mutable std::optional<types::LeAudioConfigurationStrategy> strategy_ = std::nullopt; Loading Loading @@ -204,14 +210,15 @@ class LeAudioDeviceGroup { bool GetPresentationDelay(uint32_t* delay, uint8_t direction) const; uint16_t GetRemoteDelay(uint8_t direction) const; bool UpdateAudioContextAvailability(void); bool UpdateAudioSetConfigurationCache(types::LeAudioContextType ctx_type); bool UpdateAudioSetConfigurationCache( types::LeAudioContextType ctx_type) const; bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); std::shared_ptr<const set_configurations::AudioSetConfiguration> GetActiveConfiguration(void) const; bool IsPendingConfiguration(void) const; std::shared_ptr<const set_configurations::AudioSetConfiguration> GetConfiguration(types::LeAudioContextType ctx_type); GetConfiguration(types::LeAudioContextType ctx_type) const; std::shared_ptr<const set_configurations::AudioSetConfiguration> GetCachedConfiguration(types::LeAudioContextType ctx_type) const; void InvalidateCachedConfigurations(void); Loading @@ -225,10 +232,9 @@ class LeAudioDeviceGroup { bool IsAudioSetConfigurationSupported( LeAudioDevice* leAudioDevice, const set_configurations::AudioSetConfiguration* audio_set_conf) const; std::optional<LeAudioCodecConfiguration> GetCodecConfigurationByDirection( types::LeAudioContextType group_context_type, uint8_t direction); std::optional<LeAudioCodecConfiguration> GetCachedCodecConfigurationByDirection( LeAudioCodecConfiguration GetAudioSessionCodecConfigForDirection( types::LeAudioContextType group_context_type, uint8_t direction) const; bool HasCodecConfigurationForDirection( types::LeAudioContextType group_context_type, uint8_t direction) const; bool IsAudioSetConfigurationAvailable( types::LeAudioContextType group_context_type); Loading Loading @@ -432,7 +438,8 @@ class LeAudioDeviceGroup { * change. Stored as a pair of (is_valid_cache, configuration*). `pair.first` * being `false` means that the cached value should be refreshed. */ std::map<types::LeAudioContextType, mutable std::map< types::LeAudioContextType, std::pair<bool, const std::shared_ptr< set_configurations::AudioSetConfiguration>>> context_to_configuration_cache_map; Loading system/bta/le_audio/devices_test.cc +50 −70 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
system/bta/le_audio/audio_hal_client/audio_hal_client.h +6 −7 Original line number Diff line number Diff line Loading @@ -23,9 +23,8 @@ #include "audio_hal_interface/le_audio_software.h" namespace bluetooth::le_audio { /* Represents configuration of audio codec, as exchanged between le audio and * phone. * It can also be passed to the audio source to configure its parameters. /* Represents configuration used to configure the local audio sessions and * the software codecs in case of a software coding sessions. */ struct LeAudioCodecConfiguration { static constexpr uint8_t kChannelNumberMono = Loading Loading @@ -57,13 +56,13 @@ struct LeAudioCodecConfiguration { static constexpr uint32_t kInterval10000Us = 10000; /** number of channels */ uint8_t num_channels; uint8_t num_channels = 0; /** sampling rate that the codec expects to receive from audio framework */ uint32_t sample_rate; uint32_t sample_rate = 0; /** bits per sample that codec expects to receive from audio framework */ uint8_t bits_per_sample; uint8_t bits_per_sample = 0; /** Data interval determines how often we send samples to the remote. This * should match how often we grab data from audio source, optionally we can Loading @@ -71,7 +70,7 @@ struct LeAudioCodecConfiguration { * * Value is provided in us. */ uint32_t data_interval_us; uint32_t data_interval_us = 0; bool operator!=(const LeAudioCodecConfiguration& other) { return !((num_channels == other.num_channels) && Loading
system/bta/le_audio/client.cc +65 −136 Original line number Diff line number Diff line Loading @@ -249,8 +249,6 @@ class LeAudioClientImpl : public LeAudioClient { sink_monitor_mode_(false), sink_monitor_notified_status_(std::nullopt), source_monitor_mode_(false), current_source_codec_config({0, 0, 0, 0}), current_sink_codec_config({0, 0, 0, 0}), le_audio_source_hal_client_(nullptr), le_audio_sink_hal_client_(nullptr), close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")), Loading Loading @@ -1111,9 +1109,7 @@ class LeAudioClientImpl : public LeAudioClient { group->is_duplex_preference_le_audio = is_duplex_preference_le_audio; } void StartAudioSession(LeAudioDeviceGroup* group, const LeAudioCodecConfiguration* source_config, const LeAudioCodecConfiguration* sink_config) { void StartAudioSession(LeAudioDeviceGroup* group) { /* This function is called when group is not yet set to active. * This is why we don't have to check if session is started already. * Just check if it is acquired. Loading @@ -1132,10 +1128,10 @@ class LeAudioClientImpl : public LeAudioClient { /* We assume that peer device always use same frame duration */ uint32_t frame_duration_us = 0; if (!source_config->IsInvalid()) { frame_duration_us = source_config->data_interval_us; } else if (!sink_config->IsInvalid()) { frame_duration_us = sink_config->data_interval_us; if (!current_encoder_config_.IsInvalid()) { frame_duration_us = current_encoder_config_.data_interval_us; } else if (!current_decoder_config_.IsInvalid()) { frame_duration_us = current_decoder_config_.data_interval_us; } else { log::assert_that(true, "Both configs are invalid"); } Loading @@ -1150,14 +1146,13 @@ class LeAudioClientImpl : public LeAudioClient { /* If group supports more than 16kHz for the microphone in converstional * case let's use that also for Audio Framework. */ std::optional<LeAudioCodecConfiguration> sink_configuration = group->GetCodecConfigurationByDirection( auto sink_configuration = group->GetAudioSessionCodecConfigForDirection( LeAudioContextType::CONVERSATIONAL, bluetooth::le_audio::types::kLeAudioDirectionSource); if (sink_configuration && sink_configuration->sample_rate > if (!sink_configuration.IsInvalid() && sink_configuration.sample_rate > bluetooth::audio::le_audio::kSampleRate16000) { audio_framework_sink_config.sample_rate = sink_configuration->sample_rate; audio_framework_sink_config.sample_rate = sink_configuration.sample_rate; } le_audio_sink_hal_client_->Start(audio_framework_sink_config, Loading Loading @@ -1289,14 +1284,12 @@ class LeAudioClientImpl : public LeAudioClient { } } } UpdateConfigAndCheckIfReconfigurationIsNeeded(group_id, default_context_type); if (current_source_codec_config.IsInvalid() && current_sink_codec_config.IsInvalid()) { log::error("Unsupported device configurations"); /* Only update the configuration audio context and audio coding session * parameters if needed. */ UpdateConfigAndCheckIfReconfigurationIsNeeded(group, default_context_type); callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE); return; } auto previous_active_group = active_group_id_; log::info("Active group_id changed {} -> {}", previous_active_group, Loading @@ -1304,8 +1297,7 @@ class LeAudioClientImpl : public LeAudioClient { if (previous_active_group == bluetooth::groups::kGroupUnknown) { /* Expose audio sessions if there was no previous active group */ StartAudioSession(group, ¤t_source_codec_config, ¤t_sink_codec_config); StartAudioSession(group); active_group_id_ = group_id; } else { /* In case there was an active group. Stop the stream, but before that, set Loading Loading @@ -3678,7 +3670,7 @@ class LeAudioClientImpl : public LeAudioClient { sw_enc_left = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); auto codec_status = sw_enc_left->InitEncoder( audio_framework_source_config, current_source_codec_config); audio_framework_source_config, current_encoder_config_); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { log::error("Left channel codec setup failed with err: {}", Loading @@ -3690,7 +3682,7 @@ class LeAudioClientImpl : public LeAudioClient { sw_enc_right = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); codec_status = sw_enc_right->InitEncoder(audio_framework_source_config, current_source_codec_config); current_encoder_config_); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { log::error("Right channel codec setup failed with err: {}", Loading Loading @@ -3757,7 +3749,7 @@ class LeAudioClientImpl : public LeAudioClient { } sw_dec_left = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); auto codec_status = sw_dec_left->InitDecoder(current_sink_codec_config, auto codec_status = sw_dec_left->InitDecoder(current_decoder_config_, audio_framework_sink_config); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { Loading @@ -3769,7 +3761,7 @@ class LeAudioClientImpl : public LeAudioClient { sw_dec_right = bluetooth::le_audio::CodecInterface::CreateInstance( stream_conf->codec_id); codec_status = sw_dec_right->InitDecoder(current_sink_codec_config, codec_status = sw_dec_right->InitDecoder(current_decoder_config_, audio_framework_sink_config); if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) { Loading Loading @@ -3810,49 +3802,30 @@ class LeAudioClientImpl : public LeAudioClient { void StopAudio(void) { SuspendAudio(); } void printSingleConfiguration(int fd, LeAudioCodecConfiguration* conf, bool print_audio_state, bool sender = false) { void printCurrentStreamConfiguration(int fd) { std::stringstream stream; if (print_audio_state) { if (sender) { stream << "\taudio sender state: " << audio_sender_state_ << "\n"; } else { stream << "\taudio receiver state: " << audio_receiver_state_ << "\n"; } } stream << "\tsample rate: " << +conf->sample_rate << ",\tchan: " << +conf->num_channels << ",\tbits: " << +conf->bits_per_sample << ",\tdata_interval_us: " << +conf->data_interval_us << "\n"; auto config_printer = [&stream](LeAudioCodecConfiguration& conf) { stream << "\tsample rate: " << +conf.sample_rate << ",\tchan: " << +conf.num_channels << ",\tbits: " << +conf.bits_per_sample << ",\tdata_interval_us: " << +conf.data_interval_us << "\n"; }; dprintf(fd, "%s", stream.str().c_str()); } stream << " Speaker codec config (audio framework) \n"; stream << "\taudio sender state: " << audio_sender_state_ << "\n"; config_printer(audio_framework_source_config); void printCurrentStreamConfiguration(int fd) { auto conf = &audio_framework_source_config; dprintf(fd, " Speaker codec config (audio framework) \n"); if (conf) { printSingleConfiguration(fd, conf, false); } stream << " Microphone codec config (audio framework) \n"; stream << "\taudio receiver state: " << audio_receiver_state_ << "\n"; config_printer(audio_framework_sink_config); dprintf(fd, " Microphone codec config (audio framework) \n"); conf = &audio_framework_sink_config; if (conf) { printSingleConfiguration(fd, conf, false); } stream << " Speaker codec config (SW encoder)\n"; config_printer(current_encoder_config_); conf = ¤t_source_codec_config; dprintf(fd, " Speaker codec config (Bluetooth)\n"); if (conf) { printSingleConfiguration(fd, conf, true, true); } stream << " Microphone codec config (SW decoder)\n"; config_printer(current_decoder_config_); conf = ¤t_sink_codec_config; dprintf(fd, " Microphone codec config (Bluetooth)\n"); if (conf) { printSingleConfiguration(fd, conf, true, false); } dprintf(fd, "%s", stream.str().c_str()); } void Dump(int fd) { Loading Loading @@ -3924,65 +3897,17 @@ class LeAudioClientImpl : public LeAudioClient { } AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded( int group_id, LeAudioContextType context_type) { bool reconfiguration_needed = false; bool sink_cfg_available = true; bool source_cfg_available = true; LeAudioDeviceGroup* group, LeAudioContextType context_type) { log::debug("Checking whether to reconfigure from {} to {}", ToString(configuration_context_type_), ToString(context_type)); auto group = aseGroups_.FindById(group_id); if (!group) { log::error("Invalid group: {}", static_cast<int>(group_id)); return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED; } std::optional<LeAudioCodecConfiguration> source_configuration = group->GetCodecConfigurationByDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSink); std::optional<LeAudioCodecConfiguration> sink_configuration = group->GetCodecConfigurationByDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSource); if (source_configuration) { if (*source_configuration != current_source_codec_config) { current_source_codec_config = *source_configuration; reconfiguration_needed = true; } } else { if (!current_source_codec_config.IsInvalid()) { current_source_codec_config = {0, 0, 0, 0}; reconfiguration_needed = true; } source_cfg_available = false; } if (sink_configuration) { if (*sink_configuration != current_sink_codec_config) { current_sink_codec_config = *sink_configuration; reconfiguration_needed = true; } } else { if (!current_sink_codec_config.IsInvalid()) { current_sink_codec_config = {0, 0, 0, 0}; reconfiguration_needed = true; } sink_cfg_available = false; } if (DsaReconfigureNeeded(group, context_type)) { reconfiguration_needed = true; auto audio_set_conf = group->GetConfiguration(context_type); if (!audio_set_conf) { return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE; } log::debug( "Context: {} Reconfiguration_needed = {}, sink_cfg_available = {}, " "source_cfg_available = {}", ToString(context_type), reconfiguration_needed, sink_cfg_available, source_cfg_available); if (!reconfiguration_needed) { if (group->IsGroupConfiguredTo(*audio_set_conf) && !DsaReconfigureNeeded(group, context_type)) { // Assign the new configuration context as it reprents the current // use case even when it eventually ends up being the exact same // codec and qos configuration. Loading @@ -3993,14 +3918,17 @@ class LeAudioClientImpl : public LeAudioClient { return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED; } if (!sink_cfg_available && !source_cfg_available) { return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE; } log::info("Session reconfiguration needed group: {} for context type: {}", group->group_id_, ToHexString(context_type)); configuration_context_type_ = context_type; // Note: The local sink config is based on remote device's source config // and vice versa. current_decoder_config_ = group->GetAudioSessionCodecConfigForDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSource); current_encoder_config_ = group->GetAudioSessionCodecConfigForDirection( context_type, bluetooth::le_audio::types::kLeAudioDirectionSink); return AudioReconfigurationResult::RECONFIGURATION_NEEDED; } Loading Loading @@ -4143,7 +4071,7 @@ class LeAudioClientImpl : public LeAudioClient { } /* Check if the device resume is allowed */ if (!group->GetCodecConfigurationByDirection( if (!group->HasCodecConfigurationForDirection( configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSink)) { log::error("invalid resume request for context type: {}", Loading Loading @@ -4358,10 +4286,11 @@ class LeAudioClientImpl : public LeAudioClient { inline bool IsDirectionAvailableForCurrentConfiguration( const LeAudioDeviceGroup* group, uint8_t direction) const { return group ->GetCachedCodecConfigurationByDirection(configuration_context_type_, direction) .has_value(); auto current_config = group->GetCachedConfiguration(configuration_context_type_); if (current_config) return (current_config->confs.get(direction).size() != 0); return false; } void notifyAudioLocalSink(UnicastMonitorModeStatus status) { Loading Loading @@ -4418,7 +4347,7 @@ class LeAudioClientImpl : public LeAudioClient { } /* Check if the device resume is allowed */ if (!group->GetCodecConfigurationByDirection( if (!group->HasCodecConfigurationForDirection( configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSource)) { log::error("invalid resume request for context type: {}", Loading Loading @@ -4639,8 +4568,8 @@ class LeAudioClientImpl : public LeAudioClient { bool SetConfigurationAndStopStreamWhenNeeded( LeAudioDeviceGroup* group, LeAudioContextType new_context_type) { auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded( group->group_id_, new_context_type); auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded(group, new_context_type); /* Even though the reconfiguration may not be needed, this has * to be set here as it might be the initial configuration. */ Loading Loading @@ -5821,9 +5750,9 @@ class LeAudioClientImpl : public LeAudioClient { static constexpr uint16_t kBapMinimumAttMtu = 64; /* Current stream configuration */ LeAudioCodecConfiguration current_source_codec_config; LeAudioCodecConfiguration current_sink_codec_config; /* Current stream configuration - used to set up the software codecs */ LeAudioCodecConfiguration current_encoder_config_; LeAudioCodecConfiguration current_decoder_config_; /* Static Audio Framework session configuration. * Resampling will be done inside the bt stack Loading
system/bta/le_audio/device_groups.cc +22 −57 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <bluetooth/log.h> #include <optional> #include "bta/include/bta_gatt_api.h" #include "bta_csis_api.h" #include "btif/include/btif_profile_storage.h" Loading @@ -28,6 +30,7 @@ #include "internal_include/bt_trace.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "le_audio_utils.h" #include "main/shim/entry.h" #include "metrics_collector.h" #include "os/log.h" Loading Loading @@ -760,7 +763,7 @@ bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) { } bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache( LeAudioContextType ctx_type) { LeAudioContextType ctx_type) const { CodecManager::UnicastConfigurationRequirements requirements = { .audio_context_type = ctx_type}; auto new_conf = CodecManager::GetInstance()->GetCodecConfig( Loading Loading @@ -1550,7 +1553,7 @@ LeAudioDeviceGroup::GetActiveConfiguration(void) const { } std::shared_ptr<const set_configurations::AudioSetConfiguration> LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) { LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) const { if (context_type == LeAudioContextType::UNINITIALIZED) { return nullptr; } Loading @@ -1572,60 +1575,9 @@ LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) { return GetCachedConfiguration(context_type); } std::optional<LeAudioCodecConfiguration> LeAudioDeviceGroup::GetCachedCodecConfigurationByDirection( LeAudioCodecConfiguration LeAudioDeviceGroup::GetAudioSessionCodecConfigForDirection( LeAudioContextType context_type, uint8_t direction) const { auto audio_set_conf = GetCachedConfiguration(context_type); if (!audio_set_conf) return std::nullopt; LeAudioCodecConfiguration group_config = {0, 0, 0, 0}; for (const auto& conf : audio_set_conf->confs.get(direction)) { if (group_config.sample_rate != 0 && conf.codec.GetSamplingFrequencyHz() != group_config.sample_rate) { log::warn( "stream configuration could not be determined (sampling frequency " "differs) for direction: {}", loghex(direction)); return std::nullopt; } group_config.sample_rate = conf.codec.GetSamplingFrequencyHz(); if (group_config.data_interval_us != 0 && conf.codec.GetDataIntervalUs() != group_config.data_interval_us) { log::warn( "stream configuration could not be determined (data interval " "differs) for direction: {}", loghex(direction)); return std::nullopt; } group_config.data_interval_us = conf.codec.GetDataIntervalUs(); if (group_config.bits_per_sample != 0 && conf.codec.GetBitsPerSample() != group_config.bits_per_sample) { log::warn( "stream configuration could not be determined (bits per sample " "differs) for direction: {}", loghex(direction)); return std::nullopt; } group_config.bits_per_sample = conf.codec.GetBitsPerSample(); log::assert_that( audio_set_conf->topology_info.has_value(), "No topology info, which is required to properly configure the ASEs"); group_config.num_channels += conf.codec.GetChannelCountPerIsoStream() * audio_set_conf->topology_info->device_count.get(direction); } if (group_config.IsInvalid()) return std::nullopt; return group_config; } std::optional<LeAudioCodecConfiguration> LeAudioDeviceGroup::GetCodecConfigurationByDirection( LeAudioContextType context_type, uint8_t direction) { const set_configurations::AudioSetConfiguration* conf = nullptr; bool is_valid = false; Loading @@ -1640,8 +1592,19 @@ LeAudioDeviceGroup::GetCodecConfigurationByDirection( UpdateAudioSetConfigurationCache(context_type); } /* Return the cached value */ return GetCachedCodecConfigurationByDirection(context_type, direction); auto audio_set_conf = GetCachedConfiguration(context_type); if (!audio_set_conf) return {0, 0, 0, 0}; auto group_config = utils::GetAudioSessionCodecConfigFromAudioSetConfiguration( *audio_set_conf.get(), direction); return group_config; } bool LeAudioDeviceGroup::HasCodecConfigurationForDirection( types::LeAudioContextType context_type, uint8_t direction) const { auto audio_set_conf = GetConfiguration(context_type); return audio_set_conf ? !audio_set_conf->confs.get(direction).empty() : false; } bool LeAudioDeviceGroup::IsAudioSetConfigurationAvailable( Loading Loading @@ -1864,6 +1827,8 @@ bool LeAudioDeviceGroup::IsConfiguredForContext( return false; } if (!stream_conf.conf) return false; /* Check if used configuration is same as the active one.*/ return (stream_conf.conf.get() == GetActiveConfiguration().get()); } Loading
system/bta/le_audio/device_groups.h +16 −9 Original line number Diff line number Diff line Loading @@ -76,6 +76,12 @@ class LeAudioDeviceGroup { types::CigState state_; } cig; bool IsGroupConfiguredTo( const set_configurations::AudioSetConfiguration& cfg) { if (!stream_conf.conf) return false; return cfg == *stream_conf.conf; } /* Current configuration strategy - recalculated on demand */ mutable std::optional<types::LeAudioConfigurationStrategy> strategy_ = std::nullopt; Loading Loading @@ -204,14 +210,15 @@ class LeAudioDeviceGroup { bool GetPresentationDelay(uint32_t* delay, uint8_t direction) const; uint16_t GetRemoteDelay(uint8_t direction) const; bool UpdateAudioContextAvailability(void); bool UpdateAudioSetConfigurationCache(types::LeAudioContextType ctx_type); bool UpdateAudioSetConfigurationCache( types::LeAudioContextType ctx_type) const; bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); std::shared_ptr<const set_configurations::AudioSetConfiguration> GetActiveConfiguration(void) const; bool IsPendingConfiguration(void) const; std::shared_ptr<const set_configurations::AudioSetConfiguration> GetConfiguration(types::LeAudioContextType ctx_type); GetConfiguration(types::LeAudioContextType ctx_type) const; std::shared_ptr<const set_configurations::AudioSetConfiguration> GetCachedConfiguration(types::LeAudioContextType ctx_type) const; void InvalidateCachedConfigurations(void); Loading @@ -225,10 +232,9 @@ class LeAudioDeviceGroup { bool IsAudioSetConfigurationSupported( LeAudioDevice* leAudioDevice, const set_configurations::AudioSetConfiguration* audio_set_conf) const; std::optional<LeAudioCodecConfiguration> GetCodecConfigurationByDirection( types::LeAudioContextType group_context_type, uint8_t direction); std::optional<LeAudioCodecConfiguration> GetCachedCodecConfigurationByDirection( LeAudioCodecConfiguration GetAudioSessionCodecConfigForDirection( types::LeAudioContextType group_context_type, uint8_t direction) const; bool HasCodecConfigurationForDirection( types::LeAudioContextType group_context_type, uint8_t direction) const; bool IsAudioSetConfigurationAvailable( types::LeAudioContextType group_context_type); Loading Loading @@ -432,7 +438,8 @@ class LeAudioDeviceGroup { * change. Stored as a pair of (is_valid_cache, configuration*). `pair.first` * being `false` means that the cached value should be refreshed. */ std::map<types::LeAudioContextType, mutable std::map< types::LeAudioContextType, std::pair<bool, const std::shared_ptr< set_configurations::AudioSetConfiguration>>> context_to_configuration_cache_map; Loading
system/bta/le_audio/devices_test.cc +50 −70 File changed.Preview size limit exceeded, changes collapsed. Show changes