~aleteoryx/muditaos

214451ccf152a8262d9925b84bc97cd14e7c5c6e — Jakub Pyszczak 4 years ago a912db5
[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.
M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +13 -2
@@ 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

M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +11 -0
@@ 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;

M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +5 -0
@@ 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<Profile::Type> profiles, bool available)
    {
        for (auto &p : supportedProfiles) {

M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +11 -2
@@ 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

M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +19 -3
@@ 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<Event> 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;
        }


M module-audio/Audio/Operation/PlaybackOperation.hpp => module-audio/Audio/Operation/PlaybackOperation.hpp +1 -0
@@ 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;

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +4 -2
@@ 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));

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +9 -16
@@ 341,17 341,14 @@ std::unique_ptr<AudioResponseMessage> 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<audio::Event>(EventType::BlutoothHSPDeviceState));

                LOG_DEBUG("Sending Bluetooth start ringing");
                bus.sendUnicast(std::make_shared<message::bluetooth::Ring>(message::bluetooth::Ring::State::Enable),
                                service::name::bluetooth);
                return std::make_unique<AudioStartPlaybackResponse>(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>(message::bluetooth::Ring::State::Enable),
                            service::name::bluetooth);
            return std::make_unique<AudioStartPlaybackResponse>(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>(BluetoothMessage::Request::Play),
                                service::name::bluetooth);


@@ 368,9 365,6 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
    }
    else if (opType == Operation::Type::Router) {
        auto input = audioMux.GetRoutingInput(true);
        if (bluetoothA2DPConnected) {
            HandleSendEvent(std::make_shared<audio::Event>(EventType::BlutoothHSPDeviceState));
        }
        if (bluetoothHSPConnected) {
            LOG_DEBUG("Sending Bluetooth start routing");
            bus.sendUnicast(std::make_shared<message::bluetooth::StartAudioRouting>(), service::name::bluetooth);


@@ 396,8 390,7 @@ std::unique_ptr<AudioResponseMessage> 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");