~aleteoryx/muditaos

cc32dd30dc716cd3f6a70142ea8be795398abdcf — Bartosz Cichocki 3 years ago 58fe677
[MOS-366] Connect cellular events to HFP

Connected all (?) necessary cellular events to the HFP profile
Fixed audio issues when connected with HFP
Some cleanup
28 files changed, 131 insertions(+), 189 deletions(-)

M module-audio/Audio/Audio.hpp
M module-audio/Audio/Operation/Operation.hpp
M module-bluetooth/Bluetooth/CommandHandler.cpp
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp
M module-bluetooth/Bluetooth/command/Command.hpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp
M module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.cpp
M module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.hpp
M module-bluetooth/lib/btstack
M module-services/service-audio/ServiceAudio.cpp
M module-services/service-bluetooth/ServiceBluetooth.cpp
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp
D module-services/service-bluetooth/service-bluetooth/ServiceBluetoothCommon.hpp
D module-services/service-bluetooth/service-bluetooth/messages/Ring.hpp
M module-services/service-cellular/call/CallGUI.cpp
M module-services/service-cellular/call/CallGUI.hpp
M module-services/service-cellular/call/CellularCall.cpp
M module-services/service-cellular/service-cellular/CellularMessage.hpp
M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +1 -5
@@ 1,10 1,8 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <service-bluetooth/ServiceBluetoothCommon.hpp>

#include "AudioCommon.hpp"
#include "decoder/Decoder.hpp"
#include "Operation/Operation.hpp"


@@ 128,8 126,6 @@ namespace audio

        Muted muted = Muted::False;

        std::shared_ptr<BluetoothStreamData> btData;

        State currentState = State::Idle;
        std::unique_ptr<Operation> currentOperation;


M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 14,7 14,6 @@
#include "Audio/encoder/Encoder.hpp"
#include "Audio/Profiles/Profile.hpp"

#include <service-bluetooth/ServiceBluetoothCommon.hpp>

namespace audio
{

M module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +2 -0
@@ 76,6 76,8 @@ namespace bluetooth
            return profileManager->callAnswered();
        case Command::CallTerminated:
            return profileManager->terminateCall();
        case Command::CallStarted:
            return profileManager->callStarted(command.getData());
        case Command::IncomingCallNumber:
            return profileManager->setIncomingCallNumber(command.getData());
        case Command::SignalStrengthData:

M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp +4 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BluetoothAudioDevice.hpp"


@@ 75,6 75,7 @@ void A2DPAudioDevice::onDataReceive()

auto CVSDAudioDevice::setOutputVolume(float vol) -> audio::AudioDevice::RetCode
{
    LOG_DEBUG("Setting CVSD volume: %f", vol);
    if (getProfileType() == AudioProfile::HSP) {
        const auto volumeToSet = audio::volume::scaler::hsp::toHSPGain(vol);
        hsp_ag_set_speaker_gain(volumeToSet);


@@ 200,6 201,7 @@ void BluetoothAudioDevice::enableOutput()

void BluetoothAudioDevice::disableInput()
{
    LOG_DEBUG("Disabling bluetooth audio input.");
    inputEnabled = false;
}



@@ 211,6 213,7 @@ void BluetoothAudioDevice::disableOutput()

void CVSDAudioDevice::enableInput()
{
    LOG_DEBUG("Enabling CVSD bluetooth audio input.");
    auto blockSize = Source::_stream->getInputTraits().blockSize;
    rxLeftovers    = std::make_unique<std::uint8_t[]>(blockSize);
    decoderBuffer  = std::make_unique<std::int16_t[]>(scratchBufferSize);

M module-bluetooth/Bluetooth/command/Command.hpp => module-bluetooth/Bluetooth/command/Command.hpp +1 -0
@@ 30,6 30,7 @@ namespace bluetooth
            StopStream,
            CallAnswered,
            CallTerminated,
            CallStarted,
            IncomingCallNumber,
            SignalStrengthData,
            OperatorNameData,

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 59,7 59,6 @@ namespace bluetooth
        void stop();
        void setDevice(const Devicei &dev);
        void setOwnerService(const sys::Service *service);
        auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
    };
} // namespace bluetooth

M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +48 -64
@@ 90,9 90,9 @@ namespace bluetooth
    {
        pimpl->setAudioDevice(audioDevice);
    }
    auto HFP::callAnswered() const noexcept -> Error::Code
    auto HFP::callActive() const noexcept -> Error::Code
    {
        return pimpl->setupCall();
        return pimpl->callActive();
    }
    auto HFP::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
    {


@@ 124,6 124,10 @@ namespace bluetooth
        LOG_DEBUG("Setting roaming status: %s", enabled ? "enabled" : "disabled");
        return pimpl->setRoamingStatus(enabled);
    }
    auto HFP::callStarted(const std::string &num) const noexcept -> Error::Code
    {
        return pimpl->callStarted(num);
    }

    HFP::~HFP() = default;



@@ 138,9 142,9 @@ namespace bluetooth
    SCOCodec HFP::HFPImpl::codec            = SCOCodec::CVSD;
    std::shared_ptr<CVSDAudioDevice> HFP::HFPImpl::audioDevice;

    [[maybe_unused]] int HFP::HFPImpl::memory_1_enabled = 1;
    int HFP::HFPImpl::memory_1_enabled = 1;
    btstack_packet_callback_registration_t HFP::HFPImpl::hci_event_callback_registration;
    [[maybe_unused]] int HFP::HFPImpl::ag_indicators_nr = 7;
    int HFP::HFPImpl::ag_indicators_nr                  = 7;
    hfp_ag_indicator_t HFP::HFPImpl::ag_indicators[]    = {
        // index, name, min range, max range, status, mandatory, enabled, status changed
        {1, "service", 0, 1, 1, 0, 0, 0},


@@ 150,17 154,15 @@ namespace bluetooth
        {5, "signal", 0, 4, 5, 0, 1, 0},
        {6, "roam", 0, 1, 0, 0, 1, 0},
        {7, "callheld", 0, 2, 0, 1, 1, 0}};
    [[maybe_unused]] int HFP::HFPImpl::call_hold_services_nr                      = 5;
    int HFP::HFPImpl::call_hold_services_nr                                       = 5;
    const char *HFP::HFPImpl::call_hold_services[]                                = {"1", "1x", "2", "2x", "3"};
    [[maybe_unused]] int HFP::HFPImpl::hf_indicators_nr                           = 2;
    [[maybe_unused]] hfp_generic_status_indicator_t HFP::HFPImpl::hf_indicators[] = {
    int HFP::HFPImpl::hf_indicators_nr                                            = 2;
    hfp_generic_status_indicator_t HFP::HFPImpl::hf_indicators[]                  = {
        {1, 1},
        {2, 1},
    };
    Devicei HFP::HFPImpl::device;
    bool HFP::HFPImpl::isConnected                  = false;
    bool HFP::HFPImpl::isIncomingCall               = false;
    bool HFP::HFPImpl::isCallInitialized            = false;
    CallStatus HFP::HFPImpl::currentCallStatus = CallStatus::Unknown;

    void HFP::HFPImpl::dump_supported_codecs(void)
    {


@@ 223,7 225,7 @@ namespace bluetooth
                audioDevice->onDataSend(scoHandle);
            }
            else {
                LOG_DEBUG("Audiodevice nullptr :(");
                sco::utils::sendZeros(scoHandle);
            }
            break;
        case HCI_EVENT_HFP_META:


@@ 236,16 238,6 @@ namespace bluetooth

    void HFP::HFPImpl::processHFPEvent(uint8_t *event)
    {
        // NOTE some of the subevents are not mentioned here yet
        /*
         *
         * in hfp_ag.h there are descriptions of cellular and UI interface of HFP:
         * // Cellular Actions
         * and
         * // actions used by local device / user
         * those should be called to trigger requested state in HFP's state machine
         * (which this switch...case depends on)
         */
        switch (hci_event_hfp_meta_get_subevent_code(event)) {
        case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
            std::uint8_t status;


@@ 253,13 245,11 @@ namespace bluetooth
            if (status) {
                LOG_DEBUG("Connection failed, status 0x%02x\n", status);
                sendAudioEvent(audio::EventType::BlutoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
                isConnected = false;
                break;
            }
            aclHandle = hfp_subevent_service_level_connection_established_get_acl_handle(event);
            hfp_subevent_service_level_connection_established_get_bd_addr(event, device.address);
            LOG_DEBUG("Service level connection established to %s.\n", bd_addr_to_str(device.address));
            isConnected = true;
            sendAudioEvent(audio::EventType::BlutoothHFPDeviceState, audio::Event::DeviceState::Connected);
            {
                auto &busProxy     = const_cast<sys::Service *>(ownerService)->bus;


@@ 275,7 265,6 @@ namespace bluetooth
        case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
            LOG_DEBUG("Service level connection released.\n");
            aclHandle   = HCI_CON_HANDLE_INVALID;
            isConnected = false;
            sendAudioEvent(audio::EventType::BlutoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
            {
                auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;


@@ 316,7 305,6 @@ namespace bluetooth
            break;
        case HFP_SUBEVENT_RING:
            break;

        case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG:
            // todo has to be feeded with proper phone number from cellular
            // LOG_DEBUG("Attach number to voice tag. Sending '1234567\n");


@@ 404,9 392,7 @@ namespace bluetooth

    void HFP::HFPImpl::connect()
    {
        if (isConnected) {
            disconnect();
        }
        disconnect();
        LOG_DEBUG("Connecting the HFP profile");
        hfp_ag_establish_service_level_connection(device.address);
        hfp_ag_set_speaker_gain(aclHandle, 8);


@@ 415,9 401,11 @@ namespace bluetooth

    void HFP::HFPImpl::disconnect()
    {
        hfp_ag_release_service_level_connection(aclHandle);
        auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
        busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device), service::name::bluetooth);
        if (hfp_ag_release_service_level_connection(aclHandle) == ERROR_CODE_SUCCESS) {
            auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
            busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
                                 service::name::bluetooth);
        }
    }

    void HFP::HFPImpl::setDevice(Devicei dev)


@@ 431,19 419,6 @@ namespace bluetooth
        ownerService = service;
    }

    auto HFP::HFPImpl::getStreamData() -> std::shared_ptr<BluetoothStreamData>
    {
        return sco->getStreamData();
    }

    void HFP::HFPImpl::terminateCall() const noexcept
    {
        hfp_ag_terminate_call();
        hfp_ag_release_audio_connection(aclHandle);
        isCallInitialized = false;
        isIncomingCall    = false;
    }

    void HFP::HFPImpl::initCodecs()
    {
        std::vector<SCOCodec> codecsList;


@@ 465,12 440,6 @@ namespace bluetooth
    }
    void HFP::HFPImpl::initializeCall() const noexcept
    {
        if (!isCallInitialized && !isIncomingCall) {
            LOG_DEBUG("Initializing outgoing call");
            constexpr auto mockNumber = "1234567"; // Mocking phone number - it is not used in stack
            hfp_ag_outgoing_call_initiated(mockNumber);
            isCallInitialized = true;
        }
    }
    void HFP::HFPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
    {


@@ 481,33 450,41 @@ namespace bluetooth
    void HFP::HFPImpl::startRinging() const noexcept
    {
        LOG_DEBUG("Starting incoming call");
        isIncomingCall = true;
        currentCallStatus = CallStatus::Incoming;
        hfp_ag_incoming_call();
    }
    void HFP::HFPImpl::stopRinging() const noexcept
    {
        LOG_DEBUG("Stop ringing called!");
    }
    auto HFP::HFPImpl::setupCall() const noexcept -> Error::Code
    auto HFP::HFPImpl::callActive() const noexcept -> Error::Code
    {
        if (isIncomingCall) {
            LOG_DEBUG("Answering incoming call");
            hfp_ag_answer_incoming_call();
        }
        else {
            LOG_DEBUG("Establishing outgoing call");
            audioInterface->startAudioRouting(const_cast<sys::Service *>(ownerService));
        switch (currentCallStatus) {
        case CallStatus::Outgoing:
            hfp_ag_outgoing_call_established();
            break;
        case CallStatus::Incoming:
            hfp_ag_answer_incoming_call(); // will answer the call if it wasn't answered
            break;
        default:
            break;
        }

        currentCallStatus = CallStatus::Active;
        return Error::Success;
    }
    auto HFP::HFPImpl::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
    void HFP::HFPImpl::terminateCall() const noexcept
    {
        if (!isIncomingCall) {
            isIncomingCall = true;
            hfp_ag_incoming_call();
        if (currentCallStatus == CallStatus::Active) {
            hfp_ag_terminate_call();
        }
        else {
            hfp_ag_call_dropped();
        }
        hfp_ag_release_audio_connection(aclHandle);
        currentCallStatus = CallStatus::Unknown;
    }
    auto HFP::HFPImpl::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
    {
        hfp_ag_set_clip(129, num.c_str());
        return Error::Success;
    }


@@ 530,6 507,13 @@ namespace bluetooth
        LOG_DEBUG("Battery level (bars): %d, set result: %d", level.getBatteryLevelBars(), result);
        return Error::Success;
    }
    auto HFP::HFPImpl::callStarted(const std::string &number) const noexcept -> Error::Code
    {
        LOG_DEBUG("Call started called");
        hfp_ag_outgoing_call_initiated(number.c_str());
        currentCallStatus = CallStatus::Outgoing;
        return Error::Success;
    }
    auto HFP::HFPImpl::setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code
    {
        hfp_ag_set_registration_status(registered);

M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp +2 -1
@@ 43,7 43,8 @@ namespace bluetooth
        /// @return Success
        [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override;
        [[nodiscard]] auto terminateCall() const noexcept -> Error::Code override;
        [[nodiscard]] auto callAnswered() const noexcept -> Error::Code override;
        [[nodiscard]] auto callActive() const noexcept -> Error::Code override;
        [[nodiscard]] auto callStarted(const std::string &number) const noexcept -> Error::Code override;
        [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override;
        /// @brief Sets the signal strength bars data
        /// @return Success

M module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp +11 -5
@@ 12,6 12,14 @@ namespace bluetooth
    static constexpr int serviceBufferLength = 150;
    static constexpr int commandBufferLength = 150;

    enum class CallStatus
    {
        Outgoing,
        Incoming,
        Active,
        Unknown
    };

    class HFP::HFPImpl
    {
      public:


@@ 25,15 33,15 @@ namespace bluetooth
        void disconnect();
        void setDevice(Devicei device);
        void setOwnerService(const sys::Service *service);
        auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
        [[nodiscard]] auto setupCall() const noexcept -> Error::Code;
        [[nodiscard]] auto callActive() const noexcept -> Error::Code;
        [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code;
        [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code;
        [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code;
        [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code;
        [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code;
        [[nodiscard]] auto setRoamingStatus(bool enabled) const noexcept -> Error::Code;
        [[nodiscard]] auto callStarted(const std::string &number) const noexcept -> Error::Code;

      private:
        static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);


@@ 61,8 69,6 @@ namespace bluetooth
        [[maybe_unused]] static hfp_generic_status_indicator_t hf_indicators[2];
        static std::shared_ptr<CVSDAudioDevice> audioDevice;
        static Devicei device;
        static bool isConnected;
        static bool isIncomingCall;
        static bool isCallInitialized;
        static CallStatus currentCallStatus;
    };
} // namespace bluetooth

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +1 -6
@@ 322,11 322,6 @@ namespace bluetooth
        ownerService = service;
    }

    auto HSP::HSPImpl::getStreamData() -> std::shared_ptr<BluetoothStreamData>
    {
        return sco->getStreamData();
    }

    void HSP::HSPImpl::startRinging() const noexcept
    {
        LOG_DEBUG("Bluetooth ring started");


@@ 351,7 346,7 @@ namespace bluetooth
    {
        pimpl->setAudioDevice(audioDevice);
    }
    auto HSP::callAnswered() const noexcept -> Error::Code
    auto HSP::callActive() const noexcept -> Error::Code
    {
        return Error::Success;
    }

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +1 -1
@@ 41,7 41,7 @@ namespace bluetooth
        /// @return Success
        [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override;
        [[nodiscard]] auto terminateCall() const noexcept -> Error::Code override;
        [[nodiscard]] auto callAnswered() const noexcept -> Error::Code override;
        [[nodiscard]] auto callActive() const noexcept -> Error::Code override;
        [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override;
        /// @return Success - ignoring in HSP
        [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override;

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp +0 -1
@@ 25,7 25,6 @@ namespace bluetooth
        void disconnect();
        void setDevice(const Devicei &dev);
        void setOwnerService(const sys::Service *service);
        auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);

      private:

M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +7 -2
@@ 6,13 6,14 @@
#include "Error.hpp"
#include <audio/BluetoothAudioDevice.hpp>
#include <Service/Message.hpp>
#include <service-bluetooth/ServiceBluetoothCommon.hpp>

#include <memory>
#include <command/BatteryLevel.hpp>
#include <Device.hpp>

namespace bluetooth
{

    class Profile
    {
      public:


@@ 55,7 56,11 @@ namespace bluetooth
        [[nodiscard]] virtual auto terminateCall() const noexcept -> Error::Code = 0;
        /// Executed after the call is answered
        /// @return Error code that determines, whether operation was successful or not
        [[nodiscard]] virtual auto callAnswered() const noexcept -> Error::Code = 0;
        [[nodiscard]] virtual auto callActive() const noexcept -> Error::Code = 0;
        /// Executed after the call has been started
        /// @param outgoing call number
        /// @return Error code that determines, whether operation was successful or not
        [[nodiscard]] virtual auto callStarted(const std::string &num) const noexcept -> Error::Code = 0;
        /// Sets the incoming call number
        /// @return Error code that determines, whether operation was successful or not
        [[nodiscard]] virtual auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code = 0;

M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +10 -1
@@ 103,7 103,7 @@ namespace bluetooth
    }
    auto ProfileManager::callAnswered() -> Error::Code
    {
        return callProfilePtr->callAnswered();
        return callProfilePtr->callActive();
    }
    auto ProfileManager::setIncomingCallNumber(const DataVariant &data) -> Error::Code
    {


@@ 158,5 158,14 @@ namespace bluetooth
        LOG_ERROR("No profile, returning!");
        return Error::NotReady;
    }
    auto ProfileManager::callStarted(const DataVariant &data) -> Error::Code
    {
        if (callProfilePtr) {
            auto number = std::get<utils::PhoneNumber::View>(data);
            return callProfilePtr->callStarted(number.getE164());
        }
        LOG_ERROR("No profile, returning!");
        return Error::NotReady;
    }

} // namespace bluetooth

M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +1 -0
@@ 41,6 41,7 @@ namespace bluetooth
        auto initializeCall() -> Error::Code;
        auto terminateCall() -> Error::Code;
        auto callAnswered() -> Error::Code;
        auto callStarted(const DataVariant &data) -> Error::Code;
        auto setIncomingCallNumber(const DataVariant &data) -> Error::Code;
        auto setSignalStrengthData(const DataVariant &data) -> Error::Code;
        auto setOperatorNameData(const DataVariant &data) -> Error::Code;

M module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.cpp => module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.cpp +0 -9
@@ 30,7 30,6 @@ namespace bluetooth
        static void receive(uint8_t *packet, uint16_t size);
        void setOwnerService(const sys::Service *service);
        void setCodec(uint8_t codec);
        auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;

      private:
        static constexpr auto BYTES_PER_FRAME     = 2;


@@ 83,10 82,6 @@ namespace bluetooth
    {
        pimpl->receive(packet, size);
    }
    [[nodiscard]] auto SCO::getStreamData() const -> std::shared_ptr<BluetoothStreamData>
    {
        return pimpl->getStreamData();
    }
    void SCO::setOwnerService(const sys::Service *service)
    {
        pimpl->setOwnerService(service);


@@ 243,10 238,6 @@ void SCO::SCOImpl::receive(uint8_t *packet, uint16_t size)
{
    receiveCvsd(packet, size);
}
auto SCO::SCOImpl::getStreamData() -> std::shared_ptr<BluetoothStreamData>
{
    return std::make_shared<BluetoothStreamData>(sinkQueue, sourceQueue, metadata);
}
void SCO::SCOImpl::setOwnerService(const sys::Service *service)
{
    ownerService = service;

M module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.hpp => module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 33,7 33,6 @@ namespace bluetooth
        void init();
        void send(hci_con_handle_t sco_handle);
        void receive(uint8_t *packet, uint16_t size);
        [[nodiscard]] auto getStreamData() const -> std::shared_ptr<BluetoothStreamData>;
        void setOwnerService(const sys::Service *service);
        void setCodec(SCOCodec codec);


M module-bluetooth/lib/btstack => module-bluetooth/lib/btstack +1 -1
@@ 1,1 1,1 @@
Subproject commit 49c8d45475aa9cad1b853df2c10883ce037161cb
Subproject commit 172c792707c7e6a8ff68b939b0988f3af9a092b1

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +4 -13
@@ 12,9 12,7 @@
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-bluetooth/Constants.hpp>
#include <service-bluetooth/messages/AudioRouting.hpp>
#include <service-bluetooth/messages/Ring.hpp>
#include <service-bluetooth/messages/AudioNotify.hpp>
#include <service-bluetooth/ServiceBluetoothCommon.hpp>
#include <service-db/Settings.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <Utils.hpp>


@@ 423,18 421,11 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:

    if (opType == Operation::Type::Playback) {
        auto input = audioMux.GetPlaybackInput(playbackType);
        if (playbackType == audio::PlaybackType::CallRingtone && bluetoothVoiceProfileConnected && input) {
            LOG_DEBUG("Sending Bluetooth start ringing");
            bus.sendUnicast(std::make_shared<message::bluetooth::Ring>(message::bluetooth::Ring::State::Enable),

        if (bluetoothA2DPConnected && playbackType != audio::PlaybackType::CallRingtone) {
            LOG_DEBUG("Sending Bluetooth start stream request");
            bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Play),
                            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);
            }
        }

        AudioStart(input);

M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +15 -11
@@ 20,7 20,6 @@
#include "service-bluetooth/messages/BondedDevices.hpp"
#include "service-bluetooth/messages/Unpair.hpp"
#include "service-bluetooth/messages/SetDeviceName.hpp"
#include "service-bluetooth/messages/Ring.hpp"
#include "service-bluetooth/BluetoothDevicesModel.hpp"
#include "service-bluetooth/messages/BluetoothModeChanged.hpp"
#include "service-bluetooth/messages/RequestStatusIndicatorData.hpp"


@@ 100,7 99,6 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
    connectHandler<message::bluetooth::A2DPVolume>();
    connectHandler<message::bluetooth::HSPVolume>();
    connectHandler<message::bluetooth::HFPVolume>();
    connectHandler<message::bluetooth::Ring>();
    connectHandler<message::bluetooth::StartAudioRouting>();
    connectHandler<message::bluetooth::Connect>();
    connectHandler<message::bluetooth::ConnectResult>();


@@ 119,7 117,9 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
    connectHandler<message::bluetooth::RequestStatusIndicatorData>();
    connectHandler<CellularCallerIdMessage>();
    connectHandler<CellularCallActiveNotification>();
    connectHandler<CellularIncominCallMessage>();
    connectHandler<cellular::CallEndedNotification>();
    connectHandler<cellular::CallStartedNotification>();
    connectHandler<CellularSignalStrengthUpdateNotification>();
    connectHandler<CellularCurrentOperatorNameNotification>();
    connectHandler<CellularNetworkStatusUpdateNotification>();


@@ 485,15 485,6 @@ auto ServiceBluetooth::handle(message::bluetooth::HFPVolume *msg) -> std::shared
    return sys::MessageNone{};
}

auto ServiceBluetooth::handle(message::bluetooth::Ring *msg) -> std::shared_ptr<sys::Message>
{
    LOG_DEBUG("Start ringing from audio");
    const auto enableRing = msg->enabled();
    sendWorkerCommand(enableRing ? bluetooth::Command::Type::StartRinging : bluetooth::Command::Type::StopRinging);

    return std::make_shared<sys::ResponseMessage>();
}

auto ServiceBluetooth::handle(message::bluetooth::StartAudioRouting *msg) -> std::shared_ptr<sys::Message>
{
    sendWorkerCommand(bluetooth::Command::Type::StartRouting);


@@ 600,3 591,16 @@ auto ServiceBluetooth::handle(CellularNetworkStatusUpdateNotification *msg) -> s
    sendWorkerCommand(bluetooth::Command::Type::NetworkStatusData, std::move(commandData));
    return sys::MessageNone{};
}
auto ServiceBluetooth::handle(cellular::CallStartedNotification *msg) -> std::shared_ptr<sys::Message>
{
    if (!msg->isCallIncoming()) {
        auto commandData = std::make_unique<bluetooth::PhoneNumberData>(msg->getNumber());
        sendWorkerCommand(bluetooth::Command::Type::CallStarted, std::move(commandData));
    }
    return sys::MessageNone{};
}
auto ServiceBluetooth::handle(CellularIncominCallMessage *msg) -> std::shared_ptr<sys::Message>
{
    sendWorkerCommand(bluetooth::Command::Type::StartRinging);
    return sys::MessageNone{};
}

M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +0 -2
@@ 3,8 3,6 @@

#pragma once

#include "ServiceBluetoothCommon.hpp"

#include <Bluetooth/Device.hpp>
#include <Bluetooth/audio/BluetoothAudioDevice.hpp>
#include <Service/Message.hpp>

M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +4 -1
@@ 67,10 67,12 @@ class CellularCallerIdMessage;
class CellularCallActiveNotification;
class CellularSignalStrengthUpdateNotification;
class CellularCurrentOperatorNameNotification;
class CellularIncominCallMessage;
class CellularNetworkStatusUpdateNotification;
namespace cellular
{
    class CallEndedNotification;
    class CallStartedNotification;
}

class ServiceBluetooth : public sys::Service


@@ 126,7 128,6 @@ class ServiceBluetooth : public sys::Service
    [[nodiscard]] auto handle(message::bluetooth::A2DPVolume *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::HSPVolume *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::HFPVolume *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::Ring *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::StartAudioRouting *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePin *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePasskey *msg) -> std::shared_ptr<sys::Message>;


@@ 134,7 135,9 @@ class ServiceBluetooth : public sys::Service
    [[nodiscard]] auto handle(message::bluetooth::RequestStatusIndicatorData *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularCallerIdMessage *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularCallActiveNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularIncominCallMessage *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(cellular::CallEndedNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(cellular::CallStartedNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularSignalStrengthUpdateNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularCurrentOperatorNameNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularNetworkStatusUpdateNotification *msg) -> std::shared_ptr<sys::Message>;

D module-services/service-bluetooth/service-bluetooth/ServiceBluetoothCommon.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetoothCommon.hpp +0 -20
@@ 1,20 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Bluetooth/Device.hpp>

#include <FreeRTOS.h>
#include <queue.h>

class BluetoothStreamData
{
  public:
    QueueHandle_t in  = nullptr;
    QueueHandle_t out = nullptr;
    DeviceMetadata_t metadata;
    BluetoothStreamData(QueueHandle_t in, QueueHandle_t out, DeviceMetadata_t metadata)
        : in(in), out(out), metadata(metadata)
    {}
};

D module-services/service-bluetooth/service-bluetooth/messages/Ring.hpp => module-services/service-bluetooth/service-bluetooth/messages/Ring.hpp +0 -32
@@ 1,32 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "service-bluetooth/BluetoothMessage.hpp"

namespace message::bluetooth
{
    /// @brief Message that indicates whether to enable or disable bluetooth ring
    class Ring : public BluetoothMessage
    {
      public:
        enum class State : bool
        {
            Enable,
            Disable
        };

        explicit Ring(State state) : state{state}
        {}

        /// @return True if bluetooth should ring, false otherwise
        [[nodiscard]] auto enabled() const noexcept -> bool
        {
            return state == State::Enable;
        }

      private:
        const State state;
    };
} // namespace message::bluetooth

M module-services/service-cellular/call/CallGUI.cpp => module-services/service-cellular/call/CallGUI.cpp +4 -3
@@ 21,10 21,11 @@ void CallGUI::notifyCLIP(const utils::PhoneNumber::View &number)
        &owner, app::manager::actions::HandleCallerId, std::make_unique<app::manager::actions::CallParams>(number));
}

void CallGUI::notifyCallStarted(utils::PhoneNumber phoneNumber)
void CallGUI::notifyCallStarted(utils::PhoneNumber phoneNumber, const CallType type)
{
    owner.bus.sendMulticast(std::make_shared<cellular::CallStartedNotification>(phoneNumber),
                            sys::BusChannel::ServiceCellularNotifications);
    owner.bus.sendMulticast(
        std::make_shared<cellular::CallStartedNotification>(phoneNumber, type == CallType::CT_INCOMING),
        sys::BusChannel::ServiceCellularNotifications);
}

void CallGUI::notifyCallEnded()

M module-services/service-cellular/call/CallGUI.hpp => module-services/service-cellular/call/CallGUI.hpp +2 -1
@@ 4,6 4,7 @@
#pragma once

#include <PhoneNumber.hpp>
#include <Tables/CalllogTable.hpp>

namespace sys
{


@@ 20,7 21,7 @@ class CallGUI

    void notifyRING();
    void notifyCLIP(const utils::PhoneNumber::View &number);
    void notifyCallStarted(utils::PhoneNumber phoneNumber);
    void notifyCallStarted(utils::PhoneNumber phoneNumber, const CallType type);
    void notifyCallEnded();
    void notifyCallActive();
    void notifyCallDurationUpdate(const time_t &duration);

M module-services/service-cellular/call/CellularCall.cpp => module-services/service-cellular/call/CellularCall.cpp +1 -1
@@ 109,7 109,7 @@ namespace CellularCall
            return false;
        }

        gui.notifyCallStarted(number);
        gui.notifyCallStarted(number, type);
        LOG_INFO("call started");
        return true;
    }

M module-services/service-cellular/service-cellular/CellularMessage.hpp => module-services/service-cellular/service-cellular/CellularMessage.hpp +8 -2
@@ 1048,15 1048,21 @@ namespace cellular
    class CallStartedNotification : public sys::DataMessage
    {
      public:
        explicit CallStartedNotification(utils::PhoneNumber phoneNumber)
            : sys::DataMessage(MessageType::MessageTypeUninitialized), phoneNumber(phoneNumber){};
        CallStartedNotification(utils::PhoneNumber phoneNumber, bool isIncoming)
            : sys::DataMessage(MessageType::MessageTypeUninitialized), phoneNumber(phoneNumber),
              isIncoming(isIncoming){};
        utils::PhoneNumber getNumber()
        {
            return phoneNumber;
        };
        bool isCallIncoming()
        {
            return isIncoming;
        };

      private:
        utils::PhoneNumber phoneNumber;
        bool isIncoming;
    };

    class CallEndedNotification : public sys::DataMessage