~aleteoryx/muditaos

f7f5bc377ad45f735777096c9edddeeae453b671 — Adam Dobrowolski 4 years ago 2cf6bd6
[EGD-8208] Added stop audio route on async response

We get Token on play, and require it in stop. While we cant
stop sound by title & data set to play. And adding standard
handling causes either totally synchronous calls or requires
multiple additional guards it seemed like best use.
Fixed expectation for the same named Response, but meant for bell
Needed so that
- we ring only when needed
- we handle CLIP and RING properly
Applied style
Missed file added
Moved SML logger as it's usefull to some more common parts of code
M module-apps/apps-common/notifications/NotificationsHandler.cpp => module-apps/apps-common/notifications/NotificationsHandler.cpp +0 -36
@@ 17,16 17,6 @@ NotificationsHandler::NotificationsHandler(sys::Service *parentService, Notifica

void NotificationsHandler::registerMessageHandlers()
{
    parentService->connect(typeid(CellularIncominCallMessage), [&](sys::Message *request) -> sys::MessagePointer {
        incomingCallHandler(request);
        return sys::msgHandled();
    });

    parentService->connect(typeid(CellularCallerIdMessage), [&](sys::Message *request) -> sys::MessagePointer {
        callerIdHandler(request);
        return sys::msgHandled();
    });

    parentService->connect(typeid(CellularIncomingSMSNotificationMessage),
                           [&](sys::Message *request) -> sys::MessagePointer {
                               incomingSMSHandler();


@@ 34,32 24,6 @@ void NotificationsHandler::registerMessageHandlers()
                           });
}

void NotificationsHandler::incomingCallHandler(sys::Message *request)
{
    notifcationConfig.updateCurrentCall(currentCallPolicy);

    if (currentCallPolicy.isPopupAllowed()) {
        auto msg = static_cast<CellularIncominCallMessage *>(request);
        app::manager::Controller::sendAction(parentService,
                                             app::manager::actions::HandleIncomingCall,
                                             std::make_unique<app::manager::actions::CallParams>(msg->number));
    }
}

void NotificationsHandler::callerIdHandler(sys::Message *request)
{
    auto msg = static_cast<CellularCallerIdMessage *>(request);

    if (currentCallPolicy.isPopupAllowed()) {
        app::manager::Controller::sendAction(parentService,
                                             app::manager::actions::HandleCallerId,
                                             std::make_unique<app::manager::actions::CallParams>(msg->number));
    }
    else {
        CellularServiceAPI::DismissCall(parentService, currentCallPolicy.isDismissedCallNotificationAllowed());
    }
}

void NotificationsHandler::incomingSMSHandler()
{
    notifcationConfig.updateCurrentSMS(currentSMSPolicy);

M module-apps/apps-common/notifications/NotificationsHandler.hpp => module-apps/apps-common/notifications/NotificationsHandler.hpp +1 -3
@@ 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


@@ 19,8 19,6 @@ namespace notifications
        void registerMessageHandlers();

      private:
        void incomingCallHandler(sys::Message *request);
        void callerIdHandler(sys::Message *request);
        void incomingSMSHandler();

        void policyNumberCheck(const utils::PhoneNumber::View &number);

M module-apps/apps-common/notifications/policies/CallNotificationPolicy.cpp => module-apps/apps-common/notifications/policies/CallNotificationPolicy.cpp +0 -8
@@ 10,7 10,6 @@ void CallNotificationPolicy::updateCurrentCall(sys::phone_modes::PhoneMode phone
    popupOn           = false;
    ringtoneOn        = false;
    numberCheckNeeded = false;
    dismissedCallNotification = false;

    switch (phoneMode) {
    case sys::phone_modes::PhoneMode::Connected:


@@ 18,11 17,9 @@ void CallNotificationPolicy::updateCurrentCall(sys::phone_modes::PhoneMode phone
        ringtoneOn = true;
        break;
    case sys::phone_modes::PhoneMode::DoNotDisturb:
        dismissedCallNotification = true;
        numberCheckNeeded = true;
        break;
    case sys::phone_modes::PhoneMode::Offline:
        dismissedCallNotification = false;
        break;
    }
}


@@ 37,11 34,6 @@ bool CallNotificationPolicy::isRingtoneAllowed() const noexcept
    return ringtoneOn;
}

bool CallNotificationPolicy::isDismissedCallNotificationAllowed() const noexcept
{
    return dismissedCallNotification;
}

void CallNotificationPolicy::numberCheck(bool callsFromFavouritesSetting, bool isNumberinFavourites)
{
    numberCheckNeeded = false;

M module-apps/apps-common/notifications/policies/CallNotificationPolicy.hpp => module-apps/apps-common/notifications/policies/CallNotificationPolicy.hpp +0 -1
@@ 20,7 20,6 @@ namespace notifications
      private:
        bool popupOn;
        bool ringtoneOn;
        bool dismissedCallNotification;
        bool numberCheckNeeded;
    };
} // namespace notifications

M module-apps/tests/test-PhoneModesPolicies.cpp => module-apps/tests/test-PhoneModesPolicies.cpp +0 -1
@@ 144,5 144,4 @@ TEST_CASE("Offline Mode notifications - calls policy test")
    callPolicy.updateCurrentCall(sys::phone_modes::PhoneMode::Offline);
    REQUIRE(!callPolicy.isPopupAllowed());
    REQUIRE(!callPolicy.isRingtoneAllowed());
    REQUIRE(!callPolicy.isDismissedCallNotificationAllowed());
}

M module-services/service-cellular/CMakeLists.txt => module-services/service-cellular/CMakeLists.txt +1 -0
@@ 18,6 18,7 @@ set(SOURCES

    CellularCall.cpp
    CallAudio.cpp
    CallGUI.cpp
    CallRingGuard.cpp
    CellularServiceAPI.cpp
    CellularUrcHandler.cpp

M module-services/service-cellular/CallAudio.cpp => module-services/service-cellular/CallAudio.cpp +18 -23
@@ 3,44 3,39 @@

#include "CallAudio.hpp"
#include "Service/Message.hpp"
#include "products/BellHybrid/services/audio/include/audio/AudioMessage.hpp"
#include "log/log.hpp"
#include <limits>
#include <service-audio/AudioMessage.hpp>
#include "service-audio/AudioServiceName.hpp"
#include <service-audio/AudioServiceAPI.hpp>
#include <Timers/TimerFactory.hpp>

struct CallRingAudio::CallMeta
{
    audio::Token token;
    sys::TimerHandle retryTimer;
    sys::Async<AudioStartPlaybackRequest, AudioStartPlaybackResponse> p;
};

CallRingAudio::CallRingAudio(sys::Service &s) : owner(s), meta(new CallRingAudio::CallMeta)
{}

CallRingAudio::~CallRingAudio()
{
    delete meta;
}

void CallRingAudio::play()
{
    const auto filePath = AudioServiceAPI::GetSound(&owner, audio::PlaybackType::CallRingtone);
    AudioServiceAPI::PlaybackStart(&owner, audio::PlaybackType::CallRingtone, filePath);
    owner.connect(typeid(service::AudioStartPlaybackResponse), [this](sys::Message *msg) -> sys::MessagePointer {
        auto *message = dynamic_cast<service::AudioStartPlaybackResponse *>(msg);
        assert(meta);
        meta->token = message->token;
        owner.disconnect(typeid(service::AudioStartPlaybackResponse));
        return sys::msgHandled();
    });
    started = true;
    const auto file = AudioServiceAPI::GetSound(&owner, audio::PlaybackType::CallRingtone);
    meta->p         = owner.async_call<AudioStartPlaybackRequest, AudioStartPlaybackResponse>(
        service::name::audio, file, audio::PlaybackType::CallRingtone);
}

void CallRingAudio::stop()
{
    assert(meta && "we have stop without start - this should never happen");
    // there is still a chance we didn't get the token - in this case, maybe timer? :D
    if (!meta->token.IsValid() && !meta->retryTimer.isActive()) {
        meta->retryTimer = sys::TimerFactory::createPeriodicTimer(
            &owner, "retry stop music", std::chrono::seconds{1}, [this](sys::Timer &) {
                meta->token.IsValid();
                AudioServiceAPI::Stop(&owner, meta->token);
                meta->retryTimer.stop();
            });
        meta->retryTimer.start();
    if ( not started ) {
        return;
    }
    AudioServiceAPI::Stop(&owner, meta->token);
    owner.sync(meta->p);
    AudioServiceAPI::Stop(&owner, meta->p.getResult().token);
}

M module-services/service-cellular/CallAudio.hpp => module-services/service-cellular/CallAudio.hpp +3 -1
@@ 12,10 12,12 @@ class CallRingAudio
{
    struct CallMeta;
    sys::Service &owner;
    CallMeta *meta;
    CallMeta *meta = nullptr;
    bool started = false;

  public:
    explicit CallRingAudio(sys::Service &);
    ~CallRingAudio();

    void play();
    void stop();

A module-services/service-cellular/CallGUI.cpp => module-services/service-cellular/CallGUI.cpp +24 -0
@@ 0,0 1,24 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CallGUI.hpp"
#include "service-appmgr/data/CallActionsParams.hpp"
#include <service-appmgr/Controller.hpp>

CallGUI::CallGUI(sys::Service &s) : owner(s)
{}


void CallGUI::notifyRING()
{
        app::manager::Controller::sendAction(&owner,
                                             app::manager::actions::HandleIncomingCall,
                                             std::make_unique<app::manager::actions::CallParams>());
}

void CallGUI::notifyCLIP(const utils::PhoneNumber::View & number)
{
        app::manager::Controller::sendAction(&owner,
                                             app::manager::actions::HandleCallerId,
                                             std::make_unique<app::manager::actions::CallParams>(number));
}

A module-services/service-cellular/CallGUI.hpp => module-services/service-cellular/CallGUI.hpp +23 -0
@@ 0,0 1,23 @@
// 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 <PhoneNumber.hpp>

namespace sys
{
    class Service;
}

class CallGUI
{
    struct CallMeta;
    sys::Service &owner;

  public:
    explicit CallGUI(sys::Service &);

    void notifyRING();
    void notifyCLIP(const utils::PhoneNumber::View & number);
};

M module-services/service-cellular/CallRingGuard.cpp => module-services/service-cellular/CallRingGuard.cpp +7 -4
@@ 4,9 4,12 @@
#include "CallRingGuard.hpp"
#include "service-cellular/CellularCall.hpp"

bool callRingGuard(CellularCall::CellularCall &call)
bool callRingGuard(CellularCall::Call &call)
{
    return call.mode == sys::phone_modes::PhoneMode::Connected ||
           (call.mode == sys::phone_modes::PhoneMode::DoNotDisturb && call.operations.areCallsFromFavouritesEnabled() &&
            call.operations.isNumberInFavourites());
    return call.mode == sys::phone_modes::PhoneMode::Connected;
}

bool callClipGuard(CellularCall::Call &call)
{
    return call.mode == sys::phone_modes::PhoneMode::DoNotDisturb && call.operations.areCallsFromFavouritesEnabled() && call.operations.isNumberInFavourites();
}

A module-services/service-cellular/CallRingGuard.hpp => module-services/service-cellular/CallRingGuard.hpp +26 -0
@@ 0,0 1,26 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#pragma once

namespace CellularCall
{
    class Call;
}

/// Guard to check if we should ring on cellular RING URC
/// This flow is when:
/// - We are in normal mode
/// - somebody calls
/// Without this check we could never ring on private numbers
bool callRingGuard(CellularCall::Call &call);

/// Guard to check if we should ring on cellular CLIP URC
/// This flow is when:
/// - We are in do not disturb mode
/// - somebody calls
/// - we have this somebody phone number via CLIP URC
/// It wont be ever called for private numbers
bool callClipGuard(CellularCall::Call &call);

M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +38 -9
@@ 21,7 21,7 @@

namespace CellularCall
{
    CellularCall::CellularCall(ServiceCellular &owner) : owner(owner), audio(owner)
    Call::Call(ServiceCellular &owner) : owner(owner), audio(owner), gui(owner)
    {
        utils::PhoneNumber::View number = utils::PhoneNumber::View();
        const CallType type             = CallType::CT_NONE;


@@ 37,10 37,39 @@ namespace CellularCall
        this->call.name        = number.getEntered(); // temporary set number as name
    }

    bool CellularCall::startCall(const utils::PhoneNumber::View &number, const CallType type)
    bool Call::handleRING()
    {
        callRingGuard(*this) ? audio.play() : void();
        if (callRingGuard(*this)) {
            startCall(utils::PhoneNumber::View(), CallType::CT_INCOMING);
            audio.play();
            gui.notifyRING();
            return true;
        }
        return false;
    }

    bool Call::handleCLIP(const utils::PhoneNumber::View &number)
    {
        setNumber(number);
        if ( callClipGuard(*this)) {
            startCall(number, CallType::CT_INCOMING);
            audio.play();
        }

        if (callClipGuard(*this) || callRingGuard(*this)) {
            gui.notifyCLIP(number);
            return true;
        }
        return false;
    }

    bool Call::startOutgoing(const utils::PhoneNumber::View &number)
    {
        return startCall(number, CallType::CT_OUTGOING);
    }

    bool Call::startCall(const utils::PhoneNumber::View &number, const CallType type)
    {
        LOG_INFO("starting call");

        if (isValid()) {


@@ 69,7 98,7 @@ namespace CellularCall
        return true;
    }

    bool CellularCall::setActive()
    bool Call::setActive()
    {
        if (isValid()) {
            startActiveTime = utils::time::getCurrentTimestamp();


@@ 81,7 110,7 @@ namespace CellularCall
        return false;
    }

    bool CellularCall::endCall(Forced forced)
    bool Call::endCall(Forced forced)
    {
        audio.stop();
        LOG_INFO("ending call");


@@ 133,23 162,23 @@ namespace CellularCall
        return true;
    }

    void CellularCall::setNumber(const utils::PhoneNumber::View &number)
    void Call::setNumber(const utils::PhoneNumber::View &number)
    {
        call.presentation = number.getFormatted().empty() ? PresentationType::PR_UNKNOWN : PresentationType::PR_ALLOWED;
        call.phoneNumber  = number;
    }

    void CellularCall::setCpuSentinel(std::shared_ptr<sys::CpuSentinel> sentinel)
    void Call::setCpuSentinel(std::shared_ptr<sys::CpuSentinel> sentinel)
    {
        cpuSentinel = std::move(sentinel);
    }

    bool CellularCall::Operations::areCallsFromFavouritesEnabled()
    bool Call::Operations::areCallsFromFavouritesEnabled()
    {
        return owner.owner.areCallsFromFavouritesEnabled();
    }

    bool CellularCall::Operations::isNumberInFavourites()
    bool Call::Operations::isNumberInFavourites()
    {
        return DBServiceAPI::IsContactInFavourites(&owner.owner, owner.call.phoneNumber);
    }

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +7 -8
@@ 43,7 43,6 @@
#include <Utility.hpp>
#include <at/cmd/CLCC.hpp>
#include <at/cmd/CFUN.hpp>
#include <at/UrcClip.hpp>
#include <at/UrcCmti.hpp>
#include <at/UrcCreg.hpp>
#include <at/UrcCtze.hpp>


@@ 1925,25 1924,23 @@ auto ServiceCellular::handleDBNotificationMessage(db::NotificationMessage *msg) 
auto ServiceCellular::handleCellularRingingMessage(CellularRingingMessage *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    LOG_INFO("%s", __PRETTY_FUNCTION__);
    return std::make_shared<CellularResponseMessage>(ongoingCall.startCall(msg->number, CallType::CT_OUTGOING));
    return std::make_shared<CellularResponseMessage>(ongoingCall.startOutgoing(msg->number));
}

auto ServiceCellular::handleCellularIncomingCallMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    LOG_INFO("%s", __PRETTY_FUNCTION__);
    auto ret     = true;
    auto message = static_cast<CellularIncominCallMessage *>(msg);

    if (!ongoingCall.isValid()) {
        ret = ongoingCall.startCall(message->number, CallType::CT_INCOMING);
    }
    return std::make_shared<CellularResponseMessage>(ret);
}

auto ServiceCellular::handleCellularCallerIdMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    auto message = static_cast<CellularCallerIdMessage *>(msg);
    ongoingCall.setNumber(message->number);
    if ( not ongoingCall.handleCLIP(message->number) ) {
        CellularServiceAPI::DismissCall(this, phoneModeObserver->getCurrentPhoneMode() == sys::phone_modes::PhoneMode::DoNotDisturb);
    }

    return sys::MessageNone{};
}



@@ 2207,6 2204,7 @@ auto ServiceCellular::handleCellularRingNotification(sys::Message *msg) -> std::
    if (phoneModeObserver->isTetheringOn() || connectionManager->forceDismissCalls()) {
        return std::make_shared<CellularResponseMessage>(hangUpCall());
    }
    ongoingCall.handleRING();

    /// NOTE: the code below should be investigated as there is something weird in this flow
    if (!callManager.isIncomingCallPropagated()) {


@@ 2223,6 2221,7 @@ auto ServiceCellular::handleCellularCallerIdNotification(sys::Message *msg) -> s
        return std::make_shared<CellularResponseMessage>(hangUpCall());
    }


    auto message = static_cast<CellularCallerIdNotification *>(msg);
    if (phoneModeObserver->isTetheringOn()) {
        tetheringCalllog.push_back(CalllogRecord{CallType::CT_MISSED, message->getNubmer()});

M module-services/service-cellular/service-cellular/CellularCall.hpp => module-services/service-cellular/service-cellular/CellularCall.hpp +12 -5
@@ 4,6 4,7 @@
#pragma once

#include "CallAudio.hpp"
#include "CallGUI.hpp"
#include "PhoneModes/PhoneMode.hpp"
#include <Interface/CalllogRecord.hpp>
#include <SystemManager/CpuSentinel.hpp>


@@ 30,7 31,7 @@ namespace CellularCall
        True
    };

    class CellularCall
    class Call
    {
        CalllogRecord call;
        bool isActiveCall = false;


@@ 59,6 60,7 @@ namespace CellularCall

        ServiceCellular &owner;
        CallRingAudio audio;
        CallGUI gui;

      public:
        void setMode(sys::phone_modes::PhoneMode mode)


@@ 67,13 69,14 @@ namespace CellularCall
        }

        mutable sys::phone_modes::PhoneMode mode;
        CellularCall(ServiceCellular &owner);
        explicit Call(ServiceCellular &owner);

        void setStartCallAction(const std::function<CalllogRecord(const CalllogRecord &rec)> callAction)
        {
            startCallAction = callAction;
        }

        void ongoingCallShowUI();
        void setEndCallAction(const std::function<bool(const CalllogRecord &rec)> callAction)
        {
            endCallAction = callAction;


@@ 81,7 84,11 @@ namespace CellularCall

        bool setActive();
        void setNumber(const utils::PhoneNumber::View &number);
        bool ringAudioOnClip();

        bool startOutgoing(const utils::PhoneNumber::View &number);
        bool handleRING();
        bool handleCLIP(const utils::PhoneNumber::View &number);
        bool startCall(const utils::PhoneNumber::View &number, const CallType type);
        bool endCall(Forced forced = Forced::False);



@@ 108,9 115,9 @@ namespace CellularCall
            bool isNumberInFavourites();

          private:
            friend CellularCall;
            CellularCall &owner;
            explicit Operations(CellularCall &owner) : owner(owner)
            friend Call;
            Call &owner;
            explicit Operations(Call &owner) : owner(owner)
            {}
        };
        Operations operations = Operations(*this);

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +1 -1
@@ 140,7 140,7 @@ class ServiceCellular : public sys::Service

    std::vector<std::string> messageParts;

    CellularCall::CellularCall ongoingCall = CellularCall::CellularCall(*this);
    CellularCall::Call ongoingCall = CellularCall::Call(*this);
    std::vector<CalllogRecord> tetheringCalllog;

    ussd::State ussdState = ussd::State::none;

M module-sys/Service/BusProxy.cpp => module-sys/Service/BusProxy.cpp +1 -1
@@ 24,7 24,7 @@ namespace sys
        return ret;
    }

    SendResult BusProxy::unicastSync(std::shared_ptr<Message> message, sys::Service*whose,  std::uint32_t timeout)
    SendResult BusProxy::unicastSync(std::shared_ptr<Message> message, sys::Service *whose, std::uint32_t timeout)
    {
        auto ret = busImpl->UnicastSync(message, whose, timeout);
        if (ret.first != ReturnCodes::Failure) {

M module-sys/Service/Service.cpp => module-sys/Service/Service.cpp +7 -8
@@ 31,7 31,7 @@ void debug_msg(sys::Service *srvc, const sys::Message *ptr)
    assert(srvc);
    assert(ptr);

    if (xPortIsInsideInterrupt()){
    if (xPortIsInsideInterrupt()) {
        throw std::runtime_error("message sent from irq");
    }
    if (xTaskGetCurrentTaskHandle() == nullptr) {


@@ 39,11 39,11 @@ void debug_msg(sys::Service *srvc, const sys::Message *ptr)
    }

    LOG_DEBUG("([%s] -> [%s] (%s) data: %s | %s",
             ptr ? ptr->sender.c_str() : "",
             srvc ? srvc->GetName().c_str() : "",
             realname,
             std::string(*ptr).c_str(),
             ptr->to_string().c_str());
              ptr ? ptr->sender.c_str() : "",
              srvc ? srvc->GetName().c_str() : "",
              realname,
              std::string(*ptr).c_str(),
              ptr->to_string().c_str());
#else
#endif
}


@@ 62,8 62,7 @@ namespace sys
    Service::Service(
        std::string name, std::string parent, uint32_t stackDepth, ServicePriority priority, Watchdog &watchdog)
        : cpp_freertos::Thread(name, stackDepth / 4 /* Stack depth in bytes */, static_cast<UBaseType_t>(priority)),
          parent(parent), bus(this, watchdog), mailbox(this), watchdog(watchdog),
          isReady(false), enableRunLoop(false)
          parent(parent), bus(this, watchdog), mailbox(this), watchdog(watchdog), isReady(false), enableRunLoop(false)
    {}

    Service::~Service()

M module-sys/Service/details/bus/Bus.cpp => module-sys/Service/details/bus/Bus.cpp +8 -8
@@ 101,16 101,16 @@ namespace sys
        return false;
    }

    namespace {
        template <class W, class X>
        void restoreMessagess(W &mailbox, X &tempMsg)
    namespace
    {
        template <class W, class X> void restoreMessagess(W &mailbox, X &tempMsg)
        {
                // Push messages collected during waiting for response to processing queue
                for (const auto &w : tempMsg) {
                    mailbox.push(w);
                }
            // Push messages collected during waiting for response to processing queue
            for (const auto &w : tempMsg) {
                mailbox.push(w);
            }
        }
    }
    } // namespace

    SendResult Bus::SendUnicastSync(std::shared_ptr<Message> message,
                                    const std::string &targetName,

M module-sys/Service/include/Service/Service.hpp => module-sys/Service/include/Service/Service.hpp +28 -20
@@ 29,8 29,9 @@ namespace sys

    class async_fail : public std::runtime_error
    {
        public: 
            async_fail() : runtime_error("async failure") {}
      public:
        async_fail() : runtime_error("async failure")
        {}
    };

    template <typename Request, typename Response> struct Async // : public with_timer


@@ 48,18 49,19 @@ namespace sys
            return m->state;
        }

        Response& getResult()
        Response &getResult()
        {
            return *m->result;
        }

        Request& getRequest()
        Request &getRequest()
        {
            return *m->request;
        }

        static_assert(std::is_base_of<sys::Message, Request>::value, "Request has to be based on system message");
        static_assert(std::is_base_of<sys::ResponseMessage, Response>::value, "Response has to be based on system response message");
        static_assert(std::is_base_of<sys::ResponseMessage, Response>::value,
                      "Response has to be based on system response message");
        explicit operator bool()
        {
            return m->state == State::Done;


@@ 67,8 69,12 @@ namespace sys

      private:
        friend sys::Service;
        void setState(State state) { this->m->state=state;}
        struct M {
        void setState(State state)
        {
            this->m->state = state;
        }
        struct M
        {
            State state = State::Pending;
            std::shared_ptr<Request> request;
            std::shared_ptr<Response> result;


@@ 149,18 155,19 @@ namespace sys
        template <typename Request, typename Response, typename... Arg>
        Async<Request, Response> async_call(std::string whom, Arg... arg)
        {
            static_assert(std::is_base_of<sys::ResponseMessage, Response>::value, "Response has to be based on system message");
            Async<Request,Response> p;
            static_assert(std::is_base_of<sys::ResponseMessage, Response>::value,
                          "Response has to be based on system message");
            Async<Request, Response> p;
            auto request = std::make_shared<Request>(arg...);
            if (isConnected(std::type_index(typeid(Response)))) {
                p.setState(Async<Request,Response>::State::Error);
                p.setState(Async<Request, Response>::State::Error);
                throw async_fail();
            }
            auto meta = p.m;
            meta->request = request;
            auto meta                                    = p.m;
            meta->request                                = request;
            std::function<MessagePointer(Message *)> foo = [this, meta](Message *m) {
                auto &response = dynamic_cast<Response &>(*m);
                meta->state = Async<Request,Response>::State::Done;
                meta->state    = Async<Request, Response>::State::Done;
                // this is counter productive - but this is what needs to be done here
                meta->result = std::make_shared<Response>(response);
                disconnect(typeid(Response));


@@ 176,23 183,24 @@ namespace sys
            return p;
        }

        template <typename Request,typename Response>
        void sync(Async<Request,Response> &p, std::uint32_t timeout=std::numeric_limits<std::uint32_t>::max())
        template <typename Request, typename Response>
        void sync(Async<Request, Response> &p, std::uint32_t timeout = std::numeric_limits<std::uint32_t>::max())
        {
            static_assert(std::is_base_of<sys::ResponseMessage, Response>::value, "Response has to be based on system message");
            static_assert(std::is_base_of<sys::ResponseMessage, Response>::value,
                          "Response has to be based on system message");
            if (p.m->request == nullptr) {
                throw async_fail();
            }
            if (p.getState() !=  Async<Request,Response>::State::Pending) {
            if (p.getState() != Async<Request, Response>::State::Pending) {
                return;
            }
            auto val = bus.unicastSync(p.m->request, this, timeout);
            if (val.first != sys::ReturnCodes::Success) {
                val.first == sys::ReturnCodes::Timeout ? p.setState(Async<Request,Response>::State::TimedOut):
                                                         p.setState(Async<Request,Response>::State::Error);
                val.first == sys::ReturnCodes::Timeout ? p.setState(Async<Request, Response>::State::TimedOut)
                                                       : p.setState(Async<Request, Response>::State::Error);
                return;
            }
            this->HandleResponse(dynamic_cast<sys::ResponseMessage*>(val.second.get()));
            this->HandleResponse(dynamic_cast<sys::ResponseMessage *>(val.second.get()));
        }

        void sendCloseReadyMessage(Service *service);

M products/BellHybrid/apps/application-bell-main/CMakeLists.txt => products/BellHybrid/apps/application-bell-main/CMakeLists.txt +2 -1
@@ 33,7 33,6 @@ target_sources(application-bell-main

        presenters/HomeScreenPresenter.hpp
        presenters/StateController.hpp
        presenters/StateControllerLogger.hpp

    PUBLIC
        include/application-bell-main/ApplicationBellMain.hpp


@@ 68,4 67,6 @@ target_link_libraries(application-bell-main
        ${TARGET_LIBRARIES}
    PUBLIC
        bell::app-common
        sml::sml
        sml::utils::logger
)

M third-party/CMakeLists.txt => third-party/CMakeLists.txt +1 -0
@@ 21,6 21,7 @@ add_subdirectory(protobuf)
add_subdirectory(pugixml)
add_subdirectory(re2)
add_subdirectory(sml)
add_subdirectory(sml-utils)
add_subdirectory(taglib)
add_subdirectory(tinyexpr)
add_subdirectory(utz)

A third-party/sml-utils/CMakeLists.txt => third-party/sml-utils/CMakeLists.txt +4 -0
@@ 0,0 1,4 @@
add_library(sml-logger INTERFACE) 
add_library(sml::utils::logger ALIAS sml-logger)

target_include_directories(sml-logger INTERFACE include/) 

R products/BellHybrid/apps/application-bell-main/presenters/StateControllerLogger.hpp => third-party/sml-utils/include/sml-utils/Logger.hpp +0 -0