Loading system/audio_hal_interface/aidl/le_audio_utils.cc +3 −1 Original line number Diff line number Diff line Loading @@ -440,8 +440,10 @@ GetStackBroadcastConfigurationFromAidlFormat( stack_config.params = GetStackLeAudioLtvMapFromAidlFormat(ase_config->codecConfiguration); auto cfg = stack_config.params.GetAsCoreCodecConfig(); if (cfg.audio_channel_allocation.has_value()) { auto allocation_bitset = std::bitset<32>(cfg.audio_channel_allocation.value()); // Value of 0x00000000 means MonoAudio - one channel per iso stream stack_config.channel_count_per_iso_stream = std::bitset<32>(cfg.audio_channel_allocation.value()).count(); allocation_bitset.any() ? allocation_bitset.count() : 1; } } } Loading system/audio_hal_interface/aidl/le_audio_utils_unittest.cc +57 −12 Original line number Diff line number Diff line Loading @@ -351,8 +351,11 @@ PrepareReferenceAseDirectionConfigLc3(bool is_left, bool is_right, bool is_low_l aidl_ase_config.aseConfiguration.metadata = aidl_metadata; auto stack_codec_params = stack_params.GetAsCoreCodecConfig(); // Value of 0x00000000 means MonoAudio - one channel per iso stream auto location_bitset = std::bitset<32>(stack_codec_params.audio_channel_allocation.value_or(0)); stack_ase_config.codec.channel_count_per_iso_stream = std::bitset<32>(stack_codec_params.audio_channel_allocation.value_or(1)).count(); location_bitset.any() ? location_bitset.count() : 1; /* QoS configuration */ if (has_qos) { Loading @@ -375,8 +378,11 @@ PrepareReferenceAseDirectionConfigLc3(bool is_left, bool is_right, bool is_low_l std::pair<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting, ::bluetooth::le_audio::set_configurations::AudioSetConfiguration> PrepareReferenceAseConfigurationSetting(::bluetooth::le_audio::types::LeAudioContextType ctx_type, bool has_source = false) { PrepareReferenceAseConfigurationSetting( ::bluetooth::le_audio::types::LeAudioContextType ctx_type, std::optional<uint32_t> source_locations = le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | le_audio::codec_spec_conf::kLeAudioLocationFrontRight) { // Prepare the AIDL format config ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting aidl_audio_set_config; Loading Loading @@ -424,8 +430,8 @@ PrepareReferenceAseConfigurationSetting(::bluetooth::le_audio::types::LeAudioCon ALLOW_ASYMMETRIC_CONFIGURATIONS | ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags::MONO_MIC_CONFIGURATION; /* Low latency, mono microphone - Single source ASE */ if (has_source) { /* Low latency microphone */ if (source_locations) { if (!aidl_audio_set_config.sourceAseConfiguration) { log::error("Has no source container"); aidl_audio_set_config.sourceAseConfiguration = std::vector< Loading @@ -433,13 +439,36 @@ PrepareReferenceAseConfigurationSetting(::bluetooth::le_audio::types::LeAudioCon LeAudioAseConfigurationSetting::AseDirectionConfiguration>>(); } // Left ASE config if (source_locations.value() & le_audio::codec_spec_conf::kLeAudioLocationFrontLeft) { auto [aidl_ase_config_source, stack_ase_config_source] = PrepareReferenceAseDirectionConfigLc3(true, false, true); // AIDL: aidl_audio_set_config.sourceAseConfiguration->push_back(aidl_ase_config_source); // STACK: stack_audio_set_config.confs.source.push_back(stack_ase_config_source); } // Right ASE config if (source_locations.value() & le_audio::codec_spec_conf::kLeAudioLocationFrontRight) { auto [aidl_ase_config_source, stack_ase_config_source] = PrepareReferenceAseDirectionConfigLc3(false, true, true); // AIDL: aidl_audio_set_config.sourceAseConfiguration->push_back(aidl_ase_config_source); // STACK: stack_audio_set_config.confs.source.push_back(stack_ase_config_source); } // Use Mono ASE config if not Left nor Right if (stack_audio_set_config.confs.source.empty()) { auto [aidl_ase_config_source, stack_ase_config_source] = PrepareReferenceAseDirectionConfigLc3(true, true, true); PrepareReferenceAseDirectionConfigLc3(false, false, true); // AIDL: aidl_audio_set_config.sourceAseConfiguration->push_back(aidl_ase_config_source); // STACK: stack_audio_set_config.confs.source.push_back(stack_ase_config_source); } } return {aidl_audio_set_config, stack_audio_set_config}; } Loading Loading @@ -886,13 +915,29 @@ TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackMetadataFromAidlFormat) } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFromAidlFormat) { auto source_allocations = le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | le_audio::codec_spec_conf::kLeAudioLocationFrontRight; auto [aidl_config, expected_stack_config] = test_utils::PrepareReferenceAseConfigurationSetting( ::bluetooth::le_audio::types::LeAudioContextType::GAME, true); ::bluetooth::le_audio::types::LeAudioContextType::GAME, source_allocations); auto stack_config = GetStackUnicastConfigurationFromAidlFormat( ::bluetooth::le_audio::types::LeAudioContextType::GAME, aidl_config); ASSERT_TRUE(stack_config.has_value()); ASSERT_EQ(stack_config->confs.sink.size(), 2ul); ASSERT_EQ(stack_config->confs.source.size(), 2ul); ASSERT_EQ(*stack_config, expected_stack_config); } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFromAidlFormatMonoLoc) { auto source_allocations = le_audio::codec_spec_conf::kLeAudioLocationMonoAudio; auto [aidl_config, expected_stack_config] = test_utils::PrepareReferenceAseConfigurationSetting( ::bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL, source_allocations); auto stack_config = GetStackUnicastConfigurationFromAidlFormat( ::bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL, aidl_config); ASSERT_TRUE(stack_config.has_value()); ASSERT_EQ(stack_config->confs.sink.size(), 2ul); ASSERT_EQ(stack_config->confs.source.size(), 1ul); ASSERT_EQ(*stack_config, expected_stack_config); } Loading system/bta/le_audio/client.cc +9 −9 Original line number Diff line number Diff line Loading @@ -1467,19 +1467,11 @@ public: group_add_node(group_id, address); } leAudioDevice->src_audio_locations_ = source_audio_location; leAudioDevice->snk_audio_locations_ = sink_audio_location; if (sink_audio_location != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink; } callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_, leAudioDevice->snk_audio_locations_.to_ulong()); leAudioDevice->src_audio_locations_ = source_audio_location; if (source_audio_location != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource; } BidirectionalPair<AudioContexts> supported_contexts = { .sink = AudioContexts(sink_supported_context_types), .source = AudioContexts(source_supported_context_types), Loading @@ -1494,6 +1486,14 @@ public: log::warn("Could not load Handles"); } /* Presence of PAC characteristic for a direction means support for that direction */ if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource; } if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink; } if (!DeserializeSinkPacs(leAudioDevice, sink_pacs)) { /* If PACs are invalid, just say whole cache is invalid */ leAudioDevice->known_service_handles_ = false; Loading system/bta/le_audio/le_audio_client_test.cc +109 −0 Original line number Diff line number Diff line Loading @@ -3791,6 +3791,115 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) { DisconnectLeAudioWithAclClose(test_address1, 2); } TEST_F(UnicastTest, LoadStoredBandedHeadphones) { const RawAddress test_address0 = GetTestAddress(0); uint16_t conn_id = 1; SetSampleDatabaseEarbudsValid( conn_id, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationMonoAudio, 2, 1, 0x0004, /* source sample freq 16khz */ false, /*add_csis*/ true, /*add_cas*/ true, /*add_pacs*/ true, /*add_ascs*/ 0, 0); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::CONNECTED, test_address0)) .Times(1); /* Connect and fill the device storage */ ConnectLeAudio(test_address0); std::vector<uint8_t> handles; LeAudioClient::GetHandlesForStorage(test_address0, handles); std::vector<uint8_t> ases; LeAudioClient::GetAsesForStorage(test_address0, ases); std::vector<uint8_t> src_pacs; LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs); std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); /* Disconnect & Cleanup */ DisconnectLeAudioWithAclClose(test_address0, conn_id); if (LeAudioClient::IsLeAudioClientRunning()) { LeAudioClient::Cleanup(); ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning()); } Mock::VerifyAndClearExpectations(&mock_hal_2_1_verifier); Mock::VerifyAndClearExpectations(&mock_storage_load); // Load devices from the storage when storage API is called bool autoconnect = true; EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationMonoAudio, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), std::move(ases))); SyncOnMainLoop(); }); /* Prepare mock to not inject connect event so the device can stay in * CONNECTING state*/ ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false)) .WillByDefault(DoAll(Return())); // Re-Initialize & load from storage BtaAppRegisterCallback app_register_callback; ON_CALL(mock_gatt_interface_, AppRegister(_, _, _)) .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback))); std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference; LeAudioClient::Initialize( &mock_audio_hal_client_callbacks_, base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load), base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier), framework_encode_preference); if (app_register_callback) { app_register_callback.Run(gatt_if, GATT_SUCCESS); } InjectConnectedEvent(test_address0, conn_id); SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_gatt_interface_); // Verify if all went well and we got the proper group auto group_id = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0); std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id); ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end()); SetUpMockCodecManager(::bluetooth::le_audio::types::CodecLocation::HOST); // Start streaming LeAudioClient::Get()->GroupSetActive(group_id); SyncOnMainLoop(); EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _)) .Times(1); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id); SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_state_machine_); ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_NE(group, nullptr); auto device = group->GetFirstDevice(); ASSERT_NE(device, nullptr); ASSERT_EQ(device->audio_directions_, bluetooth::le_audio::types::kLeAudioDirectionSink | bluetooth::le_audio::types::kLeAudioDirectionSource); DisconnectLeAudioWithAclClose(test_address0, conn_id); } TEST_F(UnicastTestNoInit, ServiceChangedBeforeServiceIsConnected) { // Prepare two devices uint8_t group_size = 2; Loading Loading
system/audio_hal_interface/aidl/le_audio_utils.cc +3 −1 Original line number Diff line number Diff line Loading @@ -440,8 +440,10 @@ GetStackBroadcastConfigurationFromAidlFormat( stack_config.params = GetStackLeAudioLtvMapFromAidlFormat(ase_config->codecConfiguration); auto cfg = stack_config.params.GetAsCoreCodecConfig(); if (cfg.audio_channel_allocation.has_value()) { auto allocation_bitset = std::bitset<32>(cfg.audio_channel_allocation.value()); // Value of 0x00000000 means MonoAudio - one channel per iso stream stack_config.channel_count_per_iso_stream = std::bitset<32>(cfg.audio_channel_allocation.value()).count(); allocation_bitset.any() ? allocation_bitset.count() : 1; } } } Loading
system/audio_hal_interface/aidl/le_audio_utils_unittest.cc +57 −12 Original line number Diff line number Diff line Loading @@ -351,8 +351,11 @@ PrepareReferenceAseDirectionConfigLc3(bool is_left, bool is_right, bool is_low_l aidl_ase_config.aseConfiguration.metadata = aidl_metadata; auto stack_codec_params = stack_params.GetAsCoreCodecConfig(); // Value of 0x00000000 means MonoAudio - one channel per iso stream auto location_bitset = std::bitset<32>(stack_codec_params.audio_channel_allocation.value_or(0)); stack_ase_config.codec.channel_count_per_iso_stream = std::bitset<32>(stack_codec_params.audio_channel_allocation.value_or(1)).count(); location_bitset.any() ? location_bitset.count() : 1; /* QoS configuration */ if (has_qos) { Loading @@ -375,8 +378,11 @@ PrepareReferenceAseDirectionConfigLc3(bool is_left, bool is_right, bool is_low_l std::pair<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting, ::bluetooth::le_audio::set_configurations::AudioSetConfiguration> PrepareReferenceAseConfigurationSetting(::bluetooth::le_audio::types::LeAudioContextType ctx_type, bool has_source = false) { PrepareReferenceAseConfigurationSetting( ::bluetooth::le_audio::types::LeAudioContextType ctx_type, std::optional<uint32_t> source_locations = le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | le_audio::codec_spec_conf::kLeAudioLocationFrontRight) { // Prepare the AIDL format config ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting aidl_audio_set_config; Loading Loading @@ -424,8 +430,8 @@ PrepareReferenceAseConfigurationSetting(::bluetooth::le_audio::types::LeAudioCon ALLOW_ASYMMETRIC_CONFIGURATIONS | ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags::MONO_MIC_CONFIGURATION; /* Low latency, mono microphone - Single source ASE */ if (has_source) { /* Low latency microphone */ if (source_locations) { if (!aidl_audio_set_config.sourceAseConfiguration) { log::error("Has no source container"); aidl_audio_set_config.sourceAseConfiguration = std::vector< Loading @@ -433,13 +439,36 @@ PrepareReferenceAseConfigurationSetting(::bluetooth::le_audio::types::LeAudioCon LeAudioAseConfigurationSetting::AseDirectionConfiguration>>(); } // Left ASE config if (source_locations.value() & le_audio::codec_spec_conf::kLeAudioLocationFrontLeft) { auto [aidl_ase_config_source, stack_ase_config_source] = PrepareReferenceAseDirectionConfigLc3(true, false, true); // AIDL: aidl_audio_set_config.sourceAseConfiguration->push_back(aidl_ase_config_source); // STACK: stack_audio_set_config.confs.source.push_back(stack_ase_config_source); } // Right ASE config if (source_locations.value() & le_audio::codec_spec_conf::kLeAudioLocationFrontRight) { auto [aidl_ase_config_source, stack_ase_config_source] = PrepareReferenceAseDirectionConfigLc3(false, true, true); // AIDL: aidl_audio_set_config.sourceAseConfiguration->push_back(aidl_ase_config_source); // STACK: stack_audio_set_config.confs.source.push_back(stack_ase_config_source); } // Use Mono ASE config if not Left nor Right if (stack_audio_set_config.confs.source.empty()) { auto [aidl_ase_config_source, stack_ase_config_source] = PrepareReferenceAseDirectionConfigLc3(true, true, true); PrepareReferenceAseDirectionConfigLc3(false, false, true); // AIDL: aidl_audio_set_config.sourceAseConfiguration->push_back(aidl_ase_config_source); // STACK: stack_audio_set_config.confs.source.push_back(stack_ase_config_source); } } return {aidl_audio_set_config, stack_audio_set_config}; } Loading Loading @@ -886,13 +915,29 @@ TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackMetadataFromAidlFormat) } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFromAidlFormat) { auto source_allocations = le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | le_audio::codec_spec_conf::kLeAudioLocationFrontRight; auto [aidl_config, expected_stack_config] = test_utils::PrepareReferenceAseConfigurationSetting( ::bluetooth::le_audio::types::LeAudioContextType::GAME, true); ::bluetooth::le_audio::types::LeAudioContextType::GAME, source_allocations); auto stack_config = GetStackUnicastConfigurationFromAidlFormat( ::bluetooth::le_audio::types::LeAudioContextType::GAME, aidl_config); ASSERT_TRUE(stack_config.has_value()); ASSERT_EQ(stack_config->confs.sink.size(), 2ul); ASSERT_EQ(stack_config->confs.source.size(), 2ul); ASSERT_EQ(*stack_config, expected_stack_config); } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFromAidlFormatMonoLoc) { auto source_allocations = le_audio::codec_spec_conf::kLeAudioLocationMonoAudio; auto [aidl_config, expected_stack_config] = test_utils::PrepareReferenceAseConfigurationSetting( ::bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL, source_allocations); auto stack_config = GetStackUnicastConfigurationFromAidlFormat( ::bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL, aidl_config); ASSERT_TRUE(stack_config.has_value()); ASSERT_EQ(stack_config->confs.sink.size(), 2ul); ASSERT_EQ(stack_config->confs.source.size(), 1ul); ASSERT_EQ(*stack_config, expected_stack_config); } Loading
system/bta/le_audio/client.cc +9 −9 Original line number Diff line number Diff line Loading @@ -1467,19 +1467,11 @@ public: group_add_node(group_id, address); } leAudioDevice->src_audio_locations_ = source_audio_location; leAudioDevice->snk_audio_locations_ = sink_audio_location; if (sink_audio_location != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink; } callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_, leAudioDevice->snk_audio_locations_.to_ulong()); leAudioDevice->src_audio_locations_ = source_audio_location; if (source_audio_location != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource; } BidirectionalPair<AudioContexts> supported_contexts = { .sink = AudioContexts(sink_supported_context_types), .source = AudioContexts(source_supported_context_types), Loading @@ -1494,6 +1486,14 @@ public: log::warn("Could not load Handles"); } /* Presence of PAC characteristic for a direction means support for that direction */ if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource; } if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0) { leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink; } if (!DeserializeSinkPacs(leAudioDevice, sink_pacs)) { /* If PACs are invalid, just say whole cache is invalid */ leAudioDevice->known_service_handles_ = false; Loading
system/bta/le_audio/le_audio_client_test.cc +109 −0 Original line number Diff line number Diff line Loading @@ -3791,6 +3791,115 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) { DisconnectLeAudioWithAclClose(test_address1, 2); } TEST_F(UnicastTest, LoadStoredBandedHeadphones) { const RawAddress test_address0 = GetTestAddress(0); uint16_t conn_id = 1; SetSampleDatabaseEarbudsValid( conn_id, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationMonoAudio, 2, 1, 0x0004, /* source sample freq 16khz */ false, /*add_csis*/ true, /*add_cas*/ true, /*add_pacs*/ true, /*add_ascs*/ 0, 0); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::CONNECTED, test_address0)) .Times(1); /* Connect and fill the device storage */ ConnectLeAudio(test_address0); std::vector<uint8_t> handles; LeAudioClient::GetHandlesForStorage(test_address0, handles); std::vector<uint8_t> ases; LeAudioClient::GetAsesForStorage(test_address0, ases); std::vector<uint8_t> src_pacs; LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs); std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); /* Disconnect & Cleanup */ DisconnectLeAudioWithAclClose(test_address0, conn_id); if (LeAudioClient::IsLeAudioClientRunning()) { LeAudioClient::Cleanup(); ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning()); } Mock::VerifyAndClearExpectations(&mock_hal_2_1_verifier); Mock::VerifyAndClearExpectations(&mock_storage_load); // Load devices from the storage when storage API is called bool autoconnect = true; EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationMonoAudio, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), std::move(ases))); SyncOnMainLoop(); }); /* Prepare mock to not inject connect event so the device can stay in * CONNECTING state*/ ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false)) .WillByDefault(DoAll(Return())); // Re-Initialize & load from storage BtaAppRegisterCallback app_register_callback; ON_CALL(mock_gatt_interface_, AppRegister(_, _, _)) .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback))); std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference; LeAudioClient::Initialize( &mock_audio_hal_client_callbacks_, base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load), base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier), framework_encode_preference); if (app_register_callback) { app_register_callback.Run(gatt_if, GATT_SUCCESS); } InjectConnectedEvent(test_address0, conn_id); SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_gatt_interface_); // Verify if all went well and we got the proper group auto group_id = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0); std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id); ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end()); SetUpMockCodecManager(::bluetooth::le_audio::types::CodecLocation::HOST); // Start streaming LeAudioClient::Get()->GroupSetActive(group_id); SyncOnMainLoop(); EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _)) .Times(1); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id); SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_state_machine_); ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_NE(group, nullptr); auto device = group->GetFirstDevice(); ASSERT_NE(device, nullptr); ASSERT_EQ(device->audio_directions_, bluetooth::le_audio::types::kLeAudioDirectionSink | bluetooth::le_audio::types::kLeAudioDirectionSource); DisconnectLeAudioWithAclClose(test_address0, conn_id); } TEST_F(UnicastTestNoInit, ServiceChangedBeforeServiceIsConnected) { // Prepare two devices uint8_t group_size = 2; Loading