~aleteoryx/muditaos

20c7efdd71eeab2f740b063d40280bf0cb2983c4 — Kuba 5 years ago d896843
[EGD-4861] Call waiting response parser

It allows to show proper GUI windows for call waiting MMI responses.
M module-cellular/at/response.cpp => module-cellular/at/response.cpp +102 -0
@@ 685,5 685,107 @@ namespace at
                return message;
            }
        } // namespace clip

        namespace ccwa
        {
            auto parse(const std::vector<std::string> &data, std::vector<CcwaParsed> &parsed) noexcept -> bool
            {

                auto constexpr toRemove    = "+CCWA: ";
                auto constexpr emptyString = "";
                auto constexpr tokenCount  = 2;
                parsed.clear();

                for (auto el : data) {

                    if (el.find("OK") != std::string::npos) {
                        return true;
                    }

                    if (el.find(toRemove) == std::string::npos) {
                        parsed.clear();
                        return false;
                    }

                    utils::findAndReplaceAll(el, toRemove, emptyString);
                    auto tokens = utils::split(el, ",");
                    if (tokens.size() != tokenCount) {
                        parsed.clear();
                        return false;
                    }

                    for (auto &t : tokens) {
                        t = utils::trim(t);
                    }
                    int statusToken       = 0;
                    int serviceClassToken = 0;

                    if (!utils::toNumeric(tokens[0], statusToken) || !utils::toNumeric(tokens[1], serviceClassToken)) {
                        parsed.clear();
                        return false;
                    }
                    auto status       = static_cast<Status>(statusToken);
                    auto serviceClass = static_cast<ServiceClass>(serviceClassToken);

                    if (magic_enum::enum_contains<Status>(status) &&
                        magic_enum::enum_contains<ServiceClass>(serviceClass)) {
                        parsed.push_back(CcwaParsed(status, serviceClass));
                    }
                    else {
                        parsed.clear();
                        return false;
                    }
                }

                return true;
            }

            auto getStatus(const Status &status) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage
            {
                using namespace app::manager::actions;

                auto message = IMMICustomResultParams::MMIResultMessage::CommonNoMessage;
                switch (status) {
                case Status::Disable:
                    message = IMMICustomResultParams::MMIResultMessage::CallWaitingDeactivated;
                    break;
                case Status::Enable:
                    message = IMMICustomResultParams::MMIResultMessage::CallWaitingActivated;
                    break;
                }
                return message;
            }

            auto getClass(const ServiceClass &serviceClass) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage
            {
                using namespace app::manager::actions;

                auto message = IMMICustomResultParams::MMIResultMessage::CommonNoMessage;
                switch (serviceClass) {
                case ServiceClass::Voice:
                    message = IMMICustomResultParams::MMIResultMessage::CommonVoice;
                    break;
                case ServiceClass::Data:
                    message = IMMICustomResultParams::MMIResultMessage::CommonData;
                    break;
                case ServiceClass::Fax:
                    message = IMMICustomResultParams::MMIResultMessage::CommonFax;
                    break;
                case ServiceClass::DataSync:
                    message = IMMICustomResultParams::MMIResultMessage::CommonSync;
                    break;
                case ServiceClass::DataAsync:
                    message = IMMICustomResultParams::MMIResultMessage::CommonAsync;
                    break;
                case ServiceClass::AllDisabled:
                    message = IMMICustomResultParams::MMIResultMessage::CommonAllDisabled;
                    break;
                }
                return message;
            }

        } // namespace ccwa
    }     // namespace response
} // namespace at

M module-cellular/at/response.hpp => module-cellular/at/response.hpp +32 -0
@@ 404,5 404,37 @@ namespace at
            auto getStatus(const Status &status) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
        } // namespace clck

        namespace ccwa
        {
            enum class Status
            {
                Disable,
                Enable
            };
            enum class ServiceClass
            {
                Voice       = 1,
                Data        = 2,
                Fax         = 4,
                DataSync    = 16,
                DataAsync   = 32,
                AllDisabled = 255
            };

            struct CcwaParsed
            {
                Status status;
                ServiceClass serviceClass;
                explicit CcwaParsed(const Status status, const ServiceClass serviceClass)
                    : status(status), serviceClass(serviceClass){};
            };

            auto parse(const std::vector<std::string> &data, std::vector<CcwaParsed> &parsed) noexcept -> bool;
            auto getStatus(const Status &status) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
            auto getClass(const ServiceClass &serviceClass) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
        } // namespace ccwa
    }     // namespace response
} // namespace at

M module-cellular/test/unittest_response.cpp => module-cellular/test/unittest_response.cpp +115 -0
@@ 434,3 434,118 @@ TEST_CASE("Response CLCK")
        REQUIRE(ret.size() == 0);
    }
}

TEST_CASE("Response CCWA?")
{
    SECTION("OK CCWA?  - all disabled")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCWA: 0,255");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == true);
        REQUIRE(ret.size() == 1);
        REQUIRE(ret[0].status == at::response::ccwa::Status::Disable);
        REQUIRE(ret[0].serviceClass == at::response::ccwa::ServiceClass::AllDisabled);
    }

    SECTION("OK CCWA?  - voice, fax enabled")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCWA: 1,1");
        resp.response.push_back("+CCWA: 1,4");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == true);
        REQUIRE(ret.size() == 2);

        REQUIRE(ret[0].status == at::response::ccwa::Status::Enable);
        REQUIRE(ret[0].serviceClass == at::response::ccwa::ServiceClass::Voice);

        REQUIRE(ret[1].status == at::response::ccwa::Status::Enable);
        REQUIRE(ret[1].serviceClass == at::response::ccwa::ServiceClass::Fax);
    }

    SECTION("WRONG CCWA?  - invalid status")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCWA: 9,1");
        resp.response.push_back("+CCWA: 1,4");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == false);
        REQUIRE(ret.size() == 0);
    }

    SECTION("WRONG CCWA?  - invalid class")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCWA: 1,1");
        resp.response.push_back("+CCWA: 1,66");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == false);
        REQUIRE(ret.size() == 0);
    }

    SECTION("WRONG CCWA?  - invalid token")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCW: 1,1");
        resp.response.push_back("+CCWA: 1,66");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == false);
        REQUIRE(ret.size() == 0);
    }

    SECTION("WRONG CCWA?  - to little tokens")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCWA: 1,1");
        resp.response.push_back("+CCWA: 1");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == false);
        REQUIRE(ret.size() == 0);
    }

    SECTION("WRONG CCWA?  - to many tokens")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::ccwa::CcwaParsed> ret;
        resp.response.push_back("+CCWA: 1,1,9");
        resp.response.push_back("+CCWA: 1,4");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::ccwa::parse(resp.response, ret) == false);
        REQUIRE(ret.size() == 0);
    }
}

M module-services/service-appmgr/data/MmiActionsParams.cpp => module-services/service-appmgr/data/MmiActionsParams.cpp +10 -0
@@ 77,3 77,13 @@ auto MMIImeiResult::getImei() const noexcept -> std::string
{
    return imei;
}

void MMICallWaitingResult::addMessages(const std::pair<MMIResultMessage, MMIResultMessage> &message)
{
    messages.push_back(message);
}

auto MMICallWaitingResult::getMessages() const noexcept -> std::vector<std::pair<MMIResultMessage, MMIResultMessage>>
{
    return messages;
}

M module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp => module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp +18 -1
@@ 34,7 34,9 @@ namespace app::manager::actions
            Clip,
            Imei,
            CallBarringNotification,
            CallBarringData
            CallBarringData,
            CallWaitingNotification,
            CallWaitingData
        };

        enum class MMIResultMessage


@@ 85,6 87,9 @@ namespace app::manager::actions
            ClipProvisioned,
            ClipUnknown,

            CallWaitingActivated,
            CallWaitingDeactivated,

        };

        virtual auto getMessage() const -> std::vector<MMIResultMessage> = 0;


@@ 204,4 209,16 @@ namespace app::manager::actions
      private:
        std::string imei;
    };

    class MMICallWaitingResult : public MMICustomResultParams
    {
      public:
        explicit MMICallWaitingResult(const MMIType type) : MMICustomResultParams(type)
        {}
        void addMessages(const std::pair<MMIResultMessage, MMIResultMessage> &message);
        auto getMessages() const noexcept -> std::vector<std::pair<MMIResultMessage, MMIResultMessage>>;

      private:
        std::vector<std::pair<MMIResultMessage, MMIResultMessage>> messages;
    };
} // namespace app::manager::actions

M module-services/service-cellular/CellularRequestHandler.cpp => module-services/service-cellular/CellularRequestHandler.cpp +48 -3
@@ 15,15 15,13 @@
#include "service-cellular/requests/PinChangeRequest.hpp"
#include "service-cellular/requests/ImeiRequest.hpp"
#include "service-cellular/requests/UssdRequest.hpp"
#include "service-cellular/service-cellular/requests/ClirRequest.hpp"
#include "service-cellular/requests/CallForwardingRequest.hpp"
#include "service-cellular/requests/CallBarringRequest.hpp"
#include "service-cellular/requests/ClirRequest.hpp"
#include "service-cellular/requests/ClipRequest.hpp"
#include "service-cellular/requests/CallWaitingRequest.hpp"

#include <service-appmgr/model/ApplicationManager.hpp>
#include "service-cellular/service-cellular/requests/ClirRequest.hpp"
#include "service-cellular/service-cellular/requests/SupplementaryServicesRequest.hpp"

#include <module-cellular/at/response.hpp>



@@ 281,6 279,53 @@ void CellularRequestHandler::handle(cellular::ClipRequest &request, at::Result &
    request.setHandled(requestHandled);
}

void CellularRequestHandler::handle(cellular::CallWaitingRequest &request, at::Result &result)
{
    using namespace app::manager::actions;
    using namespace cellular;
    using namespace at::response;
    auto requestHandled = request.checkModemResponse(result);

    std::shared_ptr<MMICustomResultParams> response;
    if (requestHandled) {
        auto procedureType = request.getProcedureType();
        if (procedureType == SupplementaryServicesRequest::ProcedureType::Activation) {
            response = std::make_shared<MMICallWaitingResult>(IMMICustomResultParams::MMIType::CallWaitingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CallWaitingActivated);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Deactivation) {
            response = std::make_shared<MMICallWaitingResult>(IMMICustomResultParams::MMIType::CallWaitingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CallWaitingDeactivated);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Interrogation) {
            std::vector<ccwa::CcwaParsed> parsed;
            if (ccwa::parse(result.response, parsed)) {
                MMICallWaitingResult resp = MMICallWaitingResult(IMMICustomResultParams::MMIType::CallWaitingData);
                for (auto el : parsed) {
                    resp.addMessages(std::make_pair(ccwa::getClass(el.serviceClass), ccwa::getStatus(el.status)));
                }
                response = std::make_shared<MMICallWaitingResult>(resp);
            }
            else {
                response =
                    std::make_shared<MMICallWaitingResult>(IMMICustomResultParams::MMIType::CallWaitingNotification);
                response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure);
            }
        }
        else {
            response = std::make_shared<MMICallWaitingResult>(IMMICustomResultParams::MMIType::CallWaitingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonMMINotSupported);
        }
    }
    else {
        response = std::make_shared<MMICallWaitingResult>(IMMICustomResultParams::MMIType::CallWaitingNotification);
        response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure);
    }
    auto msg = std::make_shared<CellularMMIResultMessage>(MMIResultParams::MMIResult::Success, response);
    sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
    request.setHandled(requestHandled);
}

void CellularRequestHandler::sendMmiResult(bool result)
{
    using namespace app::manager::actions;

M module-services/service-cellular/service-cellular/CellularRequestHandler.hpp => module-services/service-cellular/service-cellular/CellularRequestHandler.hpp +1 -0
@@ 22,6 22,7 @@ class CellularRequestHandler : public cellular::RequestHandler
    void handle(cellular::ClipRequest &request, at::Result &result) final;
    void handle(cellular::CallForwardingRequest &request, at::Result &result) final;
    void handle(cellular::CallBarringRequest &request, at::Result &result) final;
    void handle(cellular::CallWaitingRequest &request, at::Result &result) final;

  private:
    ServiceCellular &cellular;

M module-services/service-cellular/service-cellular/RequestHandler.hpp => module-services/service-cellular/service-cellular/RequestHandler.hpp +2 -0
@@ 17,6 17,7 @@ namespace cellular
    class ClirRequest;
    class CallForwardingRequest;
    class CallBarringRequest;
    class CallWaitingRequest;

    class RequestHandler
    {


@@ 31,5 32,6 @@ namespace cellular
        virtual void handle(ClipRequest &request, at::Result &result)                  = 0;
        virtual void handle(CallForwardingRequest &request, at::Result &result)        = 0;
        virtual void handle(CallBarringRequest &request, at::Result &result)           = 0;
        virtual void handle(CallWaitingRequest &request, at::Result &result)           = 0;
    };
} // namespace cellular