Loading system/bta/le_audio/state_machine.cc +4 −6 Original line number Diff line number Diff line Loading @@ -2905,12 +2905,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { } switch (ase->state) { case AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING: case AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED: case AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING: { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING); break; } case AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED: SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING); Loading @@ -2918,8 +2914,10 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { if (group->HaveAllActiveDevicesAsesTheSameState( AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)) { group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING); } /* At this point all of the active ASEs within group are released. */ if (group->cig.GetState() == CigState::CREATED && group->HaveAllCisesDisconnected()) { RemoveCigForGroup(group); } Loading system/bta/le_audio/state_machine_test.cc +68 −3 Original line number Diff line number Diff line Loading @@ -239,6 +239,13 @@ class StateMachineTestBase : public Test { ContentControlIdKeeper::GetInstance()->Start(); ON_CALL(mock_callbacks_, StatusReportCb(_, _)) .WillByDefault(Invoke( [](int group_id, bluetooth::le_audio::GroupStreamStatus status) { LOG_DEBUG(" [Testing] StatusReportCb: group id: %d, status: %d", group_id, status); })); MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_); ON_CALL(mock_csis_client_module_, Get()) .WillByDefault(Return(&mock_csis_client_module_)); Loading Loading @@ -1741,6 +1748,60 @@ TEST_F(StateMachineTest, testConfigureQosMultiple) { ASSERT_EQ(0, get_func_call_count("alarm_cancel")); } TEST_F(StateMachineTest, testConfigureQosFailed) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 3; const auto num_devices = 2; // Check if CIG is properly cleared when QoS failed // Prepare multiple fake connected devices in a group auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); ASSERT_EQ(group->Size(), num_devices); PrepareConfigureCodecHandler(group); PrepareCtpNotificationError( group, client_parser::ascs::kCtpOpcodeQosConfiguration, client_parser::ascs::kCtpResponseCodeInvalidConfigurationParameterValue, client_parser::ascs::kCtpResponsePhy); PrepareReleaseHandler(group); auto* leAudioDevice = group->GetFirstDevice(); auto expected_devices_written = 0; while (leAudioDevice) { EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) .Times(AtLeast(2)); expected_devices_written++; leAudioDevice = group->GetNextDevice(leAudioDevice); } ASSERT_EQ(expected_devices_written, num_devices); EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0); EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0); EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); InjectInitialIdleNotification(group); // Start the configuration and stream Media content ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream( group, context_type, {.sink = types::AudioContexts(context_type), .source = types::AudioContexts(context_type)})); // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); ASSERT_EQ(2, get_func_call_count("alarm_cancel")); testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_); } TEST_F(StateMachineTest, testStreamCreationError) { /* Device is banded headphones with 1x snk + 0x src ase * (1xunidirectional CIS) with channel count 2 (for stereo Loading Loading @@ -5602,19 +5663,23 @@ TEST_F(StateMachineTest, StartStreamCachedConfigReconfigInvalidBehavior) { EXPECT_CALL(mock_callbacks_, StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING)) .Times(1); .Times(0); EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0); // Block the fallback Release which will happen when CreateCig will faile // Block the fallback Release which will happen when CreateCig will fail stay_in_releasing_state_ = true; // Start the configuration and stream Live content LeAudioGroupStateMachine::Get()->StartStream( bool result = LeAudioGroupStateMachine::Get()->StartStream( group, kContextTypeLive, {.sink = types::AudioContexts(kContextTypeLive), .source = types::AudioContexts(kContextTypeLive)}); // Group internally in releasing state. StartStrean should faile. ASSERT_FALSE(result); testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_); } Loading Loading
system/bta/le_audio/state_machine.cc +4 −6 Original line number Diff line number Diff line Loading @@ -2905,12 +2905,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { } switch (ase->state) { case AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING: case AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED: case AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING: { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING); break; } case AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED: SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING); Loading @@ -2918,8 +2914,10 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { if (group->HaveAllActiveDevicesAsesTheSameState( AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)) { group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING); } /* At this point all of the active ASEs within group are released. */ if (group->cig.GetState() == CigState::CREATED && group->HaveAllCisesDisconnected()) { RemoveCigForGroup(group); } Loading
system/bta/le_audio/state_machine_test.cc +68 −3 Original line number Diff line number Diff line Loading @@ -239,6 +239,13 @@ class StateMachineTestBase : public Test { ContentControlIdKeeper::GetInstance()->Start(); ON_CALL(mock_callbacks_, StatusReportCb(_, _)) .WillByDefault(Invoke( [](int group_id, bluetooth::le_audio::GroupStreamStatus status) { LOG_DEBUG(" [Testing] StatusReportCb: group id: %d, status: %d", group_id, status); })); MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_); ON_CALL(mock_csis_client_module_, Get()) .WillByDefault(Return(&mock_csis_client_module_)); Loading Loading @@ -1741,6 +1748,60 @@ TEST_F(StateMachineTest, testConfigureQosMultiple) { ASSERT_EQ(0, get_func_call_count("alarm_cancel")); } TEST_F(StateMachineTest, testConfigureQosFailed) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 3; const auto num_devices = 2; // Check if CIG is properly cleared when QoS failed // Prepare multiple fake connected devices in a group auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); ASSERT_EQ(group->Size(), num_devices); PrepareConfigureCodecHandler(group); PrepareCtpNotificationError( group, client_parser::ascs::kCtpOpcodeQosConfiguration, client_parser::ascs::kCtpResponseCodeInvalidConfigurationParameterValue, client_parser::ascs::kCtpResponsePhy); PrepareReleaseHandler(group); auto* leAudioDevice = group->GetFirstDevice(); auto expected_devices_written = 0; while (leAudioDevice) { EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) .Times(AtLeast(2)); expected_devices_written++; leAudioDevice = group->GetNextDevice(leAudioDevice); } ASSERT_EQ(expected_devices_written, num_devices); EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0); EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0); EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); InjectInitialIdleNotification(group); // Start the configuration and stream Media content ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream( group, context_type, {.sink = types::AudioContexts(context_type), .source = types::AudioContexts(context_type)})); // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); ASSERT_EQ(2, get_func_call_count("alarm_cancel")); testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_); } TEST_F(StateMachineTest, testStreamCreationError) { /* Device is banded headphones with 1x snk + 0x src ase * (1xunidirectional CIS) with channel count 2 (for stereo Loading Loading @@ -5602,19 +5663,23 @@ TEST_F(StateMachineTest, StartStreamCachedConfigReconfigInvalidBehavior) { EXPECT_CALL(mock_callbacks_, StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING)) .Times(1); .Times(0); EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0); // Block the fallback Release which will happen when CreateCig will faile // Block the fallback Release which will happen when CreateCig will fail stay_in_releasing_state_ = true; // Start the configuration and stream Live content LeAudioGroupStateMachine::Get()->StartStream( bool result = LeAudioGroupStateMachine::Get()->StartStream( group, kContextTypeLive, {.sink = types::AudioContexts(kContextTypeLive), .source = types::AudioContexts(kContextTypeLive)}); // Group internally in releasing state. StartStrean should faile. ASSERT_FALSE(result); testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_); } Loading