Loading system/bta/le_audio/client.cc +12 −0 Original line number Diff line number Diff line Loading @@ -518,6 +518,12 @@ class LeAudioClientImpl : public LeAudioClient { } while (leAudioDevice); } void OnDeviceAutonomousStateTransitionTimeout(LeAudioDevice* leAudioDevice) { LOG_ERROR("Device %s, failed to complete autonomous transition", ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_)); DisconnectDevice(leAudioDevice, true); } void UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup* group) { bool group_conf_changed = group->ReloadAudioLocations(); group_conf_changed |= group->ReloadAudioDirections(); Loading Loading @@ -5530,6 +5536,12 @@ class CallbacksImpl : public LeAudioGroupStateMachine::Callbacks { if (instance) instance->OnLeAudioDeviceSetStateTimeout(group_id); } void OnDeviceAutonomousStateTransitionTimeout( LeAudioDevice* leAudioDevice) override { if (instance) instance->OnDeviceAutonomousStateTransitionTimeout(leAudioDevice); } void OnUpdatedCisConfiguration(int group_id, uint8_t direction) { if (instance) instance->OnUpdatedCisConfiguration(group_id, direction); } Loading system/bta/le_audio/devices.cc +8 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,9 @@ void LeAudioDevice::ClearPACs(void) { LeAudioDevice::~LeAudioDevice(void) { alarm_free(link_quality_timer); for (auto& ase : ases_) { alarm_free(ase.autonomous_operation_timer_); } this->ClearPACs(); } Loading Loading @@ -946,6 +949,11 @@ void LeAudioDevice::DeactivateAllAses(void) { ase.cis_conn_hdl, bluetooth::common::ToString(ase.cis_state).c_str(), bluetooth::common::ToString(ase.data_path_state).c_str()); } if (alarm_is_scheduled(ase.autonomous_operation_timer_)) { alarm_free(ase.autonomous_operation_timer_); ase.autonomous_operation_timer_ = NULL; ase.autonomous_target_state_ = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE; } ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE; ase.cis_state = CisState::IDLE; ase.data_path_state = DataPathState::IDLE; Loading system/bta/le_audio/le_audio_types.h +7 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "bta_le_audio_uuids.h" #include "btm_iso_api_types.h" #include "osi/include/alarm.h" namespace le_audio { Loading Loading @@ -722,6 +723,8 @@ struct ase { pres_delay_max(0), preferred_pres_delay_min(0), preferred_pres_delay_max(0), autonomous_operation_timer_(nullptr), autonomous_target_state_(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE), state(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {} struct hdl_pair hdls; Loading Loading @@ -761,6 +764,10 @@ struct ase { std::vector<uint8_t> metadata; /* Autonomous change data */ alarm_t* autonomous_operation_timer_; types::AseState autonomous_target_state_; AseState state; }; Loading system/bta/le_audio/state_machine.cc +58 −2 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ using le_audio::types::LeAudioContextType; namespace { constexpr int linkQualityCheckInterval = 4000; constexpr int kAutonomousTransitionTimeoutMs = 5000; static void link_quality_cb(void* data) { // very ugly, but we need to pass just two bytes Loading Loading @@ -2075,6 +2076,12 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); /* Remote may autonomously bring ASEs to QoS configured state */ if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { ProcessAutonomousDisable(leAudioDevice, ase); } /* Process the Disable Transition of the rest of group members if no * more ASE notifications has to come from this device. */ if (leAudioDevice->IsReadyToSuspendStream()) ProcessGroupDisable(group); Loading Loading @@ -2670,6 +2677,22 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { } } void ScheduleAutonomousOperationTimer(AseState target_state, LeAudioDevice* leAudioDevice, struct ase* ase) { ase->autonomous_target_state_ = target_state; ase->autonomous_operation_timer_ = alarm_new("LeAudioAutonomousOperationTimeout"); alarm_set_on_mloop( ase->autonomous_operation_timer_, kAutonomousTransitionTimeoutMs, [](void* data) { LeAudioDevice* leAudioDevice = static_cast<LeAudioDevice*>(data); instance->state_machine_callbacks_ ->OnDeviceAutonomousStateTransitionTimeout(leAudioDevice); }, leAudioDevice); } void AseStateMachineProcessDisabling( struct le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { Loading @@ -2696,10 +2719,15 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING); /* Remote may autonomously bring ASEs to QoS configured state */ if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { ProcessAutonomousDisable(leAudioDevice, ase); } /* Process the Disable Transition of the rest of group members if no * more ASE notifications has to come from this device. */ if (leAudioDevice->IsReadyToSuspendStream()) ProcessGroupDisable(group); if (leAudioDevice->IsReadyToSuspendStream()) ProcessGroupDisable(group); break; Loading Loading @@ -2895,6 +2923,34 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { StopStream(group); } } void ProcessAutonomousDisable(LeAudioDevice* leAudioDevice, struct ase* ase) { auto bidirection_ase = leAudioDevice->GetAseToMatchBidirectionCis(ase); /* ASE is not a part of bi-directional CIS */ if (!bidirection_ase) return; /* ASE is already disabled */ if (bidirection_ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { /* Bi-direction ASEs are now disabled */ if ((ase->autonomous_target_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) && alarm_is_scheduled(ase->autonomous_operation_timer_)) { alarm_free(ase->autonomous_operation_timer_); ase->autonomous_operation_timer_ = NULL; ase->autonomous_target_state_ = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE; } return; } /* Schedule alarm if first ASE is autonomously disabling */ if (!alarm_is_scheduled(bidirection_ase->autonomous_operation_timer_)) { ScheduleAutonomousOperationTimer( AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED, leAudioDevice, bidirection_ase); } } }; } // namespace Loading system/bta/le_audio/state_machine.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ class LeAudioGroupStateMachine { int group_id, bluetooth::le_audio::GroupStreamStatus status) = 0; virtual void OnStateTransitionTimeout(int group_id) = 0; virtual void OnUpdatedCisConfiguration(int group_id, uint8_t direction) = 0; virtual void OnDeviceAutonomousStateTransitionTimeout( LeAudioDevice* leAudioDevice) = 0; }; virtual ~LeAudioGroupStateMachine() = default; Loading Loading
system/bta/le_audio/client.cc +12 −0 Original line number Diff line number Diff line Loading @@ -518,6 +518,12 @@ class LeAudioClientImpl : public LeAudioClient { } while (leAudioDevice); } void OnDeviceAutonomousStateTransitionTimeout(LeAudioDevice* leAudioDevice) { LOG_ERROR("Device %s, failed to complete autonomous transition", ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_)); DisconnectDevice(leAudioDevice, true); } void UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup* group) { bool group_conf_changed = group->ReloadAudioLocations(); group_conf_changed |= group->ReloadAudioDirections(); Loading Loading @@ -5530,6 +5536,12 @@ class CallbacksImpl : public LeAudioGroupStateMachine::Callbacks { if (instance) instance->OnLeAudioDeviceSetStateTimeout(group_id); } void OnDeviceAutonomousStateTransitionTimeout( LeAudioDevice* leAudioDevice) override { if (instance) instance->OnDeviceAutonomousStateTransitionTimeout(leAudioDevice); } void OnUpdatedCisConfiguration(int group_id, uint8_t direction) { if (instance) instance->OnUpdatedCisConfiguration(group_id, direction); } Loading
system/bta/le_audio/devices.cc +8 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,9 @@ void LeAudioDevice::ClearPACs(void) { LeAudioDevice::~LeAudioDevice(void) { alarm_free(link_quality_timer); for (auto& ase : ases_) { alarm_free(ase.autonomous_operation_timer_); } this->ClearPACs(); } Loading Loading @@ -946,6 +949,11 @@ void LeAudioDevice::DeactivateAllAses(void) { ase.cis_conn_hdl, bluetooth::common::ToString(ase.cis_state).c_str(), bluetooth::common::ToString(ase.data_path_state).c_str()); } if (alarm_is_scheduled(ase.autonomous_operation_timer_)) { alarm_free(ase.autonomous_operation_timer_); ase.autonomous_operation_timer_ = NULL; ase.autonomous_target_state_ = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE; } ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE; ase.cis_state = CisState::IDLE; ase.data_path_state = DataPathState::IDLE; Loading
system/bta/le_audio/le_audio_types.h +7 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "bta_le_audio_uuids.h" #include "btm_iso_api_types.h" #include "osi/include/alarm.h" namespace le_audio { Loading Loading @@ -722,6 +723,8 @@ struct ase { pres_delay_max(0), preferred_pres_delay_min(0), preferred_pres_delay_max(0), autonomous_operation_timer_(nullptr), autonomous_target_state_(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE), state(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {} struct hdl_pair hdls; Loading Loading @@ -761,6 +764,10 @@ struct ase { std::vector<uint8_t> metadata; /* Autonomous change data */ alarm_t* autonomous_operation_timer_; types::AseState autonomous_target_state_; AseState state; }; Loading
system/bta/le_audio/state_machine.cc +58 −2 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ using le_audio::types::LeAudioContextType; namespace { constexpr int linkQualityCheckInterval = 4000; constexpr int kAutonomousTransitionTimeoutMs = 5000; static void link_quality_cb(void* data) { // very ugly, but we need to pass just two bytes Loading Loading @@ -2075,6 +2076,12 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); /* Remote may autonomously bring ASEs to QoS configured state */ if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { ProcessAutonomousDisable(leAudioDevice, ase); } /* Process the Disable Transition of the rest of group members if no * more ASE notifications has to come from this device. */ if (leAudioDevice->IsReadyToSuspendStream()) ProcessGroupDisable(group); Loading Loading @@ -2670,6 +2677,22 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { } } void ScheduleAutonomousOperationTimer(AseState target_state, LeAudioDevice* leAudioDevice, struct ase* ase) { ase->autonomous_target_state_ = target_state; ase->autonomous_operation_timer_ = alarm_new("LeAudioAutonomousOperationTimeout"); alarm_set_on_mloop( ase->autonomous_operation_timer_, kAutonomousTransitionTimeoutMs, [](void* data) { LeAudioDevice* leAudioDevice = static_cast<LeAudioDevice*>(data); instance->state_machine_callbacks_ ->OnDeviceAutonomousStateTransitionTimeout(leAudioDevice); }, leAudioDevice); } void AseStateMachineProcessDisabling( struct le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { Loading @@ -2696,10 +2719,15 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING); /* Remote may autonomously bring ASEs to QoS configured state */ if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { ProcessAutonomousDisable(leAudioDevice, ase); } /* Process the Disable Transition of the rest of group members if no * more ASE notifications has to come from this device. */ if (leAudioDevice->IsReadyToSuspendStream()) ProcessGroupDisable(group); if (leAudioDevice->IsReadyToSuspendStream()) ProcessGroupDisable(group); break; Loading Loading @@ -2895,6 +2923,34 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { StopStream(group); } } void ProcessAutonomousDisable(LeAudioDevice* leAudioDevice, struct ase* ase) { auto bidirection_ase = leAudioDevice->GetAseToMatchBidirectionCis(ase); /* ASE is not a part of bi-directional CIS */ if (!bidirection_ase) return; /* ASE is already disabled */ if (bidirection_ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { /* Bi-direction ASEs are now disabled */ if ((ase->autonomous_target_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) && alarm_is_scheduled(ase->autonomous_operation_timer_)) { alarm_free(ase->autonomous_operation_timer_); ase->autonomous_operation_timer_ = NULL; ase->autonomous_target_state_ = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE; } return; } /* Schedule alarm if first ASE is autonomously disabling */ if (!alarm_is_scheduled(bidirection_ase->autonomous_operation_timer_)) { ScheduleAutonomousOperationTimer( AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED, leAudioDevice, bidirection_ase); } } }; } // namespace Loading
system/bta/le_audio/state_machine.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ class LeAudioGroupStateMachine { int group_id, bluetooth::le_audio::GroupStreamStatus status) = 0; virtual void OnStateTransitionTimeout(int group_id) = 0; virtual void OnUpdatedCisConfiguration(int group_id, uint8_t direction) = 0; virtual void OnDeviceAutonomousStateTransitionTimeout( LeAudioDevice* leAudioDevice) = 0; }; virtual ~LeAudioGroupStateMachine() = default; Loading