Loading system/bta/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -1205,6 +1205,7 @@ cc_test { "libbt_shim_ffi", "libchrome", "libevent", "libflagtest", "libflatbuffers-cpp", "libgmock", "libgtest", Loading system/bta/le_audio/broadcaster/broadcaster.cc +90 −20 Original line number Diff line number Diff line Loading @@ -84,19 +84,14 @@ std::mutex instance_mutex; * for test purposes. */ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { enum class AudioDataPathState { INACTIVE, ACTIVE, SUSPENDED, }; enum class AudioState { SUSPENDED, ACTIVE }; public: LeAudioBroadcasterImpl( bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_) LeAudioBroadcasterImpl(bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_) : callbacks_(callbacks_), current_phy_(PHY_LE_2M), audio_data_path_state_(AudioDataPathState::INACTIVE), le_audio_source_hal_client_(nullptr) { le_audio_source_hal_client_(nullptr), audio_state_(AudioState::SUSPENDED) { log::info(""); /* Register State machine callbacks */ Loading Loading @@ -146,6 +141,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { le_audio_source_hal_client_.get(), false); le_audio_source_hal_client_.reset(); } audio_state_ = AudioState::SUSPENDED; } void Stop() { Loading Loading @@ -329,6 +325,46 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { } } void UpdateAudioActiveStateInPublicAnnouncement() { for (auto const& kv_it : broadcasts_) { auto& broadcast = kv_it.second; bool audio_active_state = (audio_state_ == AudioState::ACTIVE) && (broadcast->GetState() == BroadcastStateMachine::State::STREAMING); log::info("broadcast_id={}, audio_active_state={}", broadcast->GetBroadcastId(), audio_active_state); auto updateLtv = [](bool audio_active_state, LeAudioLtvMap& ltv) -> bool { auto existing_audio_active_state = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState); if (existing_audio_active_state && !existing_audio_active_state->empty()) { if (audio_active_state != static_cast<bool>(existing_audio_active_state->at(0))) { ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, audio_active_state); return true; } } else { ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, audio_active_state); return true; } return false; }; auto public_announcement = broadcast->GetPublicBroadcastAnnouncement(); auto public_ltv = LeAudioLtvMap(public_announcement.metadata); if (updateLtv(audio_active_state, public_ltv)) { public_announcement.metadata = public_ltv.Values(); broadcast->UpdatePublicBroadcastAnnouncement( broadcast->GetBroadcastId(), broadcast->GetBroadcastName(), public_announcement); } } } void UpdateMetadata( uint32_t broadcast_id, const std::string& broadcast_name, const std::vector<uint8_t>& public_metadata, Loading Loading @@ -410,6 +446,16 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { log::error("Invalid public metadata provided."); return; } if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { // Append the Audio Active State bool audio_active_state = (audio_state_ == AudioState::ACTIVE) && (broadcasts_[broadcast_id]->GetState() == BroadcastStateMachine::State::STREAMING); public_ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, audio_active_state); } PublicBroadcastAnnouncementData pb_announcement = preparePublicAnnouncement(broadcasts_[broadcast_id] ->GetPublicBroadcastAnnouncement() Loading Loading @@ -483,6 +529,11 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { false); return; } if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { // Append the Audio Active State public_ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, false); } // Prepare public features byte // bit 0 Encryption broadcast stream encrypted or not // bit 1 Standard quality audio configuration present or not Loading Loading @@ -660,6 +711,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { if (broadcasts_.count(broadcast_id) != 0) { log::info("Stopping AudioHalClient"); if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop(); audio_state_ = AudioState::SUSPENDED; broadcasts_[broadcast_id]->SetMuted(true); broadcasts_[broadcast_id]->ProcessMessage( BroadcastStateMachine::Message::SUSPEND, nullptr); Loading Loading @@ -731,6 +783,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { log::info("Stopping AudioHalClient, broadcast_id={}", broadcast_id); if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop(); audio_state_ = AudioState::SUSPENDED; broadcasts_[broadcast_id]->SetMuted(true); broadcasts_[broadcast_id]->ProcessMessage( BroadcastStateMachine::Message::STOP, nullptr); Loading Loading @@ -976,13 +1029,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { switch (state) { case BroadcastStateMachine::State::STOPPED: /* Pass through */ break; case BroadcastStateMachine::State::CONFIGURING: /* Pass through */ break; case BroadcastStateMachine::State::CONFIGURED: /* Pass through */ if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } break; case BroadcastStateMachine::State::STOPPING: /* Nothing to do here? */ break; case BroadcastStateMachine::State::STREAMING: if (getStreamerCount() == 1) { Loading @@ -1004,7 +1059,9 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { return; } instance->audio_data_path_state_ = AudioDataPathState::ACTIVE; if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } } } break; Loading Loading @@ -1269,8 +1326,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { virtual void OnAudioSuspend(void) override { log::info(""); /* TODO: Should we suspend all broadcasts - remove BIGs? */ if (instance) instance->audio_data_path_state_ = AudioDataPathState::SUSPENDED; if (!instance) { return; } instance->audio_state_ = AudioState::SUSPENDED; if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } } virtual void OnAudioResume(void) override { Loading @@ -1278,7 +1342,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { if (!instance) return; /* TODO: Should we resume all broadcasts - recreate BIGs? */ instance->audio_data_path_state_ = AudioDataPathState::ACTIVE; instance->audio_state_ = AudioState::ACTIVE; if (!IsAnyoneStreaming()) { instance->le_audio_source_hal_client_->CancelStreamingRequest(); Loading @@ -1286,6 +1350,10 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { } instance->le_audio_source_hal_client_->ConfirmStreamingRequest(); if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } } virtual void OnAudioMetadataUpdate( Loading Loading @@ -1320,10 +1388,12 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { /* Some BIG params are set globally */ uint8_t current_phy_; AudioDataPathState audio_data_path_state_; std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_; std::vector<BroadcastId> available_broadcast_ids_; // Current state of audio playback AudioState audio_state_; // Flag to track iso state bool is_iso_running_ = false; }; Loading system/bta/le_audio/broadcaster/broadcaster_test.cc +101 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ */ #include <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <flag_macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <hardware/audio.h> Loading @@ -36,6 +38,8 @@ #include "test/mock/mock_main_shim_entry.h" #include "test/mock/mock_stack_btm_iso.h" #define TEST_BT com::android::bluetooth::flags using namespace std::chrono_literals; using bluetooth::le_audio::types::AudioContexts; Loading Loading @@ -201,6 +205,10 @@ static const std::vector<uint8_t> default_public_metadata = { 5, bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfo, 0x1, 0x2, 0x3, 0x4}; static const std::vector<uint8_t> audio_active_state_false = { 2, bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, 0x00}; static const std::vector<uint8_t> audio_active_state_true = { 2, bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, 0x01}; // bit 0: encrypted, bit 1: standard quality present static const uint8_t test_public_broadcast_features = 0x3; Loading Loading @@ -736,11 +744,19 @@ TEST_F(BroadcasterTest, UpdateMetadata) { broadcast_id, test_broadcast_name, default_public_metadata, {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})}); std::vector<uint8_t> public_metadata(default_public_metadata); public_metadata.insert(public_metadata.end(), audio_active_state_false.begin(), audio_active_state_false.end()); ASSERT_EQ(2u, ccid_list.size()); ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), media_ccid)); ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), default_ccid)); ASSERT_EQ(expected_broadcast_name, test_broadcast_name); if (!com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { ASSERT_EQ(expected_public_meta, default_public_metadata); } else { ASSERT_EQ(expected_public_meta, public_metadata); } } static BasicAudioAnnouncementData prepareAnnouncement( Loading Loading @@ -1185,6 +1201,90 @@ TEST_F(BroadcasterTest, VendorCodecConfig) { subgroup.bis_configs.at(1).vendor_codec_specific_params->size())); } TEST_F_WITH_FLAGS(BroadcasterTest, AudioActiveState, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, leaudio_big_depends_on_audio_state))) { std::vector<uint8_t> updated_public_meta; PublicBroadcastAnnouncementData pb_announcement; std::vector<uint8_t> public_metadata_audio_false(default_public_metadata); public_metadata_audio_false.insert(public_metadata_audio_false.end(), audio_active_state_false.begin(), audio_active_state_false.end()); std::vector<uint8_t> public_metadata_audio_true(default_public_metadata); public_metadata_audio_true.insert(public_metadata_audio_true.end(), audio_active_state_true.begin(), audio_active_state_true.end()); // Add Audio Actie State while broadcast created auto broadcast_id = InstantiateBroadcast(); auto sm = MockBroadcastStateMachine::GetLastInstance(); pb_announcement = sm->GetPublicBroadcastAnnouncement(); auto created_public_meta = types::LeAudioLtvMap(pb_announcement.metadata).RawPacket(); ASSERT_EQ(created_public_meta, public_metadata_audio_false); ON_CALL(*sm, UpdatePublicBroadcastAnnouncement(broadcast_id, _, _)) .WillByDefault( [&](uint32_t broadcast_id, const std::string& broadcast_name, const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement) { pb_announcement = announcement; updated_public_meta = types::LeAudioLtvMap(announcement.metadata).RawPacket(); }); ON_CALL(*sm, GetPublicBroadcastAnnouncement()).WillByDefault(ReturnRef(pb_announcement)); LeAudioSourceAudioHalClient::Callbacks* audio_receiver; EXPECT_CALL(*mock_audio_source_, Start) .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))); LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); ASSERT_NE(audio_receiver, nullptr); // Update to true Audio Active State while audio resumed EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioResume(); ASSERT_EQ(updated_public_meta, public_metadata_audio_true); // No update Audio Active State if the same value EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement).Times(0); audio_receiver->OnAudioResume(); // Updated to false Audio Active State while audio suspended EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioSuspend(); ASSERT_EQ(updated_public_meta, public_metadata_audio_false); // No update Audio Active State if the same value EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement).Times(0); audio_receiver->OnAudioSuspend(); // Update to false Audio Active State while metada updated EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); LeAudioBroadcaster::Get()->UpdateMetadata( broadcast_id, test_broadcast_name, default_public_metadata, {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})}); ASSERT_EQ(updated_public_meta, public_metadata_audio_false); // Update to true Audio Active State while audio resumed EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioResume(); ASSERT_EQ(updated_public_meta, public_metadata_audio_true); // Update to true Audio Active State while metada updated EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); LeAudioBroadcaster::Get()->UpdateMetadata( broadcast_id, test_broadcast_name, default_public_metadata, {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})}); ASSERT_EQ(updated_public_meta, public_metadata_audio_true); // Updated to false Audio Active State while broadcast suspended EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id); ASSERT_EQ(updated_public_meta, public_metadata_audio_false); // No update to true Audio Active State while audio resumed when not in // streaming state EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement).Times(0); audio_receiver->OnAudioResume(); } // TODO: Add tests for: // ToRawPacket(BasicAudioAnnouncementData const& in, std::vector<uint8_t>& data) Loading Loading
system/bta/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -1205,6 +1205,7 @@ cc_test { "libbt_shim_ffi", "libchrome", "libevent", "libflagtest", "libflatbuffers-cpp", "libgmock", "libgtest", Loading
system/bta/le_audio/broadcaster/broadcaster.cc +90 −20 Original line number Diff line number Diff line Loading @@ -84,19 +84,14 @@ std::mutex instance_mutex; * for test purposes. */ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { enum class AudioDataPathState { INACTIVE, ACTIVE, SUSPENDED, }; enum class AudioState { SUSPENDED, ACTIVE }; public: LeAudioBroadcasterImpl( bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_) LeAudioBroadcasterImpl(bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_) : callbacks_(callbacks_), current_phy_(PHY_LE_2M), audio_data_path_state_(AudioDataPathState::INACTIVE), le_audio_source_hal_client_(nullptr) { le_audio_source_hal_client_(nullptr), audio_state_(AudioState::SUSPENDED) { log::info(""); /* Register State machine callbacks */ Loading Loading @@ -146,6 +141,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { le_audio_source_hal_client_.get(), false); le_audio_source_hal_client_.reset(); } audio_state_ = AudioState::SUSPENDED; } void Stop() { Loading Loading @@ -329,6 +325,46 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { } } void UpdateAudioActiveStateInPublicAnnouncement() { for (auto const& kv_it : broadcasts_) { auto& broadcast = kv_it.second; bool audio_active_state = (audio_state_ == AudioState::ACTIVE) && (broadcast->GetState() == BroadcastStateMachine::State::STREAMING); log::info("broadcast_id={}, audio_active_state={}", broadcast->GetBroadcastId(), audio_active_state); auto updateLtv = [](bool audio_active_state, LeAudioLtvMap& ltv) -> bool { auto existing_audio_active_state = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState); if (existing_audio_active_state && !existing_audio_active_state->empty()) { if (audio_active_state != static_cast<bool>(existing_audio_active_state->at(0))) { ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, audio_active_state); return true; } } else { ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, audio_active_state); return true; } return false; }; auto public_announcement = broadcast->GetPublicBroadcastAnnouncement(); auto public_ltv = LeAudioLtvMap(public_announcement.metadata); if (updateLtv(audio_active_state, public_ltv)) { public_announcement.metadata = public_ltv.Values(); broadcast->UpdatePublicBroadcastAnnouncement( broadcast->GetBroadcastId(), broadcast->GetBroadcastName(), public_announcement); } } } void UpdateMetadata( uint32_t broadcast_id, const std::string& broadcast_name, const std::vector<uint8_t>& public_metadata, Loading Loading @@ -410,6 +446,16 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { log::error("Invalid public metadata provided."); return; } if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { // Append the Audio Active State bool audio_active_state = (audio_state_ == AudioState::ACTIVE) && (broadcasts_[broadcast_id]->GetState() == BroadcastStateMachine::State::STREAMING); public_ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, audio_active_state); } PublicBroadcastAnnouncementData pb_announcement = preparePublicAnnouncement(broadcasts_[broadcast_id] ->GetPublicBroadcastAnnouncement() Loading Loading @@ -483,6 +529,11 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { false); return; } if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { // Append the Audio Active State public_ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, false); } // Prepare public features byte // bit 0 Encryption broadcast stream encrypted or not // bit 1 Standard quality audio configuration present or not Loading Loading @@ -660,6 +711,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { if (broadcasts_.count(broadcast_id) != 0) { log::info("Stopping AudioHalClient"); if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop(); audio_state_ = AudioState::SUSPENDED; broadcasts_[broadcast_id]->SetMuted(true); broadcasts_[broadcast_id]->ProcessMessage( BroadcastStateMachine::Message::SUSPEND, nullptr); Loading Loading @@ -731,6 +783,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { log::info("Stopping AudioHalClient, broadcast_id={}", broadcast_id); if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop(); audio_state_ = AudioState::SUSPENDED; broadcasts_[broadcast_id]->SetMuted(true); broadcasts_[broadcast_id]->ProcessMessage( BroadcastStateMachine::Message::STOP, nullptr); Loading Loading @@ -976,13 +1029,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { switch (state) { case BroadcastStateMachine::State::STOPPED: /* Pass through */ break; case BroadcastStateMachine::State::CONFIGURING: /* Pass through */ break; case BroadcastStateMachine::State::CONFIGURED: /* Pass through */ if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } break; case BroadcastStateMachine::State::STOPPING: /* Nothing to do here? */ break; case BroadcastStateMachine::State::STREAMING: if (getStreamerCount() == 1) { Loading @@ -1004,7 +1059,9 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { return; } instance->audio_data_path_state_ = AudioDataPathState::ACTIVE; if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } } } break; Loading Loading @@ -1269,8 +1326,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { virtual void OnAudioSuspend(void) override { log::info(""); /* TODO: Should we suspend all broadcasts - remove BIGs? */ if (instance) instance->audio_data_path_state_ = AudioDataPathState::SUSPENDED; if (!instance) { return; } instance->audio_state_ = AudioState::SUSPENDED; if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } } virtual void OnAudioResume(void) override { Loading @@ -1278,7 +1342,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { if (!instance) return; /* TODO: Should we resume all broadcasts - recreate BIGs? */ instance->audio_data_path_state_ = AudioDataPathState::ACTIVE; instance->audio_state_ = AudioState::ACTIVE; if (!IsAnyoneStreaming()) { instance->le_audio_source_hal_client_->CancelStreamingRequest(); Loading @@ -1286,6 +1350,10 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { } instance->le_audio_source_hal_client_->ConfirmStreamingRequest(); if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { instance->UpdateAudioActiveStateInPublicAnnouncement(); } } virtual void OnAudioMetadataUpdate( Loading Loading @@ -1320,10 +1388,12 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { /* Some BIG params are set globally */ uint8_t current_phy_; AudioDataPathState audio_data_path_state_; std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_; std::vector<BroadcastId> available_broadcast_ids_; // Current state of audio playback AudioState audio_state_; // Flag to track iso state bool is_iso_running_ = false; }; Loading
system/bta/le_audio/broadcaster/broadcaster_test.cc +101 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ */ #include <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <flag_macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <hardware/audio.h> Loading @@ -36,6 +38,8 @@ #include "test/mock/mock_main_shim_entry.h" #include "test/mock/mock_stack_btm_iso.h" #define TEST_BT com::android::bluetooth::flags using namespace std::chrono_literals; using bluetooth::le_audio::types::AudioContexts; Loading Loading @@ -201,6 +205,10 @@ static const std::vector<uint8_t> default_public_metadata = { 5, bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfo, 0x1, 0x2, 0x3, 0x4}; static const std::vector<uint8_t> audio_active_state_false = { 2, bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, 0x00}; static const std::vector<uint8_t> audio_active_state_true = { 2, bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, 0x01}; // bit 0: encrypted, bit 1: standard quality present static const uint8_t test_public_broadcast_features = 0x3; Loading Loading @@ -736,11 +744,19 @@ TEST_F(BroadcasterTest, UpdateMetadata) { broadcast_id, test_broadcast_name, default_public_metadata, {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})}); std::vector<uint8_t> public_metadata(default_public_metadata); public_metadata.insert(public_metadata.end(), audio_active_state_false.begin(), audio_active_state_false.end()); ASSERT_EQ(2u, ccid_list.size()); ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), media_ccid)); ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), default_ccid)); ASSERT_EQ(expected_broadcast_name, test_broadcast_name); if (!com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { ASSERT_EQ(expected_public_meta, default_public_metadata); } else { ASSERT_EQ(expected_public_meta, public_metadata); } } static BasicAudioAnnouncementData prepareAnnouncement( Loading Loading @@ -1185,6 +1201,90 @@ TEST_F(BroadcasterTest, VendorCodecConfig) { subgroup.bis_configs.at(1).vendor_codec_specific_params->size())); } TEST_F_WITH_FLAGS(BroadcasterTest, AudioActiveState, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, leaudio_big_depends_on_audio_state))) { std::vector<uint8_t> updated_public_meta; PublicBroadcastAnnouncementData pb_announcement; std::vector<uint8_t> public_metadata_audio_false(default_public_metadata); public_metadata_audio_false.insert(public_metadata_audio_false.end(), audio_active_state_false.begin(), audio_active_state_false.end()); std::vector<uint8_t> public_metadata_audio_true(default_public_metadata); public_metadata_audio_true.insert(public_metadata_audio_true.end(), audio_active_state_true.begin(), audio_active_state_true.end()); // Add Audio Actie State while broadcast created auto broadcast_id = InstantiateBroadcast(); auto sm = MockBroadcastStateMachine::GetLastInstance(); pb_announcement = sm->GetPublicBroadcastAnnouncement(); auto created_public_meta = types::LeAudioLtvMap(pb_announcement.metadata).RawPacket(); ASSERT_EQ(created_public_meta, public_metadata_audio_false); ON_CALL(*sm, UpdatePublicBroadcastAnnouncement(broadcast_id, _, _)) .WillByDefault( [&](uint32_t broadcast_id, const std::string& broadcast_name, const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement) { pb_announcement = announcement; updated_public_meta = types::LeAudioLtvMap(announcement.metadata).RawPacket(); }); ON_CALL(*sm, GetPublicBroadcastAnnouncement()).WillByDefault(ReturnRef(pb_announcement)); LeAudioSourceAudioHalClient::Callbacks* audio_receiver; EXPECT_CALL(*mock_audio_source_, Start) .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))); LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); ASSERT_NE(audio_receiver, nullptr); // Update to true Audio Active State while audio resumed EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioResume(); ASSERT_EQ(updated_public_meta, public_metadata_audio_true); // No update Audio Active State if the same value EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement).Times(0); audio_receiver->OnAudioResume(); // Updated to false Audio Active State while audio suspended EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioSuspend(); ASSERT_EQ(updated_public_meta, public_metadata_audio_false); // No update Audio Active State if the same value EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement).Times(0); audio_receiver->OnAudioSuspend(); // Update to false Audio Active State while metada updated EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); LeAudioBroadcaster::Get()->UpdateMetadata( broadcast_id, test_broadcast_name, default_public_metadata, {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})}); ASSERT_EQ(updated_public_meta, public_metadata_audio_false); // Update to true Audio Active State while audio resumed EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioResume(); ASSERT_EQ(updated_public_meta, public_metadata_audio_true); // Update to true Audio Active State while metada updated EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); LeAudioBroadcaster::Get()->UpdateMetadata( broadcast_id, test_broadcast_name, default_public_metadata, {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})}); ASSERT_EQ(updated_public_meta, public_metadata_audio_true); // Updated to false Audio Active State while broadcast suspended EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id); ASSERT_EQ(updated_public_meta, public_metadata_audio_false); // No update to true Audio Active State while audio resumed when not in // streaming state EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement).Times(0); audio_receiver->OnAudioResume(); } // TODO: Add tests for: // ToRawPacket(BasicAudioAnnouncementData const& in, std::vector<uint8_t>& data) Loading