From 214451ccf152a8262d9925b84bc97cd14e7c5c6e Mon Sep 17 00:00:00 2001 From: Jakub Pyszczak Date: Wed, 21 Jul 2021 10:55:17 +0200 Subject: [PATCH] [EGD-7083] Fixed earspeaker bt HSP Routing and ringtone are now hearable via earspeaker/jack while pure is connected to the device that doesn't support HSP. --- module-audio/Audio/Audio.cpp | 15 +++++++++-- module-audio/Audio/Audio.hpp | 11 ++++++++ module-audio/Audio/Operation/Operation.cpp | 5 ++++ module-audio/Audio/Operation/Operation.hpp | 13 ++++++++-- .../Audio/Operation/PlaybackOperation.cpp | 22 +++++++++++++--- .../Audio/Operation/PlaybackOperation.hpp | 1 + .../Bluetooth/interface/profiles/HSP/HSP.cpp | 6 +++-- .../service-audio/ServiceAudio.cpp | 25 +++++++------------ 8 files changed, 73 insertions(+), 25 deletions(-) diff --git a/module-audio/Audio/Audio.cpp b/module-audio/Audio/Audio.cpp index d3984eef8b313e0d51cb746f2914cdbd01d9ad45..1371812a40e4db8b3414b0861523f3ab40a3260f 100644 --- a/module-audio/Audio/Audio.cpp +++ b/module-audio/Audio/Audio.cpp @@ -90,7 +90,7 @@ namespace audio break; } currentOperation = std::move(ret); - UpdateProfiles(); + UpdateProfiles(playbackType); } catch (const AudioInitException &audioException) { // If creating operation failed fallback to IdleOperation which is guaranteed to work @@ -159,13 +159,24 @@ namespace audio return SetOutputVolume(0); } - void Audio::UpdateProfiles() + void Audio::SendUpdateEventsToCurrentOperation() { auto updateEvents = audioSinkState.getUpdateEvents(); for (auto &event : updateEvents) { currentOperation->SendEvent(event); } + } + + void Audio::UpdateProfiles() + { + SendUpdateEventsToCurrentOperation(); currentOperation->SwitchToPriorityProfile(); } + void Audio::UpdateProfiles(audio::PlaybackType playbackType) + { + SendUpdateEventsToCurrentOperation(); + currentOperation->SwitchToPriorityProfile(playbackType); + } + } // namespace audio diff --git a/module-audio/Audio/Audio.hpp b/module-audio/Audio/Audio.hpp index c6608ca306ae7cfc88555f0b0016ddfc0a0e544e..1fefbc9f1e7006560202ea8c7e88b4f78c8502a7 100644 --- a/module-audio/Audio/Audio.hpp +++ b/module-audio/Audio/Audio.hpp @@ -112,7 +112,18 @@ namespace audio virtual audio::RetCode Mute(); private: + void SendUpdateEventsToCurrentOperation(); + /** + * @brief Sends update to the current operation and switches to priority profile. + */ void UpdateProfiles(); + /** + * @brief Sends update to the current operation and switches to priority profile. + * + * @param playbackType if it's callringtone and bluetooth a2dp is used then + * ignore priorities and change profile to the earpeaker. Not needed otherwise. + */ + void UpdateProfiles(audio::PlaybackType playbackType); Muted muted = Muted::False; AudioSinkState audioSinkState; diff --git a/module-audio/Audio/Operation/Operation.cpp b/module-audio/Audio/Operation/Operation.cpp index 2347a29104aa2a8ddba35ccfc67eb1f79ad4a021..a4abdba06f1cd3d388ac3cea89700b09a820b1ec 100644 --- a/module-audio/Audio/Operation/Operation.cpp +++ b/module-audio/Audio/Operation/Operation.cpp @@ -65,6 +65,11 @@ namespace audio return audio::RetCode::ProfileNotSet; } + audio::RetCode Operation::SwitchToPriorityProfile([[maybe_unused]] audio::PlaybackType playbackType) + { + return SwitchToPriorityProfile(); + } + void Operation::SetProfileAvailability(std::vector profiles, bool available) { for (auto &p : supportedProfiles) { diff --git a/module-audio/Audio/Operation/Operation.hpp b/module-audio/Audio/Operation/Operation.hpp index d8f94ad6991f7156878f64ea9733bccbcb0f7750..625eec6d4fe9e4d5a5ea4107b130b7a584a39c7b 100644 --- a/module-audio/Audio/Operation/Operation.hpp +++ b/module-audio/Audio/Operation/Operation.hpp @@ -114,8 +114,17 @@ namespace audio { return filePath; } - - audio::RetCode SwitchToPriorityProfile(); + /** + * @brief Switches operation to priority profile. + */ + virtual audio::RetCode SwitchToPriorityProfile(); + /** + * @brief Switches operation to priority profile. + * + * @param playbackType if it's callringtone and bluetooth a2dp is used then + * ignore priorities and change profile to the earpeaker. Not needed otherwise. + */ + virtual audio::RetCode SwitchToPriorityProfile(audio::PlaybackType playbackType); protected: struct SupportedProfile diff --git a/module-audio/Audio/Operation/PlaybackOperation.cpp b/module-audio/Audio/Operation/PlaybackOperation.cpp index b6aa30d0f722e2a0c293d14908f86c9541745c1f..6ab876ee572370d325a5e528c90d5aae220decec 100644 --- a/module-audio/Audio/Operation/PlaybackOperation.cpp +++ b/module-audio/Audio/Operation/PlaybackOperation.cpp @@ -40,7 +40,7 @@ namespace audio auto format = dec->getSourceFormat(); LOG_DEBUG("Source format: %s", format.toString().c_str()); - auto retCode = SwitchToPriorityProfile(); + auto retCode = SwitchToPriorityProfile(playbackType); if (retCode != RetCode::Success) { throw AudioInitException("Failed to switch audio profile", retCode); } @@ -133,17 +133,32 @@ namespace audio return dec->getCurrentPosition(); } + audio::RetCode PlaybackOperation::SwitchToPriorityProfile(audio::PlaybackType playbackType) + { + for (const auto &p : supportedProfiles) { + const auto profileType = p.profile->GetType(); + if (profileType == audio::Profile::Type::PlaybackBluetoothA2DP && + playbackType == audio::PlaybackType::CallRingtone) { + continue; + } + if (p.isAvailable) { + return SwitchProfile(profileType); + } + } + return audio::RetCode::ProfileNotSet; + } + audio::RetCode PlaybackOperation::SendEvent(std::shared_ptr evt) { auto isAvailable = evt->getDeviceState() == Event::DeviceState::Connected ? true : false; switch (evt->getType()) { case EventType::JackState: SetProfileAvailability({Profile::Type::PlaybackHeadphones}, isAvailable); - SwitchToPriorityProfile(); + Operation::SwitchToPriorityProfile(); break; case EventType::BlutoothA2DPDeviceState: SetProfileAvailability({Profile::Type::PlaybackBluetoothA2DP}, isAvailable); - SwitchToPriorityProfile(); + Operation::SwitchToPriorityProfile(); break; default: return RetCode::UnsupportedEvent; @@ -156,6 +171,7 @@ namespace audio { auto newProfile = GetProfile(type); if (newProfile == nullptr) { + LOG_ERROR("Unsupported profile"); return RetCode::UnsupportedProfile; } diff --git a/module-audio/Audio/Operation/PlaybackOperation.hpp b/module-audio/Audio/Operation/PlaybackOperation.hpp index 85fd90718c8ff9cbb6ae295803b2c59dd538150a..2281b2534f4efacc065dc2f388dc5be1fd463788 100644 --- a/module-audio/Audio/Operation/PlaybackOperation.hpp +++ b/module-audio/Audio/Operation/PlaybackOperation.hpp @@ -40,6 +40,7 @@ namespace audio audio::RetCode SetInputGain(float gain) final; Position GetPosition() final; + audio::RetCode SwitchToPriorityProfile(audio::PlaybackType playbackType) final; private: static constexpr auto playbackTimeConstraint = 10ms; diff --git a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp index 1103f441f4a5094f4df5a0eafbb860090c2df1cb..2238df6b943adafd85f6c6a36d28dec4a5943054 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp @@ -179,6 +179,8 @@ namespace bluetooth if (hsp_subevent_rfcomm_connection_complete_get_status(event) != 0u) { LOG_DEBUG("RFCOMM connection establishement failed with status %u\n", hsp_subevent_rfcomm_connection_complete_get_status(event)); + sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected); + isConnected = false; break; } LOG_DEBUG("RFCOMM connection established.\n"); @@ -200,6 +202,8 @@ namespace bluetooth if (hsp_subevent_audio_connection_complete_get_status(event) != 0u) { LOG_DEBUG("Audio connection establishment failed with status %u\n", hsp_subevent_audio_connection_complete_get_status(event)); + sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected); + isConnected = false; } else { scoHandle = hsp_subevent_audio_connection_complete_get_handle(event); @@ -210,9 +214,7 @@ namespace bluetooth break; case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: LOG_DEBUG("Audio connection released.\n\n"); - sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected); scoHandle = HCI_CON_HANDLE_INVALID; - isConnected = false; break; case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: LOG_DEBUG("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); diff --git a/module-services/service-audio/ServiceAudio.cpp b/module-services/service-audio/ServiceAudio.cpp index 7f2af9b5b7d62f91a6ec4f19a5a9829445aef6a7..412816d587f9c2d5d30c4950dfebb6f12f3afdb0 100644 --- a/module-services/service-audio/ServiceAudio.cpp +++ b/module-services/service-audio/ServiceAudio.cpp @@ -341,17 +341,14 @@ std::unique_ptr ServiceAudio::HandleStart(const Operation: if (opType == Operation::Type::Playback) { auto input = audioMux.GetPlaybackInput(playbackType); - // stop bluetooth stream if available - if (bluetoothA2DPConnected || bluetoothHSPConnected) { - if (playbackType == audio::PlaybackType::CallRingtone) { - HandleSendEvent(std::make_shared(EventType::BlutoothHSPDeviceState)); - - LOG_DEBUG("Sending Bluetooth start ringing"); - bus.sendUnicast(std::make_shared(message::bluetooth::Ring::State::Enable), - service::name::bluetooth); - return std::make_unique(audio::RetCode::Success, retToken); - } - else { + if (playbackType == audio::PlaybackType::CallRingtone && bluetoothHSPConnected) { + LOG_DEBUG("Sending Bluetooth start ringing"); + bus.sendUnicast(std::make_shared(message::bluetooth::Ring::State::Enable), + service::name::bluetooth); + return std::make_unique(audio::RetCode::Success, retToken); + } + else if (bluetoothA2DPConnected) { + if (playbackType != audio::PlaybackType::CallRingtone) { LOG_DEBUG("Sending Bluetooth start stream request"); bus.sendUnicast(std::make_shared(BluetoothMessage::Request::Play), service::name::bluetooth); @@ -368,9 +365,6 @@ std::unique_ptr ServiceAudio::HandleStart(const Operation: } else if (opType == Operation::Type::Router) { auto input = audioMux.GetRoutingInput(true); - if (bluetoothA2DPConnected) { - HandleSendEvent(std::make_shared(EventType::BlutoothHSPDeviceState)); - } if (bluetoothHSPConnected) { LOG_DEBUG("Sending Bluetooth start routing"); bus.sendUnicast(std::make_shared(), service::name::bluetooth); @@ -396,8 +390,7 @@ std::unique_ptr ServiceAudio::HandleSendEvent(std::shared_ audio::Token()); } } - - if (evt->getType() == EventType::BlutoothHSPDeviceState) { + else if (evt->getType() == EventType::BlutoothHSPDeviceState) { auto newState = evt->getDeviceState() == Event::DeviceState::Connected; if (newState != bluetoothHSPConnected) { LOG_DEBUG("Bluetooth connection status changed: %s", newState ? "connected" : "disconnected");