Loading system/bta/le_audio/client.cc +38 −37 Original line number Diff line number Diff line Loading @@ -392,14 +392,14 @@ class LeAudioClientImpl : public LeAudioClient { auto location_update = group->ReloadAudioLocations(); group->ReloadAudioDirections(); std::optional<AudioContexts> new_group_updated_contexts = group->UpdateActiveContextsMap(leAudioDevice->GetAvailableContexts()); auto contexts_updated = group->UpdateAudioContextTypeAvailability( leAudioDevice->GetAvailableContexts()); if (new_group_updated_contexts || location_update) { if (contexts_updated || location_update) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } Loading Loading @@ -528,18 +528,18 @@ class LeAudioClientImpl : public LeAudioClient { /* Group may be destroyed once moved its last node to new group */ if (aseGroups_.FindById(old_group_id) != nullptr) { /* Removing node from group may touch its context integrity */ std::optional<AudioContexts> old_group_updated_contexts = old_group->UpdateActiveContextsMap(old_group->GetActiveContexts()); auto contexts_updated = old_group->UpdateAudioContextTypeAvailability( old_group->GetAvailableContexts()); bool group_conf_changed = old_group->ReloadAudioLocations(); group_conf_changed |= old_group->ReloadAudioDirections(); group_conf_changed |= old_group_updated_contexts.has_value(); group_conf_changed |= contexts_updated; if (group_conf_changed) { callbacks_->OnAudioConf(old_group->audio_directions_, old_group_id, old_group->snk_audio_locations_.to_ulong(), old_group->src_audio_locations_.to_ulong(), old_group->GetActiveContexts().value()); old_group->GetAvailableContexts().value()); } } Loading Loading @@ -595,18 +595,18 @@ class LeAudioClientImpl : public LeAudioClient { } /* Removing node from group touch its context integrity */ std::optional<AudioContexts> updated_contexts = group->UpdateActiveContextsMap(group->GetActiveContexts()); bool contexts_updated = group->UpdateAudioContextTypeAvailability( group->GetAvailableContexts()); bool group_conf_changed = group->ReloadAudioLocations(); group_conf_changed |= group->ReloadAudioDirections(); group_conf_changed |= updated_contexts.has_value(); group_conf_changed |= contexts_updated; if (group_conf_changed) callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } void GroupRemoveNode(const int group_id, const RawAddress& address) override { Loading Loading @@ -695,7 +695,7 @@ class LeAudioClientImpl : public LeAudioClient { return false; } if (!group->GetActiveContexts().test(context_type)) { if (!group->GetAvailableContexts().test(context_type)) { LOG(ERROR) << " Unsupported context type by remote device: " << ToHexString(context_type) << ". Switching to unspecified"; final_context_type = LeAudioContextType::UNSPECIFIED; Loading Loading @@ -1283,17 +1283,17 @@ class LeAudioClientImpl : public LeAudioClient { /* Update supported context types including internal capabilities */ LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); /* Active context map should be considered to be updated in response to /* Available context map should be considered to be updated in response to * PACs update. * Read of available context during initial attribute discovery. * Group would be assigned once service search is completed. */ if (group && group->UpdateActiveContextsMap( if (group && group->UpdateAudioContextTypeAvailability( leAudioDevice->GetAvailableContexts())) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } if (notify) { btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_); Loading @@ -1317,17 +1317,17 @@ class LeAudioClientImpl : public LeAudioClient { /* Update supported context types including internal capabilities */ LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); /* Active context map should be considered to be updated in response to /* Available context map should be considered to be updated in response to * PACs update. * Read of available context during initial attribute discovery. * Group would be assigned once service search is completed. */ if (group && group->UpdateActiveContextsMap( if (group && group->UpdateAudioContextTypeAvailability( leAudioDevice->GetAvailableContexts())) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } if (notify) { Loading Loading @@ -1378,7 +1378,7 @@ class LeAudioClientImpl : public LeAudioClient { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } else if (hdl == leAudioDevice->src_audio_locations_hdls_.val_hdl) { AudioLocations src_audio_locations; Loading Loading @@ -1420,7 +1420,7 @@ class LeAudioClientImpl : public LeAudioClient { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) { le_audio::client_parser::pacs::acs_available_audio_contexts Loading @@ -1433,7 +1433,7 @@ class LeAudioClientImpl : public LeAudioClient { avail_audio_contexts.src_avail_cont); if (updated_avail_contexts.any()) { /* Update scenario map considering changed active context types */ /* Update scenario map considering changed available context types */ LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); /* Read of available context during initial attribute discovery. Loading @@ -1447,15 +1447,17 @@ class LeAudioClientImpl : public LeAudioClient { if (group->IsInTransition() || (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING)) { group->SetPendingUpdateAvailableContexts(updated_avail_contexts); group->SetPendingAvailableContextsChange(updated_avail_contexts); return; } if (group->UpdateActiveContextsMap(updated_avail_contexts)) { auto contexts_updated = group->UpdateAudioContextTypeAvailability(updated_avail_contexts); if (contexts_updated) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } } Loading Loading @@ -3443,7 +3445,7 @@ class LeAudioClientImpl : public LeAudioClient { } metadata_context_types_ |= GetAllowedAudioContextsFromSourceMetadata( source_metadata, group->GetActiveContexts()); source_metadata, group->GetAvailableContexts()); if (stack_config_get_interface() ->get_pts_force_le_audio_multiple_contexts_metadata()) { Loading Loading @@ -3744,21 +3746,20 @@ class LeAudioClientImpl : public LeAudioClient { rxUnreceivedPackets, duplicatePackets); } void HandlePendingAvailableContexts(LeAudioDeviceGroup* group) { void HandlePendingAvailableContextsChange(LeAudioDeviceGroup* group) { if (!group) return; /* Update group configuration with pending available context */ std::optional<AudioContexts> pending_update_available_contexts = group->GetPendingUpdateAvailableContexts(); if (pending_update_available_contexts) { if (group->UpdateActiveContextsMap(*pending_update_available_contexts)) { /* Update group configuration with pending available context change */ auto contexts = group->GetPendingAvailableContextsChange(); if (contexts.any()) { auto success = group->UpdateAudioContextTypeAvailability(contexts); if (success) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } group->SetPendingUpdateAvailableContexts(std::nullopt); group->ClearPendingAvailableContextsChange(); } } Loading Loading @@ -3887,7 +3888,7 @@ class LeAudioClientImpl : public LeAudioClient { * so Audio HAL can Resume again. */ CancelStreamingRequest(); HandlePendingAvailableContexts(group); HandlePendingAvailableContextsChange(group); ReconfigurationComplete(previously_active_directions); } break; case GroupStreamStatus::CONFIGURED_AUTONOMOUS: Loading Loading @@ -3915,7 +3916,7 @@ class LeAudioClientImpl : public LeAudioClient { CancelStreamingRequest(); if (group) { NotifyUpperLayerGroupTurnedIdleDuringCall(group->group_id_); HandlePendingAvailableContexts(group); HandlePendingAvailableContextsChange(group); HandlePendingDeviceDisconnection(group); } break; Loading system/bta/le_audio/devices.cc +36 −36 Original line number Diff line number Diff line Loading @@ -720,32 +720,34 @@ uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) { return remote_delay_ms; } /* This method returns AudioContext value if support for any type has changed */ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap(void) { LOG_DEBUG(" group id: %d, active contexts: %s", group_id_, active_contexts_mask_.to_string().c_str()); return UpdateActiveContextsMap(active_contexts_mask_); void LeAudioDeviceGroup::UpdateAudioContextTypeAvailability(void) { LOG_DEBUG(" group id: %d, available contexts: %s", group_id_, group_available_contexts_.to_string().c_str()); UpdateAudioContextTypeAvailability(group_available_contexts_); } /* This method returns AudioContext value if support for any type has changed */ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( /* Returns true if support for any type in the whole group has changed, * otherwise false. */ bool LeAudioDeviceGroup::UpdateAudioContextTypeAvailability( AudioContexts update_contexts) { auto contexts = AudioContexts(); auto new_contexts = AudioContexts(); bool active_contexts_has_been_modified = false; if (update_contexts.none()) { LOG_DEBUG("No context updated"); return contexts; return false; } LOG_DEBUG("Updated context: %s", update_contexts.to_string().c_str()); for (LeAudioContextType ctx_type : types::kLeAudioContextAllTypesArray) { LOG_DEBUG("Checking context: %s", ToHexString(ctx_type).c_str()); if (!update_contexts.test(ctx_type)) { LOG_DEBUG("Configuration not in updated context"); /* Fill context bitset for possible returned value if updated */ if (active_context_to_configuration_map.count(ctx_type) > 0) contexts.set(ctx_type); if (available_context_to_configuration_map.count(ctx_type) > 0) new_contexts.set(ctx_type); continue; } Loading @@ -753,8 +755,8 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( auto new_conf = FindFirstSupportedConfiguration(ctx_type); bool ctx_previously_not_supported = (active_context_to_configuration_map.count(ctx_type) == 0 || active_context_to_configuration_map[ctx_type] == nullptr); (available_context_to_configuration_map.count(ctx_type) == 0 || available_context_to_configuration_map[ctx_type] == nullptr); /* Check if support for context type has changed */ if (ctx_previously_not_supported) { /* Current configuration for context type is empty */ Loading @@ -763,22 +765,22 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( continue; } else { /* Configuration changes from empty to some */ contexts.set(ctx_type); new_contexts.set(ctx_type); active_contexts_has_been_modified = true; } } else { /* Current configuration for context type is not empty */ if (new_conf == nullptr) { /* Configuration changed to empty */ contexts.unset(ctx_type); new_contexts.unset(ctx_type); active_contexts_has_been_modified = true; } else if (new_conf != active_context_to_configuration_map[ctx_type]) { } else if (new_conf != available_context_to_configuration_map[ctx_type]) { /* Configuration changed to any other */ contexts.set(ctx_type); new_contexts.set(ctx_type); active_contexts_has_been_modified = true; } else { /* Configuration is the same */ contexts.set(ctx_type); new_contexts.set(ctx_type); continue; } } Loading @@ -787,20 +789,18 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( "updated context: %s, %s -> %s", ToHexString(ctx_type).c_str(), (ctx_previously_not_supported ? "empty" : active_context_to_configuration_map[ctx_type]->name.c_str()), : available_context_to_configuration_map[ctx_type]->name.c_str()), (new_conf != nullptr ? new_conf->name.c_str() : "empty")); active_context_to_configuration_map[ctx_type] = new_conf; available_context_to_configuration_map[ctx_type] = new_conf; } /* Some contexts have changed, return new active context bitset */ /* Some contexts have changed, return new available context bitset */ if (active_contexts_has_been_modified) { active_contexts_mask_ = contexts; return contexts; group_available_contexts_ = new_contexts; } /* Nothing has changed */ return std::nullopt; return active_contexts_has_been_modified; } bool LeAudioDeviceGroup::ReloadAudioLocations(void) { Loading Loading @@ -1600,21 +1600,21 @@ bool LeAudioDeviceGroup::ConfigureAses( LOG(INFO) << "Choosed ASE Configuration for group: " << this->group_id_ << " configuration: " << audio_set_conf->name; active_context_type_ = context_type; configuration_context_type_ = context_type; metadata_context_type_ = metadata_context_type; return true; } const set_configurations::AudioSetConfiguration* LeAudioDeviceGroup::GetActiveConfiguration(void) { return active_context_to_configuration_map[active_context_type_]; return available_context_to_configuration_map[configuration_context_type_]; } std::optional<LeAudioCodecConfiguration> LeAudioDeviceGroup::GetCodecConfigurationByDirection( types::LeAudioContextType group_context_type, uint8_t direction) { const set_configurations::AudioSetConfiguration* audio_set_conf = active_context_to_configuration_map[group_context_type]; available_context_to_configuration_map[group_context_type]; LeAudioCodecConfiguration group_config = {0, 0, 0, 0}; if (!audio_set_conf) return std::nullopt; Loading Loading @@ -1662,10 +1662,10 @@ LeAudioDeviceGroup::GetCodecConfigurationByDirection( bool LeAudioDeviceGroup::IsContextSupported( types::LeAudioContextType group_context_type) { auto iter = active_context_to_configuration_map.find(group_context_type); if (iter == active_context_to_configuration_map.end()) return false; auto iter = available_context_to_configuration_map.find(group_context_type); if (iter == available_context_to_configuration_map.end()) return false; return active_context_to_configuration_map[group_context_type] != nullptr; return available_context_to_configuration_map[group_context_type] != nullptr; } bool LeAudioDeviceGroup::IsMetadataChanged( Loading Loading @@ -1872,14 +1872,14 @@ bool LeAudioDeviceGroup::Configure(LeAudioContextType context_type, AudioContexts metadata_context_type, std::vector<uint8_t> ccid_list) { const set_configurations::AudioSetConfiguration* conf = active_context_to_configuration_map[context_type]; available_context_to_configuration_map[context_type]; DLOG(INFO) << __func__; if (!conf) { LOG(ERROR) << __func__ << ", requested context type: " << loghex(static_cast<uint16_t>(context_type)) << ", is in mismatch with cached active contexts"; << ", is in mismatch with cached available contexts"; return false; } Loading @@ -1888,7 +1888,7 @@ bool LeAudioDeviceGroup::Configure(LeAudioContextType context_type, if (!ConfigureAses(conf, context_type, metadata_context_type, ccid_list)) { LOG(ERROR) << __func__ << ", requested pick ASE config context type: " << loghex(static_cast<uint16_t>(context_type)) << ", is in mismatch with cached active contexts"; << ", is in mismatch with cached available contexts"; return false; } Loading @@ -1910,9 +1910,9 @@ void LeAudioDeviceGroup::Dump(int fd, int active_group_id) { << " state: " << GetState() << ",\ttarget state: " << GetTargetState() << ",\tcig state: " << cig_state_ << "\n" << " group available contexts: " << GetActiveContexts() << "\n" << " group available contexts: " << GetAvailableContexts() << " configuration context type: " << bluetooth::common::ToString(GetCurrentContextType()).c_str() << "\n" << bluetooth::common::ToString(GetConfigurationContextType()).c_str() << " active configuration name: " << (active_conf ? active_conf->name : " not set") << "\n" << " stream configuration: " Loading system/bta/le_audio/devices.h +42 −23 Original line number Diff line number Diff line Loading @@ -234,10 +234,11 @@ class LeAudioDeviceGroup { audio_directions_(0), transport_latency_mtos_us_(0), transport_latency_stom_us_(0), active_context_type_(types::LeAudioContextType::UNINITIALIZED), metadata_context_type_(0), active_contexts_mask_(0), pending_update_available_contexts_(std::nullopt), configuration_context_type_(types::LeAudioContextType::UNINITIALIZED), metadata_context_type_(types::LeAudioContextType::UNINITIALIZED), group_available_contexts_(types::LeAudioContextType::UNINITIALIZED), pending_group_available_contexts_change_( types::LeAudioContextType::UNINITIALIZED), target_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE), current_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {} ~LeAudioDeviceGroup(void); Loading Loading @@ -300,9 +301,8 @@ class LeAudioDeviceGroup { uint8_t GetTargetPhy(uint8_t direction); bool GetPresentationDelay(uint32_t* delay, uint8_t direction); uint16_t GetRemoteDelay(uint8_t direction); std::optional<types::AudioContexts> UpdateActiveContextsMap( types::AudioContexts contexts); std::optional<types::AudioContexts> UpdateActiveContextsMap(void); bool UpdateAudioContextTypeAvailability(types::AudioContexts contexts); void UpdateAudioContextTypeAvailability(void); bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); const set_configurations::AudioSetConfiguration* GetActiveConfiguration(void); Loading Loading @@ -334,25 +334,31 @@ class LeAudioDeviceGroup { target_state_ = state; } inline std::optional<types::AudioContexts> GetPendingUpdateAvailableContexts() const { return pending_update_available_contexts_; /* Returns context types for which support was recently added or removed */ inline types::AudioContexts GetPendingAvailableContextsChange() const { return pending_group_available_contexts_change_; } inline void SetPendingUpdateAvailableContexts( std::optional<types::AudioContexts> audio_contexts) { pending_update_available_contexts_ = audio_contexts; /* Set which context types were recently added or removed */ inline void SetPendingAvailableContextsChange( types::AudioContexts audio_contexts) { pending_group_available_contexts_change_ = audio_contexts; } inline void ClearPendingAvailableContextsChange() { pending_group_available_contexts_change_.clear(); } inline types::LeAudioContextType GetCurrentContextType(void) const { return active_context_type_; inline types::LeAudioContextType GetConfigurationContextType(void) const { return configuration_context_type_; } inline types::AudioContexts GetMetadataContextType(void) const { inline types::AudioContexts GetMetadataContexts(void) const { return metadata_context_type_; } inline types::AudioContexts GetActiveContexts(void) { return active_contexts_mask_; inline types::AudioContexts GetAvailableContexts(void) { return group_available_contexts_; } bool IsInTransition(void); Loading @@ -375,15 +381,28 @@ class LeAudioDeviceGroup { types::LeAudioContextType context_type); uint32_t GetTransportLatencyUs(uint8_t direction); /* Mask and table of currently supported contexts */ types::LeAudioContextType active_context_type_; /* Current configuration and metadata context types */ types::LeAudioContextType configuration_context_type_; types::AudioContexts metadata_context_type_; types::AudioContexts active_contexts_mask_; std::optional<types::AudioContexts> pending_update_available_contexts_; /* Mask of contexts that the whole group can handle at it's current state * It's being updated each time group members connect, disconnect or their * individual available audio contexts are changed. */ types::AudioContexts group_available_contexts_; /* A temporary mask for bits which were either added or removed when the * group available context type changes. It usually means we should refresh * our group configuration capabilities to clear this. */ types::AudioContexts pending_group_available_contexts_change_; /* Possible configuration cache - refreshed on each group context availability * change */ std::map<types::LeAudioContextType, const set_configurations::AudioSetConfiguration*> active_context_to_configuration_map; available_context_to_configuration_map; types::AseState target_state_; types::AseState current_state_; Loading system/bta/le_audio/devices_test.cc +8 −7 Original line number Diff line number Diff line Loading @@ -515,8 +515,8 @@ class LeAudioAseConfigurationTest : public Test { data[i].device->src_pacs_ = src_pac_builder.Get(); } /* Stimulate update of active context map */ group_->UpdateActiveContextsMap(AudioContexts(context_type)); /* Stimulate update of available context map */ group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type)); ASSERT_EQ(success_expected, group_->Configure(context_type, AudioContexts(context_type))); Loading Loading @@ -586,8 +586,8 @@ class LeAudioAseConfigurationTest : public Test { interesting_configuration = false; } } /* Stimulate update of active context map */ group_->UpdateActiveContextsMap(AudioContexts(context_type)); /* Stimulate update of available context map */ group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type)); auto configuration_result = group_->Configure(context_type, AudioContexts(context_type)); Loading Loading @@ -699,8 +699,9 @@ class LeAudioAseConfigurationTest : public Test { success_expected = false; } /* Stimulate update of active context map */ group_->UpdateActiveContextsMap(AudioContexts(context_type)); /* Stimulate update of available context map */ group_->UpdateAudioContextTypeAvailability( AudioContexts(context_type)); ASSERT_EQ( success_expected, group_->Configure(context_type, AudioContexts(context_type))); Loading Loading @@ -976,7 +977,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { std::vector<uint8_t> ccid_list; for (auto& ent : configuration->confs) { if (ent.direction == ::le_audio::types::kLeAudioDirectionSink) { left->ConfigureAses(ent, group_->GetCurrentContextType(), left->ConfigureAses(ent, group_->GetConfigurationContextType(), &number_of_active_ases, group_snk_audio_location, group_src_audio_location, false, ::le_audio::types::AudioContexts(), ccid_list); Loading system/bta/le_audio/le_audio_client_test.cc +2 −2 Original line number Diff line number Diff line Loading @@ -706,8 +706,8 @@ class UnicastTestNoInit : public Test { return false; } group->Configure(group->GetCurrentContextType(), group->GetMetadataContextType(), {}); group->Configure(group->GetConfigurationContextType(), group->GetMetadataContexts(), {}); if (!group->CigAssignCisIds(leAudioDevice)) return false; group->CigAssignCisConnHandlesToAses(leAudioDevice); Loading Loading
system/bta/le_audio/client.cc +38 −37 Original line number Diff line number Diff line Loading @@ -392,14 +392,14 @@ class LeAudioClientImpl : public LeAudioClient { auto location_update = group->ReloadAudioLocations(); group->ReloadAudioDirections(); std::optional<AudioContexts> new_group_updated_contexts = group->UpdateActiveContextsMap(leAudioDevice->GetAvailableContexts()); auto contexts_updated = group->UpdateAudioContextTypeAvailability( leAudioDevice->GetAvailableContexts()); if (new_group_updated_contexts || location_update) { if (contexts_updated || location_update) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } Loading Loading @@ -528,18 +528,18 @@ class LeAudioClientImpl : public LeAudioClient { /* Group may be destroyed once moved its last node to new group */ if (aseGroups_.FindById(old_group_id) != nullptr) { /* Removing node from group may touch its context integrity */ std::optional<AudioContexts> old_group_updated_contexts = old_group->UpdateActiveContextsMap(old_group->GetActiveContexts()); auto contexts_updated = old_group->UpdateAudioContextTypeAvailability( old_group->GetAvailableContexts()); bool group_conf_changed = old_group->ReloadAudioLocations(); group_conf_changed |= old_group->ReloadAudioDirections(); group_conf_changed |= old_group_updated_contexts.has_value(); group_conf_changed |= contexts_updated; if (group_conf_changed) { callbacks_->OnAudioConf(old_group->audio_directions_, old_group_id, old_group->snk_audio_locations_.to_ulong(), old_group->src_audio_locations_.to_ulong(), old_group->GetActiveContexts().value()); old_group->GetAvailableContexts().value()); } } Loading Loading @@ -595,18 +595,18 @@ class LeAudioClientImpl : public LeAudioClient { } /* Removing node from group touch its context integrity */ std::optional<AudioContexts> updated_contexts = group->UpdateActiveContextsMap(group->GetActiveContexts()); bool contexts_updated = group->UpdateAudioContextTypeAvailability( group->GetAvailableContexts()); bool group_conf_changed = group->ReloadAudioLocations(); group_conf_changed |= group->ReloadAudioDirections(); group_conf_changed |= updated_contexts.has_value(); group_conf_changed |= contexts_updated; if (group_conf_changed) callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } void GroupRemoveNode(const int group_id, const RawAddress& address) override { Loading Loading @@ -695,7 +695,7 @@ class LeAudioClientImpl : public LeAudioClient { return false; } if (!group->GetActiveContexts().test(context_type)) { if (!group->GetAvailableContexts().test(context_type)) { LOG(ERROR) << " Unsupported context type by remote device: " << ToHexString(context_type) << ". Switching to unspecified"; final_context_type = LeAudioContextType::UNSPECIFIED; Loading Loading @@ -1283,17 +1283,17 @@ class LeAudioClientImpl : public LeAudioClient { /* Update supported context types including internal capabilities */ LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); /* Active context map should be considered to be updated in response to /* Available context map should be considered to be updated in response to * PACs update. * Read of available context during initial attribute discovery. * Group would be assigned once service search is completed. */ if (group && group->UpdateActiveContextsMap( if (group && group->UpdateAudioContextTypeAvailability( leAudioDevice->GetAvailableContexts())) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } if (notify) { btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_); Loading @@ -1317,17 +1317,17 @@ class LeAudioClientImpl : public LeAudioClient { /* Update supported context types including internal capabilities */ LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); /* Active context map should be considered to be updated in response to /* Available context map should be considered to be updated in response to * PACs update. * Read of available context during initial attribute discovery. * Group would be assigned once service search is completed. */ if (group && group->UpdateActiveContextsMap( if (group && group->UpdateAudioContextTypeAvailability( leAudioDevice->GetAvailableContexts())) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } if (notify) { Loading Loading @@ -1378,7 +1378,7 @@ class LeAudioClientImpl : public LeAudioClient { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } else if (hdl == leAudioDevice->src_audio_locations_hdls_.val_hdl) { AudioLocations src_audio_locations; Loading Loading @@ -1420,7 +1420,7 @@ class LeAudioClientImpl : public LeAudioClient { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) { le_audio::client_parser::pacs::acs_available_audio_contexts Loading @@ -1433,7 +1433,7 @@ class LeAudioClientImpl : public LeAudioClient { avail_audio_contexts.src_avail_cont); if (updated_avail_contexts.any()) { /* Update scenario map considering changed active context types */ /* Update scenario map considering changed available context types */ LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); /* Read of available context during initial attribute discovery. Loading @@ -1447,15 +1447,17 @@ class LeAudioClientImpl : public LeAudioClient { if (group->IsInTransition() || (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING)) { group->SetPendingUpdateAvailableContexts(updated_avail_contexts); group->SetPendingAvailableContextsChange(updated_avail_contexts); return; } if (group->UpdateActiveContextsMap(updated_avail_contexts)) { auto contexts_updated = group->UpdateAudioContextTypeAvailability(updated_avail_contexts); if (contexts_updated) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } } } Loading Loading @@ -3443,7 +3445,7 @@ class LeAudioClientImpl : public LeAudioClient { } metadata_context_types_ |= GetAllowedAudioContextsFromSourceMetadata( source_metadata, group->GetActiveContexts()); source_metadata, group->GetAvailableContexts()); if (stack_config_get_interface() ->get_pts_force_le_audio_multiple_contexts_metadata()) { Loading Loading @@ -3744,21 +3746,20 @@ class LeAudioClientImpl : public LeAudioClient { rxUnreceivedPackets, duplicatePackets); } void HandlePendingAvailableContexts(LeAudioDeviceGroup* group) { void HandlePendingAvailableContextsChange(LeAudioDeviceGroup* group) { if (!group) return; /* Update group configuration with pending available context */ std::optional<AudioContexts> pending_update_available_contexts = group->GetPendingUpdateAvailableContexts(); if (pending_update_available_contexts) { if (group->UpdateActiveContextsMap(*pending_update_available_contexts)) { /* Update group configuration with pending available context change */ auto contexts = group->GetPendingAvailableContextsChange(); if (contexts.any()) { auto success = group->UpdateAudioContextTypeAvailability(contexts); if (success) { callbacks_->OnAudioConf(group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(), group->src_audio_locations_.to_ulong(), group->GetActiveContexts().value()); group->GetAvailableContexts().value()); } group->SetPendingUpdateAvailableContexts(std::nullopt); group->ClearPendingAvailableContextsChange(); } } Loading Loading @@ -3887,7 +3888,7 @@ class LeAudioClientImpl : public LeAudioClient { * so Audio HAL can Resume again. */ CancelStreamingRequest(); HandlePendingAvailableContexts(group); HandlePendingAvailableContextsChange(group); ReconfigurationComplete(previously_active_directions); } break; case GroupStreamStatus::CONFIGURED_AUTONOMOUS: Loading Loading @@ -3915,7 +3916,7 @@ class LeAudioClientImpl : public LeAudioClient { CancelStreamingRequest(); if (group) { NotifyUpperLayerGroupTurnedIdleDuringCall(group->group_id_); HandlePendingAvailableContexts(group); HandlePendingAvailableContextsChange(group); HandlePendingDeviceDisconnection(group); } break; Loading
system/bta/le_audio/devices.cc +36 −36 Original line number Diff line number Diff line Loading @@ -720,32 +720,34 @@ uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) { return remote_delay_ms; } /* This method returns AudioContext value if support for any type has changed */ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap(void) { LOG_DEBUG(" group id: %d, active contexts: %s", group_id_, active_contexts_mask_.to_string().c_str()); return UpdateActiveContextsMap(active_contexts_mask_); void LeAudioDeviceGroup::UpdateAudioContextTypeAvailability(void) { LOG_DEBUG(" group id: %d, available contexts: %s", group_id_, group_available_contexts_.to_string().c_str()); UpdateAudioContextTypeAvailability(group_available_contexts_); } /* This method returns AudioContext value if support for any type has changed */ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( /* Returns true if support for any type in the whole group has changed, * otherwise false. */ bool LeAudioDeviceGroup::UpdateAudioContextTypeAvailability( AudioContexts update_contexts) { auto contexts = AudioContexts(); auto new_contexts = AudioContexts(); bool active_contexts_has_been_modified = false; if (update_contexts.none()) { LOG_DEBUG("No context updated"); return contexts; return false; } LOG_DEBUG("Updated context: %s", update_contexts.to_string().c_str()); for (LeAudioContextType ctx_type : types::kLeAudioContextAllTypesArray) { LOG_DEBUG("Checking context: %s", ToHexString(ctx_type).c_str()); if (!update_contexts.test(ctx_type)) { LOG_DEBUG("Configuration not in updated context"); /* Fill context bitset for possible returned value if updated */ if (active_context_to_configuration_map.count(ctx_type) > 0) contexts.set(ctx_type); if (available_context_to_configuration_map.count(ctx_type) > 0) new_contexts.set(ctx_type); continue; } Loading @@ -753,8 +755,8 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( auto new_conf = FindFirstSupportedConfiguration(ctx_type); bool ctx_previously_not_supported = (active_context_to_configuration_map.count(ctx_type) == 0 || active_context_to_configuration_map[ctx_type] == nullptr); (available_context_to_configuration_map.count(ctx_type) == 0 || available_context_to_configuration_map[ctx_type] == nullptr); /* Check if support for context type has changed */ if (ctx_previously_not_supported) { /* Current configuration for context type is empty */ Loading @@ -763,22 +765,22 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( continue; } else { /* Configuration changes from empty to some */ contexts.set(ctx_type); new_contexts.set(ctx_type); active_contexts_has_been_modified = true; } } else { /* Current configuration for context type is not empty */ if (new_conf == nullptr) { /* Configuration changed to empty */ contexts.unset(ctx_type); new_contexts.unset(ctx_type); active_contexts_has_been_modified = true; } else if (new_conf != active_context_to_configuration_map[ctx_type]) { } else if (new_conf != available_context_to_configuration_map[ctx_type]) { /* Configuration changed to any other */ contexts.set(ctx_type); new_contexts.set(ctx_type); active_contexts_has_been_modified = true; } else { /* Configuration is the same */ contexts.set(ctx_type); new_contexts.set(ctx_type); continue; } } Loading @@ -787,20 +789,18 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap( "updated context: %s, %s -> %s", ToHexString(ctx_type).c_str(), (ctx_previously_not_supported ? "empty" : active_context_to_configuration_map[ctx_type]->name.c_str()), : available_context_to_configuration_map[ctx_type]->name.c_str()), (new_conf != nullptr ? new_conf->name.c_str() : "empty")); active_context_to_configuration_map[ctx_type] = new_conf; available_context_to_configuration_map[ctx_type] = new_conf; } /* Some contexts have changed, return new active context bitset */ /* Some contexts have changed, return new available context bitset */ if (active_contexts_has_been_modified) { active_contexts_mask_ = contexts; return contexts; group_available_contexts_ = new_contexts; } /* Nothing has changed */ return std::nullopt; return active_contexts_has_been_modified; } bool LeAudioDeviceGroup::ReloadAudioLocations(void) { Loading Loading @@ -1600,21 +1600,21 @@ bool LeAudioDeviceGroup::ConfigureAses( LOG(INFO) << "Choosed ASE Configuration for group: " << this->group_id_ << " configuration: " << audio_set_conf->name; active_context_type_ = context_type; configuration_context_type_ = context_type; metadata_context_type_ = metadata_context_type; return true; } const set_configurations::AudioSetConfiguration* LeAudioDeviceGroup::GetActiveConfiguration(void) { return active_context_to_configuration_map[active_context_type_]; return available_context_to_configuration_map[configuration_context_type_]; } std::optional<LeAudioCodecConfiguration> LeAudioDeviceGroup::GetCodecConfigurationByDirection( types::LeAudioContextType group_context_type, uint8_t direction) { const set_configurations::AudioSetConfiguration* audio_set_conf = active_context_to_configuration_map[group_context_type]; available_context_to_configuration_map[group_context_type]; LeAudioCodecConfiguration group_config = {0, 0, 0, 0}; if (!audio_set_conf) return std::nullopt; Loading Loading @@ -1662,10 +1662,10 @@ LeAudioDeviceGroup::GetCodecConfigurationByDirection( bool LeAudioDeviceGroup::IsContextSupported( types::LeAudioContextType group_context_type) { auto iter = active_context_to_configuration_map.find(group_context_type); if (iter == active_context_to_configuration_map.end()) return false; auto iter = available_context_to_configuration_map.find(group_context_type); if (iter == available_context_to_configuration_map.end()) return false; return active_context_to_configuration_map[group_context_type] != nullptr; return available_context_to_configuration_map[group_context_type] != nullptr; } bool LeAudioDeviceGroup::IsMetadataChanged( Loading Loading @@ -1872,14 +1872,14 @@ bool LeAudioDeviceGroup::Configure(LeAudioContextType context_type, AudioContexts metadata_context_type, std::vector<uint8_t> ccid_list) { const set_configurations::AudioSetConfiguration* conf = active_context_to_configuration_map[context_type]; available_context_to_configuration_map[context_type]; DLOG(INFO) << __func__; if (!conf) { LOG(ERROR) << __func__ << ", requested context type: " << loghex(static_cast<uint16_t>(context_type)) << ", is in mismatch with cached active contexts"; << ", is in mismatch with cached available contexts"; return false; } Loading @@ -1888,7 +1888,7 @@ bool LeAudioDeviceGroup::Configure(LeAudioContextType context_type, if (!ConfigureAses(conf, context_type, metadata_context_type, ccid_list)) { LOG(ERROR) << __func__ << ", requested pick ASE config context type: " << loghex(static_cast<uint16_t>(context_type)) << ", is in mismatch with cached active contexts"; << ", is in mismatch with cached available contexts"; return false; } Loading @@ -1910,9 +1910,9 @@ void LeAudioDeviceGroup::Dump(int fd, int active_group_id) { << " state: " << GetState() << ",\ttarget state: " << GetTargetState() << ",\tcig state: " << cig_state_ << "\n" << " group available contexts: " << GetActiveContexts() << "\n" << " group available contexts: " << GetAvailableContexts() << " configuration context type: " << bluetooth::common::ToString(GetCurrentContextType()).c_str() << "\n" << bluetooth::common::ToString(GetConfigurationContextType()).c_str() << " active configuration name: " << (active_conf ? active_conf->name : " not set") << "\n" << " stream configuration: " Loading
system/bta/le_audio/devices.h +42 −23 Original line number Diff line number Diff line Loading @@ -234,10 +234,11 @@ class LeAudioDeviceGroup { audio_directions_(0), transport_latency_mtos_us_(0), transport_latency_stom_us_(0), active_context_type_(types::LeAudioContextType::UNINITIALIZED), metadata_context_type_(0), active_contexts_mask_(0), pending_update_available_contexts_(std::nullopt), configuration_context_type_(types::LeAudioContextType::UNINITIALIZED), metadata_context_type_(types::LeAudioContextType::UNINITIALIZED), group_available_contexts_(types::LeAudioContextType::UNINITIALIZED), pending_group_available_contexts_change_( types::LeAudioContextType::UNINITIALIZED), target_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE), current_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {} ~LeAudioDeviceGroup(void); Loading Loading @@ -300,9 +301,8 @@ class LeAudioDeviceGroup { uint8_t GetTargetPhy(uint8_t direction); bool GetPresentationDelay(uint32_t* delay, uint8_t direction); uint16_t GetRemoteDelay(uint8_t direction); std::optional<types::AudioContexts> UpdateActiveContextsMap( types::AudioContexts contexts); std::optional<types::AudioContexts> UpdateActiveContextsMap(void); bool UpdateAudioContextTypeAvailability(types::AudioContexts contexts); void UpdateAudioContextTypeAvailability(void); bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); const set_configurations::AudioSetConfiguration* GetActiveConfiguration(void); Loading Loading @@ -334,25 +334,31 @@ class LeAudioDeviceGroup { target_state_ = state; } inline std::optional<types::AudioContexts> GetPendingUpdateAvailableContexts() const { return pending_update_available_contexts_; /* Returns context types for which support was recently added or removed */ inline types::AudioContexts GetPendingAvailableContextsChange() const { return pending_group_available_contexts_change_; } inline void SetPendingUpdateAvailableContexts( std::optional<types::AudioContexts> audio_contexts) { pending_update_available_contexts_ = audio_contexts; /* Set which context types were recently added or removed */ inline void SetPendingAvailableContextsChange( types::AudioContexts audio_contexts) { pending_group_available_contexts_change_ = audio_contexts; } inline void ClearPendingAvailableContextsChange() { pending_group_available_contexts_change_.clear(); } inline types::LeAudioContextType GetCurrentContextType(void) const { return active_context_type_; inline types::LeAudioContextType GetConfigurationContextType(void) const { return configuration_context_type_; } inline types::AudioContexts GetMetadataContextType(void) const { inline types::AudioContexts GetMetadataContexts(void) const { return metadata_context_type_; } inline types::AudioContexts GetActiveContexts(void) { return active_contexts_mask_; inline types::AudioContexts GetAvailableContexts(void) { return group_available_contexts_; } bool IsInTransition(void); Loading @@ -375,15 +381,28 @@ class LeAudioDeviceGroup { types::LeAudioContextType context_type); uint32_t GetTransportLatencyUs(uint8_t direction); /* Mask and table of currently supported contexts */ types::LeAudioContextType active_context_type_; /* Current configuration and metadata context types */ types::LeAudioContextType configuration_context_type_; types::AudioContexts metadata_context_type_; types::AudioContexts active_contexts_mask_; std::optional<types::AudioContexts> pending_update_available_contexts_; /* Mask of contexts that the whole group can handle at it's current state * It's being updated each time group members connect, disconnect or their * individual available audio contexts are changed. */ types::AudioContexts group_available_contexts_; /* A temporary mask for bits which were either added or removed when the * group available context type changes. It usually means we should refresh * our group configuration capabilities to clear this. */ types::AudioContexts pending_group_available_contexts_change_; /* Possible configuration cache - refreshed on each group context availability * change */ std::map<types::LeAudioContextType, const set_configurations::AudioSetConfiguration*> active_context_to_configuration_map; available_context_to_configuration_map; types::AseState target_state_; types::AseState current_state_; Loading
system/bta/le_audio/devices_test.cc +8 −7 Original line number Diff line number Diff line Loading @@ -515,8 +515,8 @@ class LeAudioAseConfigurationTest : public Test { data[i].device->src_pacs_ = src_pac_builder.Get(); } /* Stimulate update of active context map */ group_->UpdateActiveContextsMap(AudioContexts(context_type)); /* Stimulate update of available context map */ group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type)); ASSERT_EQ(success_expected, group_->Configure(context_type, AudioContexts(context_type))); Loading Loading @@ -586,8 +586,8 @@ class LeAudioAseConfigurationTest : public Test { interesting_configuration = false; } } /* Stimulate update of active context map */ group_->UpdateActiveContextsMap(AudioContexts(context_type)); /* Stimulate update of available context map */ group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type)); auto configuration_result = group_->Configure(context_type, AudioContexts(context_type)); Loading Loading @@ -699,8 +699,9 @@ class LeAudioAseConfigurationTest : public Test { success_expected = false; } /* Stimulate update of active context map */ group_->UpdateActiveContextsMap(AudioContexts(context_type)); /* Stimulate update of available context map */ group_->UpdateAudioContextTypeAvailability( AudioContexts(context_type)); ASSERT_EQ( success_expected, group_->Configure(context_type, AudioContexts(context_type))); Loading Loading @@ -976,7 +977,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { std::vector<uint8_t> ccid_list; for (auto& ent : configuration->confs) { if (ent.direction == ::le_audio::types::kLeAudioDirectionSink) { left->ConfigureAses(ent, group_->GetCurrentContextType(), left->ConfigureAses(ent, group_->GetConfigurationContextType(), &number_of_active_ases, group_snk_audio_location, group_src_audio_location, false, ::le_audio::types::AudioContexts(), ccid_list); Loading
system/bta/le_audio/le_audio_client_test.cc +2 −2 Original line number Diff line number Diff line Loading @@ -706,8 +706,8 @@ class UnicastTestNoInit : public Test { return false; } group->Configure(group->GetCurrentContextType(), group->GetMetadataContextType(), {}); group->Configure(group->GetConfigurationContextType(), group->GetMetadataContexts(), {}); if (!group->CigAssignCisIds(leAudioDevice)) return false; group->CigAssignCisConnHandlesToAses(leAudioDevice); Loading