Loading system/bta/le_audio/state_machine.cc +0 −2 Original line number Diff line number Diff line Loading @@ -966,13 +966,11 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { ases_pair.sink->state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { ases_pair.sink->state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; ases_pair.sink->active = false; } if (ases_pair.source && ases_pair.source->state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { ases_pair.source->state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; ases_pair.source->active = false; } } Loading system/bta/le_audio/state_machine_test.cc +119 −0 Original line number Diff line number Diff line Loading @@ -490,6 +490,7 @@ class StateMachineTest : public Test { addresses_.clear(); cached_codec_configuration_map_.clear(); cached_ase_to_cis_id_map_.clear(); cached_remote_qos_configuration_for_ase_.clear(); LeAudioGroupStateMachine::Cleanup(); ::le_audio::AudioSetConfigurationProvider::Cleanup(); } Loading Loading @@ -625,6 +626,8 @@ class StateMachineTest : public Test { UINT16_TO_STREAM(p, conf->max_transport_latency); UINT24_TO_STREAM(p, conf->pres_delay); cached_remote_qos_configuration_for_ase_[ase] = notif_value; LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent( notif_value.data(), notif_value.size(), ase, device, group); } break; Loading Loading @@ -1280,6 +1283,8 @@ class StateMachineTest : public Test { cached_codec_configuration_map_; std::map<RawAddress, std::map<int, int>> cached_ase_to_cis_id_map_; std::map<types::ase*, std::vector<uint8_t>> cached_remote_qos_configuration_for_ase_; MockLeAudioGroupStateMachineCallbacks mock_callbacks_; std::vector<std::shared_ptr<LeAudioDevice>> le_audio_devices_; Loading Loading @@ -3705,6 +3710,120 @@ TEST_F(StateMachineTest, testAttachDeviceToTheStream) { ASSERT_NE(ase->retrans_nb, 0); } TEST_F(StateMachineTest, testAttachDeviceToTheStream_autonomusQoSConfiguredState) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; const auto num_devices = 2; ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); // 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); PrepareConfigureQosHandler(group); PrepareEnableHandler(group); PrepareDisableHandler(group); PrepareReleaseHandler(group); auto* leAudioDevice = group->GetFirstDevice(); LeAudioDevice* lastDevice; LeAudioDevice* fistDevice = leAudioDevice; auto expected_devices_written = 0; while (leAudioDevice) { /* Three Writes: * 1: Codec Config * 2: Codec QoS * 3: Enabling */ lastDevice = leAudioDevice; EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) .Times(AtLeast(3)); 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(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); InjectInitialIdleNotification(group); // Start the configuration and stream Media content LeAudioGroupStateMachine::Get()->StartStream( group, context_type, {.sink = types::AudioContexts(context_type), .source = types::AudioContexts(context_type)}, {.sink = std::vector<uint8_t>(1, media_ccid), .source = std::vector<uint8_t>(1, media_ccid)}); // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_); // Inject CIS and ACL disconnection of first device InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT); // Check if group keeps streaming ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); // Make sure ASE with disconnected CIS are not left in STREAMING ASSERT_EQ(lastDevice->GetFirstAseWithState( ::le_audio::types::kLeAudioDirectionSink, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING), nullptr); ASSERT_EQ(lastDevice->GetFirstAseWithState( ::le_audio::types::kLeAudioDirectionSource, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING), nullptr); EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) .Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1); for (auto& ase : lastDevice->ases_) { if (cached_remote_qos_configuration_for_ase_.count(&ase) > 0) { InjectAseStateNotification( &ase, lastDevice, group, ascs::kAseStateQoSConfigured, &(cached_remote_qos_configuration_for_ase_[&ase])); } } // Check if group keeps streaming ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); // Verify that the joining device receives the right CCID list auto lastMeta = lastDevice->GetFirstActiveAse()->metadata; bool parsedOk = false; auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(), parsedOk); ASSERT_TRUE(parsedOk); auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList); ASSERT_TRUE(ccids.has_value()); ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end()); /* Verify that ASE of first device are still good*/ auto ase = fistDevice->GetFirstActiveAse(); ASSERT_NE(ase->max_transport_latency, 0); ASSERT_NE(ase->retrans_nb, 0); } TEST_F(StateMachineTest, testAttachDeviceToTheStreamDoNotAttach) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; Loading Loading
system/bta/le_audio/state_machine.cc +0 −2 Original line number Diff line number Diff line Loading @@ -966,13 +966,11 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { ases_pair.sink->state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { ases_pair.sink->state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; ases_pair.sink->active = false; } if (ases_pair.source && ases_pair.source->state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { ases_pair.source->state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; ases_pair.source->active = false; } } Loading
system/bta/le_audio/state_machine_test.cc +119 −0 Original line number Diff line number Diff line Loading @@ -490,6 +490,7 @@ class StateMachineTest : public Test { addresses_.clear(); cached_codec_configuration_map_.clear(); cached_ase_to_cis_id_map_.clear(); cached_remote_qos_configuration_for_ase_.clear(); LeAudioGroupStateMachine::Cleanup(); ::le_audio::AudioSetConfigurationProvider::Cleanup(); } Loading Loading @@ -625,6 +626,8 @@ class StateMachineTest : public Test { UINT16_TO_STREAM(p, conf->max_transport_latency); UINT24_TO_STREAM(p, conf->pres_delay); cached_remote_qos_configuration_for_ase_[ase] = notif_value; LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent( notif_value.data(), notif_value.size(), ase, device, group); } break; Loading Loading @@ -1280,6 +1283,8 @@ class StateMachineTest : public Test { cached_codec_configuration_map_; std::map<RawAddress, std::map<int, int>> cached_ase_to_cis_id_map_; std::map<types::ase*, std::vector<uint8_t>> cached_remote_qos_configuration_for_ase_; MockLeAudioGroupStateMachineCallbacks mock_callbacks_; std::vector<std::shared_ptr<LeAudioDevice>> le_audio_devices_; Loading Loading @@ -3705,6 +3710,120 @@ TEST_F(StateMachineTest, testAttachDeviceToTheStream) { ASSERT_NE(ase->retrans_nb, 0); } TEST_F(StateMachineTest, testAttachDeviceToTheStream_autonomusQoSConfiguredState) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; const auto num_devices = 2; ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); // 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); PrepareConfigureQosHandler(group); PrepareEnableHandler(group); PrepareDisableHandler(group); PrepareReleaseHandler(group); auto* leAudioDevice = group->GetFirstDevice(); LeAudioDevice* lastDevice; LeAudioDevice* fistDevice = leAudioDevice; auto expected_devices_written = 0; while (leAudioDevice) { /* Three Writes: * 1: Codec Config * 2: Codec QoS * 3: Enabling */ lastDevice = leAudioDevice; EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) .Times(AtLeast(3)); 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(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); InjectInitialIdleNotification(group); // Start the configuration and stream Media content LeAudioGroupStateMachine::Get()->StartStream( group, context_type, {.sink = types::AudioContexts(context_type), .source = types::AudioContexts(context_type)}, {.sink = std::vector<uint8_t>(1, media_ccid), .source = std::vector<uint8_t>(1, media_ccid)}); // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_); // Inject CIS and ACL disconnection of first device InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT); // Check if group keeps streaming ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); // Make sure ASE with disconnected CIS are not left in STREAMING ASSERT_EQ(lastDevice->GetFirstAseWithState( ::le_audio::types::kLeAudioDirectionSink, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING), nullptr); ASSERT_EQ(lastDevice->GetFirstAseWithState( ::le_audio::types::kLeAudioDirectionSource, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING), nullptr); EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) .Times(1); EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1); for (auto& ase : lastDevice->ases_) { if (cached_remote_qos_configuration_for_ase_.count(&ase) > 0) { InjectAseStateNotification( &ase, lastDevice, group, ascs::kAseStateQoSConfigured, &(cached_remote_qos_configuration_for_ase_[&ase])); } } // Check if group keeps streaming ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); // Verify that the joining device receives the right CCID list auto lastMeta = lastDevice->GetFirstActiveAse()->metadata; bool parsedOk = false; auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(), parsedOk); ASSERT_TRUE(parsedOk); auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList); ASSERT_TRUE(ccids.has_value()); ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end()); /* Verify that ASE of first device are still good*/ auto ase = fistDevice->GetFirstActiveAse(); ASSERT_NE(ase->max_transport_latency, 0); ASSERT_NE(ase->retrans_nb, 0); } TEST_F(StateMachineTest, testAttachDeviceToTheStreamDoNotAttach) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; Loading