~aleteoryx/muditaos

3baacec678a271da4d3fdf5113bad250f71f5f4d — Kuba 5 years ago 597c488
[EGD-4860] Add call barring response parser

It allows to show proper GUI windows for call barring MMI responses.
M module-cellular/at/response.cpp => module-cellular/at/response.cpp +108 -0
@@ 520,5 520,113 @@ namespace at
                return false;
            }
        } // namespace ccfc

        namespace mmi
        {
            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 mmi

        namespace clck
        {
            auto parseQueryResponse(const std::vector<std::string> &data, std::vector<ClckParsed> &parsed) -> bool
            {
                using namespace mmi;

                auto constexpr responseToken = "+CLCK: ";
                auto constexpr emptyString   = "";
                auto constexpr minTokens     = 2;
                parsed.clear();

                for (auto el : data) {
                    if (el.find("OK") != std::string::npos) {
                        return true;
                    }
                    if (el.find(responseToken) == std::string::npos) {
                        parsed.clear();
                        return false;
                    }
                    utils::findAndReplaceAll(el, responseToken, emptyString);
                    auto tokens = utils::split(el, ",");
                    if (tokens.size() < minTokens) {
                        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)) {
                        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(ClckParsed(status, serviceClass));
                    }
                    else {
                        parsed.clear();
                        return false;
                    }
                }
                return true;
            }

            auto iterLessIter(ClckParsed a, ClckParsed b) -> bool
            {
                return a.serviceClass < b.serviceClass;
            }

            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::CommonDeactivated;
                    break;
                case Status::Enable:
                    message = IMMICustomResultParams::MMIResultMessage::CommonActivated;
                    break;
                case Status::Query:
                    message = IMMICustomResultParams::MMIResultMessage::CommonQuery;
                    break;
                }
                return message;
            }
        } // namespace clck
    }     // namespace response
} // namespace at

M module-cellular/at/response.hpp => module-cellular/at/response.hpp +40 -0
@@ 334,5 334,45 @@ namespace at
            auto getNumbers(std::vector<ParsedCcfc> &parsed) -> CcfcNumbers;
            auto isAnyActive(std::vector<ParsedCcfc> &parsed) -> bool;
        } // namespace ccfc

        namespace mmi
        {

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

            auto getClass(const ServiceClass &serviceClass) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
        } // namespace mmi

        namespace clck
        {
            enum class Status
            {
                Disable,
                Enable,
                Query
            };

            struct ClckParsed
            {
                Status status;
                mmi::ServiceClass serviceClass;
                explicit ClckParsed(Status status, mmi::ServiceClass serviceClass)
                    : status(status), serviceClass(serviceClass){};
            };

            auto parseQueryResponse(const std::vector<std::string> &data, std::vector<ClckParsed> &parsed) -> bool;
            auto iterLessIter(ClckParsed a, ClckParsed b) -> bool;
            auto getStatus(const Status &status) noexcept
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
        } // namespace clck
    }     // namespace response
} // namespace at

M module-cellular/test/unittest_response.cpp => module-cellular/test/unittest_response.cpp +116 -0
@@ 152,3 152,119 @@ TEST_CASE("Response COPS")
        REQUIRE(at::response::parseCOPS(resp, ret) == false);
    }
}

TEST_CASE("Response CLCK")
{
    SECTION("OK CLCK QUERY - all disabled")
    {

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

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

    SECTION("OK CLCK QUERY - voice enabled")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::clck::ClckParsed> ret;
        resp.response.push_back("+CLCK: 1,1");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == true);
        REQUIRE(ret.size() == 1);
        REQUIRE(ret[0].status == at::response::clck::Status::Enable);
        REQUIRE(ret[0].serviceClass == at::response::mmi::ServiceClass::Voice);
    }

    SECTION("OK CLCK QUERY - voice, fax enabled")
    {

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

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

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

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

    SECTION("WRONG CLCK QUERY - invalid status")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::clck::ClckParsed> ret;
        resp.response.push_back("+CLCK: 8,1");
        resp.response.push_back("+CLCK: 1,4");
        resp.response.push_back("OK");

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

    SECTION("WRONG CLCK QUERY - invalid class")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::clck::ClckParsed> ret;
        resp.response.push_back("+CLCK: 1,1");
        resp.response.push_back("+CLCK: 1,99");
        resp.response.push_back("OK");

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

    SECTION("WRONG CLCK QUERY - too short")
    {

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

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

    SECTION("WRONG CLCK QUERY - invalid response token")
    {

        at::Result resp;
        resp.code = at::Result::Code::OK;
        std::vector<at::response::clck::ClckParsed> ret;
        resp.response.push_back("+CLC: 1,1");
        resp.response.push_back("+CLCK: 1,4");
        resp.response.push_back("OK");

        REQUIRE(resp.code == at::Result::Code::OK);
        REQUIRE(at::response::clck::parseQueryResponse(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
@@ 62,3 62,13 @@ auto MMIResultParams::getCustomData() const noexcept -> std::shared_ptr<MMICusto
{
    return customResult;
}

void MMICallBarringResult::addMessages(const std::pair<MMIResultMessage, MMIResultMessage> &message) noexcept
{
    data.push_back(message);
}

auto MMICallBarringResult::getMessages(void) noexcept -> std::vector<std::pair<MMIResultMessage, MMIResultMessage>>
{
    return data;
}

M module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp => module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp +29 -2
@@ 30,7 30,9 @@ namespace app::manager::actions
            NoneSpecified,
            CallForwardingNotification,
            CallForwardingData,
            Clir
            Clir,
            CallBarringNotification,
            CallBarringData
        };

        enum class MMIResultMessage


@@ 40,6 42,16 @@ namespace app::manager::actions
            CommonFailure,
            CommonMMINotSupported,
            CommonNoMessage,
            CommonVoice,
            CommonData,
            CommonFax,
            CommonAsync,
            CommonSync,
            CommonAllDisabled,

            CommonActivated,
            CommonDeactivated,
            CommonQuery,

            ClirAccordingToSubscription,
            ClirEnabled,


@@ 59,7 71,10 @@ namespace app::manager::actions
            DisablingFailed,
            EnablingSuccessful,
            EnablingFailed,
            CallForwardingDisabled
            CallForwardingDisabled,

            CallBarringActivated,
            CallBarringDeactivated,

        };



@@ 119,6 134,18 @@ namespace app::manager::actions
        {}
    };

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

      private:
        std::vector<std::pair<MMIResultMessage, MMIResultMessage>> data;
    };

    class MMIParams : public ActionParams
    {
      public:

M module-services/service-cellular/CellularRequestHandler.cpp => module-services/service-cellular/CellularRequestHandler.cpp +60 -10
@@ 17,14 17,15 @@
#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-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>

using namespace cellular;

void CellularRequestHandler::handle(ImeiRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::ImeiRequest &request, at::Result &result)
{
    if (!request.checkModemResponse(result)) {
        request.setHandled(false);


@@ 36,7 37,7 @@ void CellularRequestHandler::handle(ImeiRequest &request, at::Result &result)
    sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
}

void CellularRequestHandler::handle(UssdRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::UssdRequest &request, at::Result &result)
{
    auto requestHandled = request.checkModemResponse(result);



@@ 50,7 51,7 @@ void CellularRequestHandler::handle(UssdRequest &request, at::Result &result)
    request.setHandled(requestHandled);
}

void CellularRequestHandler::handle(CallRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::CallRequest &request, at::Result &result)
{
    if (!request.checkModemResponse(result)) {
        request.setHandled(false);


@@ 66,28 67,28 @@ void CellularRequestHandler::handle(CallRequest &request, at::Result &result)
    request.setHandled(true);
}

void CellularRequestHandler::handle(SupplementaryServicesRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::SupplementaryServicesRequest &request, at::Result &result)
{
    auto requestHandled = request.checkModemResponse(result);
    request.setHandled(requestHandled);
    sendMmiResult(requestHandled);
}

void CellularRequestHandler::handle(PasswordRegistrationRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::PasswordRegistrationRequest &request, at::Result &result)
{
    auto requestHandled = request.checkModemResponse(result);
    request.setHandled(requestHandled);
    sendMmiResult(requestHandled);
}

void CellularRequestHandler::handle(PinChangeRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::PinChangeRequest &request, at::Result &result)
{
    auto requestHandled = request.checkModemResponse(result);
    request.setHandled(requestHandled);
    sendMmiResult(requestHandled);
}

void CellularRequestHandler::handle(ClirRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::ClirRequest &request, at::Result &result)
{
    using namespace app::manager::actions;
    using namespace cellular;


@@ 119,7 120,7 @@ void CellularRequestHandler::handle(ClirRequest &request, at::Result &result)
    request.setHandled(requestHandled);
}

void CellularRequestHandler::handle(CallForwardingRequest &request, at::Result &result)
void CellularRequestHandler::handle(cellular::CallForwardingRequest &request, at::Result &result)
{
    using namespace app::manager::actions;
    using namespace cellular;


@@ 184,6 185,55 @@ void CellularRequestHandler::handle(CallForwardingRequest &request, at::Result &
    request.setHandled(requestHandled);
}

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

    std::shared_ptr<MMICustomResultParams> response;
    if (requestHandled) {
        auto procedureType = request.getProcedureType();

        if (procedureType == cellular::SupplementaryServicesRequest::ProcedureType::Activation) {
            response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CallBarringActivated);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Deactivation) {
            response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CallBarringDeactivated);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Interrogation) {
            std::vector<clck::ClckParsed> parsed;

            if (clck::parseQueryResponse(result.response, parsed)) {
                MMICallBarringResult resp = MMICallBarringResult(IMMICustomResultParams::MMIType::CallBarringData);
                std::sort(parsed.begin(), parsed.end(), clck::iterLessIter);
                for (auto el : parsed) {
                    resp.addMessages(std::make_pair<IMMICustomResultParams::MMIResultMessage,
                                                    IMMICustomResultParams::MMIResultMessage>(
                        mmi::getClass(el.serviceClass), clck::getStatus(el.status)));
                }
                response = std::make_shared<MMICallBarringResult>(resp);
            }
        }
        else {
            response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonMMINotSupported);
        }
    }

    if (response == nullptr) {
        response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
        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
@@ 20,6 20,7 @@ class CellularRequestHandler : public cellular::RequestHandler
    void handle(cellular::PinChangeRequest &request, at::Result &result) final;
    void handle(cellular::ClirRequest &request, at::Result &result) final;
    void handle(cellular::CallForwardingRequest &request, at::Result &result) final;
    void handle(cellular::CallBarringRequest &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
@@ 16,6 16,7 @@ namespace cellular
    class ClipRequest;
    class ClirRequest;
    class CallForwardingRequest;
    class CallBarringRequest;

    class RequestHandler
    {


@@ 28,5 29,6 @@ namespace cellular
        virtual void handle(SupplementaryServicesRequest &request, at::Result &result) = 0;
        virtual void handle(ClirRequest &request, at::Result &result)                  = 0;
        virtual void handle(CallForwardingRequest &request, at::Result &result)        = 0;
        virtual void handle(CallBarringRequest &request, at::Result &result)           = 0;
    };
} // namespace cellular