~aleteoryx/muditaos

d2b9a10dd3cc4d3441c5bc0935da25bbb0eeae70 — Lefucjusz 2 years ago f7ad63c
[MOS-1002] Change USSD code handling to match design

Fixed issues with GUI behaviour on failed
USSD code handling.
Minor code cleanup in several parts of system.
40 files changed, 362 insertions(+), 307 deletions(-)

M image/system_a/data/lang/Deutsch.json
M image/system_a/data/lang/English.json
M image/system_a/data/lang/Espanol.json
M image/system_a/data/lang/Francais.json
M image/system_a/data/lang/Polski.json
M image/system_a/data/lang/Svenska.json
M module-apps/application-call/windows/CallWindow.cpp
M module-apps/application-call/windows/EnterNumberWindow.cpp
M module-apps/application-call/windows/NumberWindow.cpp
M module-apps/application-desktop/include/application-desktop/Names.hpp
M module-apps/application-desktop/windows/MmiConfirmationWindow.cpp
M module-apps/application-desktop/windows/MmiConfirmationWindow.hpp
M module-apps/application-desktop/windows/MmiInternalMsgWindow.cpp
M module-apps/application-desktop/windows/MmiPullWindow.cpp
M module-apps/application-desktop/windows/MmiPullWindow.hpp
M module-apps/application-desktop/windows/MmiPushWindow.cpp
M module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp
M module-apps/apps-common/popups/Popups.hpp
M module-apps/apps-common/windows/AppWindow.cpp
M module-apps/apps-common/windows/AppWindow.hpp
M module-cellular/at/src/UrcCusd.cpp
M module-cellular/at/src/UrcFactory.cpp
M module-services/service-appmgr/include/service-appmgr/data/MmiActionsParams.hpp
M module-services/service-cellular/CellularRequestHandler.cpp
M module-services/service-cellular/CellularServiceAPI.cpp
M module-services/service-cellular/CellularUrcHandler.cpp
M module-services/service-cellular/RequestFactory.cpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/include/service-cellular/api/common.hpp
M module-services/service-cellular/requests/PasswordRegistrationRequest.cpp
M module-services/service-cellular/service-cellular/CellularMessage.hpp
M module-services/service-cellular/service-cellular/CellularServiceAPI.hpp
M module-services/service-cellular/service-cellular/RequestFactory.hpp
M module-services/service-cellular/service-cellular/ServiceCellular.hpp
M module-services/service-cellular/src/ServiceCellularPriv.cpp
M module-services/service-cellular/src/ussd/USSDHandler.cpp
M module-services/service-cellular/src/ussd/USSDHandler.hpp
M module-services/service-cellular/tests/unittest_ussdHandler.cpp
M products/PurePhone/services/appmgr/ApplicationManager.cpp
M pure_changelog.md
M image/system_a/data/lang/Deutsch.json => image/system_a/data/lang/Deutsch.json +2 -0
@@ 253,6 253,8 @@
    "app_desktop_info_mmi_registration_success": "Registrierung erfolgreich",
    "app_desktop_info_mmi_result_failed": "Fehlgeschlagen",
    "app_desktop_info_mmi_result_success": "Erfolgreich",
    "app_desktop_info_mmi_result_timeout": "Bei der Verarbeitung des USSD-Codes wurde das Zeitlimit überschritten. Falscher Code oder Netzwerkfehler.",
    "app_desktop_info_mmi_result_aborted": "Vorgang abgebrochen.",
    "app_desktop_menu": "MEN\u00dc",
    "app_desktop_menu_alarm": "ALARM",
    "app_desktop_menu_calendar": "KALENDER",

M image/system_a/data/lang/English.json => image/system_a/data/lang/English.json +4 -2
@@ 254,8 254,10 @@
    "app_desktop_info_mmi_none_specified_success": "Operation successful",
    "app_desktop_info_mmi_registration_failed": "Registration failed",
    "app_desktop_info_mmi_registration_success": "Registration was successful",
    "app_desktop_info_mmi_result_failed": "Failed",
    "app_desktop_info_mmi_result_success": "Success",
    "app_desktop_info_mmi_result_failed": "Operation failed.",
    "app_desktop_info_mmi_result_success": "Operation successful.",
    "app_desktop_info_mmi_result_timeout": "USSD code processing timed out. Incorrect code or network error.",
    "app_desktop_info_mmi_result_aborted": "Operation aborted.",
    "app_desktop_menu": "MENU",
    "app_desktop_menu_alarm": "ALARM",
    "app_desktop_menu_calendar": "CALENDAR",

M image/system_a/data/lang/Espanol.json => image/system_a/data/lang/Espanol.json +2 -0
@@ 252,6 252,8 @@
    "app_desktop_info_mmi_registration_success": "Registro correcto",
    "app_desktop_info_mmi_result_failed": "Error",
    "app_desktop_info_mmi_result_success": "Correcto",
    "app_desktop_info_mmi_result_timeout": "Se ha agotado el tiempo de procesamiento del código USSD. Código incorrecto o error de red.",
    "app_desktop_info_mmi_result_aborted": "Se ha abortado la operación.",
    "app_desktop_menu": "MEN\u00da",
    "app_desktop_menu_alarm": "ALARMA",
    "app_desktop_menu_calendar": "CALENDARIO",

M image/system_a/data/lang/Francais.json => image/system_a/data/lang/Francais.json +2 -0
@@ 220,6 220,8 @@
    "app_desktop_info_mmi_registration_success": "L'enregistrement fut un succ\u00e8s",
    "app_desktop_info_mmi_result_failed": "\u00c9chou\u00e9",
    "app_desktop_info_mmi_result_success": "Succ\u00e8s",
    "app_desktop_info_mmi_result_timeout": "Le traitement du code USSD a été interrompu. Code incorrect ou erreur réseau.",
    "app_desktop_info_mmi_result_aborted": "Opération annulée.",
    "app_desktop_menu": "MENU",
    "app_desktop_menu_alarm": "ALARME",
    "app_desktop_menu_calendar": "CALENDRIER",

M image/system_a/data/lang/Polski.json => image/system_a/data/lang/Polski.json +4 -2
@@ 243,8 243,10 @@
    "app_desktop_info_mmi_none_specified_success": "Operacja udana",
    "app_desktop_info_mmi_registration_failed": "Rejestracja nieudana",
    "app_desktop_info_mmi_registration_success": "Rejestracja si\u0119 powiod\u0142a",
    "app_desktop_info_mmi_result_failed": "Nie uda\u0142o si\u0119",
    "app_desktop_info_mmi_result_success": "Uda\u0142o si\u0119",
    "app_desktop_info_mmi_result_failed": "Operacja nieudana.",
    "app_desktop_info_mmi_result_success": "Operacja udana.",
    "app_desktop_info_mmi_result_timeout": "Przekroczono limit czasu\nprzetwarzania kodu USSD.\nNieprawidłowy kod lub błąd sieci.",
    "app_desktop_info_mmi_result_aborted": "Operacja anulowana.",
    "app_desktop_menu": "MENU",
    "app_desktop_menu_alarm": "BUDZIK",
    "app_desktop_menu_calendar": "KALENDARZ",

M image/system_a/data/lang/Svenska.json => image/system_a/data/lang/Svenska.json +2 -0
@@ 120,6 120,8 @@
    "app_desktop_info_mmi_registration_success": "Registrering lyckades",
    "app_desktop_info_mmi_result_failed": "Misslyckades",
    "app_desktop_info_mmi_result_success": "Lyckades",
    "app_desktop_info_mmi_result_timeout": "Bearbetningen av USSD-koden stoppades. Felaktig kod eller nätverksfel.",
    "app_desktop_info_mmi_result_aborted": "Avbruten operation.",
    "app_desktop_menu": "MENY",
    "app_desktop_menu_alarm": "V\u00c4CKARKLOCKA",
    "app_desktop_menu_calendar": "KALENDER",

M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +7 -3
@@ 172,8 172,8 @@ namespace gui
        // process only if key is released
        // InputEvent::State::keyReleasedLong is necessary for KeyCode::KEY_RF to properly abort the active call
        if (inputEvent.isKeyRelease()) {
            LOG_INFO("key released");
            const auto code = translator.handle(inputEvent.getRawKey(), InputMode({InputMode::phone}).get());

            switch (keyCode) {
            case KeyCode::KEY_LF:
                handled = presenter.handleLeftButton();


@@ 187,6 187,7 @@ namespace gui
            default:
                break;
            }

            if (!handled && code != 0) {
                handled = presenter.handleDigitButton(code);
            }


@@ 196,9 197,12 @@ namespace gui
            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
            return true;
        }
        else {
            return keyCode == KeyCode::KEY_RF ? true : AppWindow::onInput(inputEvent);

        if (keyCode == KeyCode::KEY_RF) {
            return true;
        }

        return AppWindow::onInput(inputEvent);
    }

    void CallWindow::connectTimerOnExit()

M module-apps/application-call/windows/EnterNumberWindow.cpp => module-apps/application-call/windows/EnterNumberWindow.cpp +1 -6
@@ 1,18 1,13 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CallAppStyle.hpp"
#include "CallSwitchData.hpp"
#include "EnterNumberWindow.hpp"

#include <ContactRecord.hpp>
#include <country.hpp>
#include <i18n/i18n.hpp>
#include <text/modes/InputMode.hpp>
#include <phonenumbers/asyoutypeformatter.h>
#include <phonenumbers/phonenumberutil.h>
#include <service-appmgr/Controller.hpp>
#include <service-cellular/CellularServiceAPI.hpp>

#include <cassert>


M module-apps/application-call/windows/NumberWindow.cpp => module-apps/application-call/windows/NumberWindow.cpp +7 -3
@@ 28,7 28,6 @@ namespace gui
        assert(interface != nullptr);
        assert(app != nullptr);
        switchFormatter(utils::country::getAlpha2Code(currentCountry));
        preventsLongPressLock = true;
    }

    void NumberWindow::setNumberLabel(const std::string &num)


@@ 122,14 121,19 @@ namespace gui
                    return true;
                }
                clearInput();

                return true;
            }

            // long press of '0' key is translated to '+'
            else if (inputEvent.is(KeyCode::KEY_0)) {
            if (inputEvent.is(KeyCode::KEY_0)) {
                addDigit('+');
                return true;
            }

            // prevent locking the phone by long pound press
            if (inputEvent.is(KeyCode::KEY_PND)) {
                return true;
            }
        }

        // check if any of the lower inheritance onInput methods catch the event

M module-apps/application-desktop/include/application-desktop/Names.hpp => module-apps/application-desktop/include/application-desktop/Names.hpp +1 -6
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 9,14 9,9 @@ namespace app::window::name
{
    inline constexpr auto desktop_main_window        = gui::name::window::main_window;
    inline constexpr auto desktop_menu               = "MenuWindow";
    inline constexpr auto desktop_reboot             = "Reboot";
    inline constexpr auto dead_battery               = "DeadBatteryWindow";
    inline constexpr auto charging_battery           = "CharginBatteryWindow";
    inline constexpr auto closing_window             = "ClosingWindow";
    inline constexpr auto desktop_pin_lock           = "PinLockWindow";
    inline constexpr auto desktop_update             = "Update";
    inline constexpr auto desktop_update_progress    = "UpdateProgress";
    inline constexpr auto desktop_post_update_window = "PostUpdateWindow";
    inline constexpr auto desktop_mmi_pull           = "MmiPullWindow";
    inline constexpr auto desktop_mmi_push           = "MmiPushWindow";
    inline constexpr auto desktop_mmi_internal       = "MmiInternalMsgWindow";

M module-apps/application-desktop/windows/MmiConfirmationWindow.cpp => module-apps/application-desktop/windows/MmiConfirmationWindow.cpp +28 -26
@@ 1,12 1,10 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "MmiConfirmationWindow.hpp"

#include <i18n/i18n.hpp>
#include <Image.hpp>
#include <apps-common/ApplicationCommon.hpp>
#include "Names.hpp"
#include <service-appmgr/data/MmiActionsParams.hpp>
#include <service-cellular/CellularServiceAPI.hpp>

using namespace gui;



@@ 14,24 12,24 @@ namespace style::desktop
{
    namespace image
    {
        constexpr uint32_t x = 176;
        constexpr uint32_t y = 135;
        constexpr std::uint32_t x = 176;
        constexpr std::uint32_t y = 135;
    } // namespace image

    namespace text
    {
        constexpr uint32_t x = 40;
        constexpr uint32_t y = 300;
        constexpr uint32_t w = 400;
        constexpr uint32_t h = 300;
        constexpr std::uint32_t x = 40;
        constexpr std::uint32_t y = 300;
        constexpr std::uint32_t w = 400;
        constexpr std::uint32_t h = 300;
    } // namespace text

} // namespace style::desktop

MmiConfirmationWindow::MmiConfirmationWindow(app::ApplicationCommon *app, const std::string &name)
    : gui::WindowWithTimer(app, name)
    : AppWindow(app, name)
{
    AppWindow::buildInterface();
    navBar->setText(nav_bar::Side::Center, utils::translate(style::strings::common::ok));
    navBar->setText(nav_bar::Side::Right, utils::translate(style::strings::common::abort));
    icon = new Icon(this,
                    style::window::default_left_margin,
                    style::window::default_vertical_pos,


@@ 41,23 39,27 @@ MmiConfirmationWindow::MmiConfirmationWindow(app::ApplicationCommon *app, const 
                    utils::translate("app_desktop_info_mmi_confirmation"));
    icon->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
    icon->image->setMargins(Margins(0, icon::image_top_margin, 0, icon::image_bottom_margin));

    preventsAutoLock = true;
}

bool MmiConfirmationWindow::onInput(const InputEvent &inputEvent)
{
    if (inputEvent.isShortRelease()) {
        switch (inputEvent.getKeyCode()) {
        case KeyCode::KEY_ENTER: {
            application->returnToPreviousWindow();
            return true;
        }
        case KeyCode::KEY_RF: {
            return true;
        }
        default:
            break;
        }
    if (inputEvent.isShortRelease() && inputEvent.getKeyCode() == KeyCode::KEY_RF) {
        CellularServiceAPI::USSDRequest(application, cellular::USSDMessage::RequestType::abortSession, "");

        auto data =
            std::make_unique<mmiactions::MMIResultParams>(mmiactions::MMIResultParams::MMIResult::AbortedByUser);
        application->switchWindow(app::window::name::desktop_mmi_internal, std::move(data));

        return true;
    }

    /* Prevent locking the phone by long pound press */
    if (inputEvent.isLongRelease() && inputEvent.getKeyCode() == KeyCode::KEY_PND) {
        return true;
    }

    return AppWindow::onInput(inputEvent);
}


M module-apps/application-desktop/windows/MmiConfirmationWindow.hpp => module-apps/application-desktop/windows/MmiConfirmationWindow.hpp +2 -8
@@ 1,19 1,14 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <AppWindow.hpp>
#include <module-apps/apps-common/popups/WindowWithTimer.hpp>
#include <DialogMetadata.hpp>
#include <Text.hpp>
#include <Icon.hpp>

#include <functional>

namespace gui
{
    class MmiConfirmationWindow : public WindowWithTimer
    class MmiConfirmationWindow : public AppWindow
    {
      protected:
        Icon *icon = nullptr;


@@ 24,5 19,4 @@ namespace gui
        bool onInput(const InputEvent &inputEvent) override;
        void destroyInterface() override;
    };

}; // namespace gui

M module-apps/application-desktop/windows/MmiInternalMsgWindow.cpp => module-apps/application-desktop/windows/MmiInternalMsgWindow.cpp +12 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Mmi.hpp"


@@ 14,9 14,9 @@ MmiInternalMsgWindow::MmiInternalMsgWindow(app::ApplicationCommon *app, const st
    : MmiPushWindow(app, name)
{}

void MmiInternalMsgWindow::onBeforeShow(ShowMode mode, SwitchData *data)
void MmiInternalMsgWindow::onBeforeShow([[maybe_unused]] ShowMode mode, SwitchData *data)
{
    if (auto metadata = dynamic_cast<mmiactions::MMIResultParams *>(data); metadata != nullptr) {
    if (const auto metadata = dynamic_cast<mmiactions::MMIResultParams *>(data); metadata != nullptr) {
        if (metadata->getCustomData() != nullptr) {
            mmi::MMIMessageVisitor customMMIvisitor;
            std::string displayMessage;


@@ 34,14 34,19 @@ void MmiInternalMsgWindow::handleInternalMessages(mmiactions::MMIResultParams *m
{
    icon->text->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));

    std::string displayMessage;
    auto result = metadata->getData();
    const auto result = metadata->getData();
    switch (result) {
    case mmiactions::MMIResultParams::MMIResult::Success:
        icon->text->setText(displayMessage + utils::translate("app_desktop_info_mmi_result_success"));
        icon->text->setText(utils::translate("app_desktop_info_mmi_result_success"));
        break;
    case mmiactions::MMIResultParams::MMIResult::Failed:
        icon->text->setText(displayMessage + utils::translate("app_desktop_info_mmi_result_failed"));
        icon->text->setText(utils::translate("app_desktop_info_mmi_result_failed"));
        break;
    case mmiactions::MMIResultParams::MMIResult::Timeout:
        icon->text->setText(utils::translate("app_desktop_info_mmi_result_timeout"));
        break;
    case mmiactions::MMIResultParams::MMIResult::AbortedByUser:
        icon->text->setText(utils::translate("app_desktop_info_mmi_result_aborted"));
        break;
    default:
        icon->text->clear();

M module-apps/application-desktop/windows/MmiPullWindow.cpp => module-apps/application-desktop/windows/MmiPullWindow.cpp +8 -8
@@ 19,18 19,18 @@ namespace style::desktop
{
    namespace text
    {
        constexpr uint32_t x = 30;
        constexpr uint32_t y = 120;
        constexpr uint32_t w = 440;
        constexpr uint32_t h = 320;
        constexpr std::uint32_t x = 30;
        constexpr std::uint32_t y = 120;
        constexpr std::uint32_t w = 440;
        constexpr std::uint32_t h = 320;
    } // namespace text

    namespace inputWidget
    {
        constexpr uint32_t x = 30;
        constexpr uint32_t y = 450;
        constexpr uint32_t w = 450;
        constexpr uint32_t h = 50;
        constexpr std::uint32_t x = 30;
        constexpr std::uint32_t y = 450;
        constexpr std::uint32_t w = 450;
        constexpr std::uint32_t h = 50;
    } // namespace inputWidget

} // namespace style::desktop

M module-apps/application-desktop/windows/MmiPullWindow.hpp => module-apps/application-desktop/windows/MmiPullWindow.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 28,5 28,4 @@ namespace gui
        bool onInput(const InputEvent &inputEvent) override;
        void destroyInterface() override;
    };

}; // namespace gui

M module-apps/application-desktop/windows/MmiPushWindow.cpp => module-apps/application-desktop/windows/MmiPushWindow.cpp +19 -12
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Mmi.hpp"


@@ 17,17 17,17 @@ namespace style::desktop
{
    namespace image
    {
        constexpr uint32_t x = 176;
        constexpr uint32_t y = 135;
        constexpr std::uint32_t x = 176;
        constexpr std::uint32_t y = 135;
    } // namespace image

    namespace text
    {
        constexpr uint32_t x = 40;
        constexpr uint32_t y = 300;
        constexpr uint32_t w = 400;
        constexpr uint32_t h = 300;
        constexpr std::uint32_t x = 40;
        constexpr std::uint32_t y = 300;
        constexpr std::uint32_t w = 400;
        constexpr std::uint32_t h = 300;
    } // namespace text

} // namespace style::desktop

MmiPushWindow::MmiPushWindow(app::ApplicationCommon *app, const std::string &name) : gui::AppWindow(app, name)


@@ 46,9 46,9 @@ MmiPushWindow::MmiPushWindow(app::ApplicationCommon *app, const std::string &nam
    setTitle(utils::translate("app_desktop_info"));
}

void MmiPushWindow::onBeforeShow(ShowMode mode, SwitchData *data)
void MmiPushWindow::onBeforeShow([[maybe_unused]] ShowMode mode, SwitchData *data)
{
    if (auto metadata = dynamic_cast<app::manager::actions::MMIParams *>(data); metadata != nullptr) {
    if (const auto metadata = dynamic_cast<app::manager::actions::MMIParams *>(data); metadata != nullptr) {
        icon->text->setText(mmi::removePhrase(metadata->getData(), "\r"));
    }
}


@@ 61,13 61,20 @@ bool MmiPushWindow::onInput(const InputEvent &inputEvent)
            application->switchWindow(app::window::name::desktop_main_window);
            return true;
        }
        case KeyCode::KEY_RF: {

        case KeyCode::KEY_RF:
            return true;
        }

        default:
            break;
        }
    }

    /* Prevent leaving the window by long RF press */
    if (inputEvent.isLongRelease() && inputEvent.getKeyCode() == KeyCode::KEY_RF) {
        return true;
    }

    return AppWindow::onInput(inputEvent);
}


M module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp => module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp +1 -0
@@ 71,6 71,7 @@ namespace app
                                  SwitchReason::Popup);
                return true;
            });

        popupBlueprint.registerBlueprint(
            ID::BluetoothInfo, [&](gui::popup::ID id, std::unique_ptr<gui::PopupRequestParams> &params) {
                switchWindowPopup(resolveWindowName(id),

M module-apps/apps-common/popups/Popups.hpp => module-apps/apps-common/popups/Popups.hpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

M module-apps/apps-common/windows/AppWindow.cpp => module-apps/apps-common/windows/AppWindow.cpp +2 -4
@@ 183,10 183,8 @@ namespace gui
        }

        if (inputEvent.isLongRelease(gui::KeyCode::KEY_PND)) {
            if (not preventsLongPressLock) {
                LOG_INFO("Locking phone");
                application->getPhoneLockSubject().lock();
            }
            LOG_INFO("Locking phone");
            application->getPhoneLockSubject().lock();
        }

        if (inputEvent.isShortRelease()) {

M module-apps/apps-common/windows/AppWindow.hpp => module-apps/apps-common/windows/AppWindow.hpp +1 -2
@@ 51,8 51,7 @@ namespace gui
        /**
         * A flag that is set if current window state requires the phone to stay unlocked
         */
        bool preventsAutoLock      = false;
        bool preventsLongPressLock = false;
        bool preventsAutoLock = false;

        const std::chrono::milliseconds inputModeRestoreTimeout = std::chrono::seconds{3};
        sys::TimerHandle inputModeRestoreTimer;

M module-cellular/at/src/UrcCusd.cpp => module-cellular/at/src/UrcCusd.cpp +6 -6
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "UrcCusd.hpp"


@@ 58,7 58,7 @@ auto Cusd::getMessage() const noexcept -> std::optional<std::string>
    }

    if (auto const &messageToken = tokens[Tokens::Response]; !messageToken.empty()) {
        return std::make_optional(std::move(messageToken));
        return std::make_optional(messageToken);
    }

    return std::nullopt;


@@ 80,7 80,7 @@ auto Cusd::getDCS() const noexcept -> std::optional<int>

auto Cusd::split(const std::string &str) -> void
{
    size_t constexpr maxNumberOfDcsTokens = 3;
    auto constexpr maxNumberOfDcsTokens = 3;
    tokens.resize(maxNumberOfDcsTokens);

    using namespace re2;


@@ 89,7 89,7 @@ auto Cusd::split(const std::string &str) -> void
    auto constexpr numberOfStatusTypes = magic_enum::enum_count<StatusType>();
    static_assert(numberOfStatusTypes <= 9,
                  "StatusType: too many enum entries to handle - please revise regex/algorithm");
    std::string regexForStatus(" ([0-" + std::to_string(numberOfStatusTypes) + "])");
    std::string const regexForStatus(" ([0-" + std::to_string(numberOfStatusTypes) + "])");

    if (!RE2::Consume(&input, regexForStatus, &tokens[Tokens::Status])) {
        throw std::runtime_error("unrecognized CUSD status field or corrupted CUSD format");


@@ 101,9 101,9 @@ auto Cusd::split(const std::string &str) -> void
        return;
    }

    size_t startQuotationMarkPosition = input.find('"');
    auto const startQuotationMarkPosition = input.find('"');
    // must give the size to rfind() because called in the default way is broken
    size_t endQuotationMarkPosition = input.rfind('"', input.size());
    auto const endQuotationMarkPosition = input.rfind('"', input.size());
    if (startQuotationMarkPosition == StringPiece::npos || endQuotationMarkPosition == StringPiece::npos) {
        throw std::runtime_error("cannot locate message - corrupted CUSD format");
    }

M module-cellular/at/src/UrcFactory.cpp => module-cellular/at/src/UrcFactory.cpp +5 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <UrcFactory.hpp>


@@ 23,10 23,10 @@ std::unique_ptr<Urc> UrcFactory::Create(const std::string &urcMessage)
    if (urcMessage.empty()) {
        return std::make_unique<Urc>(std::string());
    }
    const char headDelimiter = ':';
    auto it                  = std::find(urcMessage.begin(), urcMessage.end(), headDelimiter);
    std::string head         = utils::trim(std::string(urcMessage.begin(), it));
    std::string body         = std::string(it == urcMessage.end() ? urcMessage.begin() : it + 1, urcMessage.end());
    const auto headDelimiter = ':';
    const auto it            = std::find(urcMessage.begin(), urcMessage.end(), headDelimiter);
    const auto &head         = utils::trim(std::string(urcMessage.begin(), it));
    const auto &body         = std::string(it == urcMessage.end() ? urcMessage.begin() : it + 1, urcMessage.end());

    if (Ctze::isURC(head)) {
        return std::make_unique<Ctze>(body);

M module-services/service-appmgr/include/service-appmgr/data/MmiActionsParams.hpp => module-services/service-appmgr/include/service-appmgr/data/MmiActionsParams.hpp +4 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 189,7 189,9 @@ namespace app::manager::actions
        enum class MMIResult
        {
            Success,
            Failed
            Failed,
            Timeout,
            AbortedByUser
        };

        explicit MMIResultParams(MMIResult result, std::shared_ptr<MMICustomResultParams> customResult = nullptr);

M module-services/service-cellular/CellularRequestHandler.cpp => module-services/service-cellular/CellularRequestHandler.cpp +2 -2
@@ 87,7 87,7 @@ void CellularRequestHandler::handle(cellular::RejectRequest &request, at::Result
        cellular.bus.sendUnicast(message, service::name::appmgr);
    }
    else if (request.getRejectReason() == cellular::RejectRequest::RejectReason::NoNetworkConnection) {
        auto message = std::make_shared<cellular::NoNetworkConenctionNotification>();
        auto message = std::make_shared<cellular::NoNetworkConnectionNotification>();
        cellular.bus.sendUnicast(message, service::name::appmgr);
    }
    request.setHandled(true);


@@ 121,7 121,7 @@ void CellularRequestHandler::handle(cellular::ClirRequest &request, at::Result &
    using namespace at::response;
    auto requestHandled = request.checkModemResponse(result);

    std::shared_ptr<MMICustomResultParams> response = std::make_shared<MMIClirResult>();
    const auto response = std::make_shared<MMIClirResult>();
    if (requestHandled) {
        auto procedureType = request.getProcedureType();
        if (procedureType == SupplementaryServicesRequest::ProcedureType::Activation) {

M module-services/service-cellular/CellularServiceAPI.cpp => module-services/service-cellular/CellularServiceAPI.cpp +3 -2
@@ 259,11 259,12 @@ bool CellularServiceAPI::TransmitDtmfTones(sys::Service *serv, DTMFCode code)
    return serv->bus.sendUnicast(msg, service::name::cellular);
}

bool CellularServiceAPI::USSDRequest(sys::Service *serv, cellular::USSDMessage::RequestType type, std::string data)
bool CellularServiceAPI::USSDRequest(sys::Service *serv,
                                     cellular::USSDMessage::RequestType type,
                                     const std::string &data)
{
    auto msg = std::make_shared<cellular::USSDMessage>(type, data);
    return serv->bus.sendUnicast(msg, service::name::cellular);
    ;
}

bool CellularServiceAPI::GetAPN(sys::Service *serv)

M module-services/service-cellular/CellularUrcHandler.cpp => module-services/service-cellular/CellularUrcHandler.cpp +17 -14
@@ 50,7 50,7 @@ void CellularUrcHandler::Handle(Creg &urc)
            cellularService.bus.sendMulticast(std::move(notification), sys::BusChannel::ServiceCellularNotifications);
        }

        Store::Network network{status, accessTechnology};
        const Store::Network network{status, accessTechnology};
        if (Store::GSM::get()->getNetwork() != network) {
            Store::GSM::get()->setNetwork(network);
            response = std::make_unique<cellular::NetworkStatusUpdateNotification>();


@@ 77,9 77,14 @@ void CellularUrcHandler::Handle(Cmti &urc)
void CellularUrcHandler::Handle(Cusd &urc)
{
    response     = std::nullopt;
    auto message = urc.getMessage();
    const auto message = urc.getMessage();
    if (!message) {
        LOG_WARN("CUSD with empty message - will be treated as not handled");
        LOG_WARN("CUSD with empty message!");

        CellularServiceAPI::USSDRequest(&cellularService, cellular::USSDMessage::RequestType::abortSession);
        auto msg = std::make_shared<cellular::MMIResultMessage>(mmiactions::MMIResultParams::MMIResult::Failed);
        cellularService.bus.sendUnicast(std::move(msg), service::name::appmgr);

        return;
    }



@@ 92,17 97,15 @@ void CellularUrcHandler::Handle(Cusd &urc)

    urc.setHandled(true);

    if (urc.isActionNeeded()) {
        if (cellularService.handleUSSDURC()) {
            auto msg = std::make_shared<cellular::MMIResponseMessage>(*message);
            cellularService.bus.sendUnicast(msg, service::name::appmgr);
            return;
        }
    if (urc.isActionNeeded() && cellularService.handleUSSDURC()) {
        auto msg = std::make_shared<cellular::MMIResponseMessage>(*message);
        cellularService.bus.sendUnicast(std::move(msg), service::name::appmgr);
        return;
    }

    CellularServiceAPI::USSDRequest(&cellularService, cellular::USSDMessage::RequestType::abortSession);
    auto msg = std::make_shared<cellular::MMIPushMessage>(*message);
    cellularService.bus.sendUnicast(msg, service::name::appmgr);
    cellularService.bus.sendUnicast(std::move(msg), service::name::appmgr);
}

void CellularUrcHandler::Handle(Ctze &urc)


@@ 113,7 116,7 @@ void CellularUrcHandler::Handle(Ctze &urc)

    auto msg = std::make_shared<cellular::TimeNotificationMessage>(
        urc.getGMTTime(), urc.getTimeZoneOffset(), urc.getTimeZoneString());
    cellularService.bus.sendUnicast(msg, service::name::service_time);
    cellularService.bus.sendUnicast(std::move(msg), service::name::service_time);

    urc.setHandled(true);
}


@@ 128,7 131,7 @@ void CellularUrcHandler::Handle(Qind &urc)
            AntennaServiceAPI::InvalidCSQNotification(&cellularService);
        }
        else {
            SignalStrength signalStrength(*rssi);
            const SignalStrength signalStrength(*rssi);

            Store::GSM::get()->setSignalStrength(signalStrength.data);
            response = std::make_unique<cellular::SignalStrengthUpdateNotification>(urc.getUrcBody());


@@ 150,7 153,7 @@ void CellularUrcHandler::Handle(Qind &urc)
        urc.setHandled(true);
    }
    else if (urc.isFota()) {
        std::string httpSuccess = "0";
        const auto httpSuccess = "0";
        if (urc.getFotaStage() == Qind::FotaStage::HTTPEND && urc.getFotaParameter() == httpSuccess) {
            LOG_DEBUG("Fota UPDATE, switching to AT mode");
            cellularService.cmux->setMode(CellularMux::Mode::AT);


@@ 205,7 208,7 @@ void CellularUrcHandler::Handle(PoweredDown &urc)

void CellularUrcHandler::Handle(UrcResponse &urc)
{
    std::vector<UrcResponse::URCResponseType> typesToHandle = {
    const std::vector<UrcResponse::URCResponseType> typesToHandle = {
        UrcResponse::URCResponseType::NoCarrier,
        UrcResponse::URCResponseType::Busy,
        UrcResponse::URCResponseType::NoAnswer,

M module-services/service-cellular/RequestFactory.cpp => module-services/service-cellular/RequestFactory.cpp +23 -18
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-cellular/RequestFactory.hpp"


@@ 28,17 28,19 @@ namespace cellular
                                   bool simInserted)
        : request(data), channel(channel), callMode(callMode), simInserted(simInserted)
    {
        registerRequest(ImeiRegex, ImeiRequest::create);
        registerRequest(ImeiRegex, ImeiRequest::create, SimRequirement::NotRequired);
        registerRequest(PasswordRegistrationRegex, PasswordRegistrationRequest::create);
        registerRequest(PinChangeRegex, PinChangeRequest::create);
        registerRequest(SupplementaryServicesRegex, SupplementaryServicesRequest::create);
        /*It have to be last check due to 3GPP TS 22.030*/
        /* It has to be last check due to 3GPP TS 22.030 */
        registerRequest(UssdRegex, UssdRequest::create);
    }

    void RequestFactory::registerRequest(std::string regex, CreateCallback callback)
    void RequestFactory::registerRequest(const std::string &regex,
                                         const CreateCallback &callback,
                                         SimRequirement simRequirement)
    {
        requestMap.emplace_back(std::make_pair(regex, callback));
        requestMap.emplace_back(std::make_tuple(regex, callback, simRequirement));
    }

    std::unique_ptr<IRequest> RequestFactory::emergencyCheck()


@@ 58,9 60,7 @@ namespace cellular
            if (simInserted || isNoSimEmergency) {
                return std::make_unique<CallRequest>(request);
            }
            else {
                return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
            }
            return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
        }
        else if (callMode == cellular::api::CallMode::Emergency) {
            return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NotAnEmergencyNumber, request);


@@ 70,7 70,7 @@ namespace cellular

    bool RequestFactory::isConnectedToNetwork()
    {
        at::Cmd buildCmd = at::factory(at::AT::COPS) + "?";
        const at::Cmd buildCmd = at::factory(at::AT::COPS) + "?";
        auto resp        = channel.cmd(buildCmd);
        at::response::cops::CurrentOperatorInfo ret;
        if ((resp.code == at::Result::Code::OK) && (at::response::parseCOPS(resp, ret))) {


@@ 81,7 81,7 @@ namespace cellular

    std::unique_ptr<IRequest> RequestFactory::create()
    {
        if (auto req = emergencyCheck(); req) {
        if (auto req = emergencyCheck(); req != nullptr) {
            return req;
        }



@@ 91,14 91,14 @@ namespace cellular
        std::vector<std::string> results;

        for (const auto &element : requestMap) {
            auto const &requestCreateCallback = element.second;
            re2::StringPiece input(request);
            re2::RE2 reg(element.first);
            const auto [regex, requestCreateCallback, simRequirement] = element;
            const re2::StringPiece input(request);
            const re2::RE2 reg(regex);

            std::vector<RE2::Arg> reArguments;
            std::vector<RE2::Arg *> reArgumentPtrs;

            std::size_t numberOfGroups = reg.NumberOfCapturingGroups();
            const std::size_t numberOfGroups = reg.NumberOfCapturingGroups();

            if (numberOfGroups > matchPack.size()) {
                LOG_ERROR("Internal error, GroupMatch has to be redefined.");


@@ 116,14 116,18 @@ namespace cellular
                reArgumentPtrs[i] = &reArguments[i];
            }

            if (re2::RE2::FullMatchN(input, reg, reArgumentPtrs.data(), numberOfGroups)) {
            if (re2::RE2::FullMatchN(input, reg, reArgumentPtrs.data(), static_cast<int>(numberOfGroups))) {
                if ((simRequirement == SimRequirement::Required) && !simInserted) {
                    return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
                }

                try {
                    if (auto req = requestCreateCallback(request, matchPack)) {
                        return req;
                    }
                }
                catch (const std::runtime_error &except) {
                    LOG_ERROR("Failed to create MMI request. Error message:\n%s", except.what());
                    LOG_ERROR("Failed to create MMI request. Error message: %s", except.what());
                }
            }
        }


@@ 131,11 135,12 @@ namespace cellular
        if (!simInserted) {
            return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
        }
        auto isRegisteredToNetwork = isConnectedToNetwork();

        const auto isRegisteredToNetwork = isConnectedToNetwork();
        if (!isRegisteredToNetwork) {
            return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoNetworkConnection, request);
        }

        return std::make_unique<CallRequest>(request);
    }

} // namespace cellular

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +103 -96
@@ 113,7 113,7 @@ namespace constants
{
    using namespace std::chrono_literals;

    inline constexpr auto cellularStack = 8000;
    inline constexpr auto cellularStack = 1024 * 8;

    inline constexpr std::chrono::milliseconds sleepTimerInterval{500ms};
    inline constexpr std::chrono::milliseconds maxUrcHandleTime{5s};


@@ 135,7 135,7 @@ ServiceCellular::ServiceCellular()
    callStateTimer = sys::TimerFactory::createPeriodicTimer(
        this, "call_state", std::chrono::milliseconds{1000}, [this](sys::Timer &) { CallStateTimerHandler(); });
    callEndedRecentlyTimer = sys::TimerFactory::createSingleShotTimer(
        this, "callEndedRecentlyTimer", std::chrono::seconds{5}, [this](sys::Timer &timer) {
        this, "callEndedRecentlyTimer", std::chrono::seconds{5}, [this]([[maybe_unused]] sys::Timer &timer) {
            priv->outSMSHandler.sendMessageIfDelayed();
        });
    stateTimer = sys::TimerFactory::createPeriodicTimer(


@@ 149,8 149,9 @@ ServiceCellular::ServiceCellular()
            utility::conditionally_invoke(
                [this]() { return phoneModeObserver->isInMode(sys::phone_modes::PhoneMode::Offline); },
                [this]() {
                    if (connectionManager != nullptr)
                    if (connectionManager != nullptr) {
                        connectionManager->onTimerTick();
                    }
                });
        });
    simTimer = sys::TimerFactory::createSingleShotTimer(


@@ 163,17 164,17 @@ ServiceCellular::ServiceCellular()

    priv->ussdHandler->setTimerStartCallback([this]() { ussdTimer.start(); });
    priv->ussdHandler->setTimerStopCallback([this]() { ussdTimer.stop(); });
    priv->ussdHandler->setTimerGetStateCallback([this]() { return ussdTimer.isActive(); });

    notificationCallback = [this](std::string &data) {
        LOG_DEBUG("Notifications callback called with %u data bytes", static_cast<unsigned int>(data.size()));

        std::string logStr = utils::removeNewLines(data);
        const auto logStr = utils::removeNewLines(data);
        LOG_SENSITIVE(LOGDEBUG, "Data: %s", logStr.c_str());
        atURCStream.write(data);
        auto vUrc = atURCStream.getURCList();

        for (const auto &urc : vUrc) {
            std::string message;
            auto msg = identifyNotification(urc);

            if (msg != std::nullopt) {


@@ 570,7 571,7 @@ void ServiceCellular::registerMessageHandlers()
        return handleCellularSetConnectionFrequencyMessage(request);
    });

    connect(typeid(RetryPhoneModeChangeRequest), [&](sys::Message *request) -> sys::MessagePointer {
    connect(typeid(RetryPhoneModeChangeRequest), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
        connectionManager->onPhoneModeChange(phoneModeObserver->getCurrentPhoneMode());
        return sys::MessageNone{};
    });


@@ 788,7 789,7 @@ bool ServiceCellular::handle_power_up_procedure()
    return true;
}

bool ServiceCellular::handle_power_up_in_progress_procedure(void)
bool ServiceCellular::handle_power_up_in_progress_procedure()
{
    if (priv->modemResetHandler->isResetInProgress()) {
        constexpr auto msModemUartInitTime = 12000;


@@ 806,10 807,8 @@ bool ServiceCellular::handle_baud_detect()
        priv->state->set(State::ST::CellularConfProcedure);
        return true;
    }
    else {
        priv->state->set(State::ST::ModemFatalFailure);
        return false;
    }
    priv->state->set(State::ST::ModemFatalFailure);
    return false;
}

bool ServiceCellular::handle_power_down_started()


@@ 831,7 830,7 @@ bool ServiceCellular::handle_power_down_waiting()
        priv->state->set(State::ST::PowerDown);
        break;
    default:
        LOG_ERROR("Powering 'down an unknown device not handled");
        LOG_ERROR("Powering down an unknown device not handled");
        return false;
    }
    return true;


@@ 901,10 900,8 @@ bool ServiceCellular::handle_audio_conf_procedure()
            priv->state->set(State::ST::CellularPrivInit);
            return true;
        }
        else {
            priv->state->set(State::ST::Failed);
            return false;
        }
        priv->state->set(State::ST::Failed);
        return false;
    }
    else if (audioRet == CellularMux::ConfState::Failure) {
        /// restart


@@ 919,7 916,7 @@ bool ServiceCellular::handle_audio_conf_procedure()
bool ServiceCellular::handle_cellular_priv_init()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (!channel) {
    if (channel == nullptr) {
        LOG_ERROR("no cmux channel provided");
        priv->modemResetHandler->performHardReset();
        return true;


@@ 933,8 930,8 @@ bool ServiceCellular::handle_cellular_priv_init()
        return true;
    }

    auto flightMode =
        settings->getValue(settings::Cellular::offlineMode, settings::SettingsScope::Global) == "1" ? true : false;
    const auto flightMode =
        (settings->getValue(settings::Cellular::offlineMode, settings::SettingsScope::Global) == "1");
    connectionManager->setFlightMode(flightMode);
    auto interval = 0;
    if (utils::toNumeric(settings->getValue(settings::Offline::connectionFrequency, settings::SettingsScope::Global),


@@ 946,6 943,7 @@ bool ServiceCellular::handle_cellular_priv_init()
    priv->state->set(State::ST::APNConfProcedure);
    return true;
}

auto ServiceCellular::handle(db::query::SMSSearchByTypeResult *response) -> bool
{
    if (priv->state->get() != State::ST::Ready) {


@@ 975,9 973,9 @@ std::optional<std::shared_ptr<sys::Message>> ServiceCellular::identifyNotificati

    CellularUrcHandler urcHandler(*this);

    std::string str(data.begin(), data.end());
    const std::string str(data.begin(), data.end());

    std::string logStr = utils::removeNewLines(str);
    const std::string logStr = utils::removeNewLines(str);
    LOG_SENSITIVE(LOGDEBUG, "Notification:: %s", logStr.c_str());

    auto urc = at::urc::UrcFactory::Create(str);


@@ 1067,7 1065,7 @@ auto ServiceCellular::receiveSMS(std::string messageNumber) -> bool
    }

    for (std::size_t i = 0; i < receivedMessages; i++) {
        bool messageParsed = SMSParser::parse(&rawMessage.response[i]);
        const auto messageParsed = SMSParser::parse(&rawMessage.response[i]);
        if (messageParsed) {
            UTF8 decodedMessage;
            UTF8 smsNumber         = SMSParser::getNumber();


@@ 1084,7 1082,7 @@ auto ServiceCellular::receiveSMS(std::string messageNumber) -> bool
            }
            const auto mmsNotificationOpt = pdu::parse(decodedStr);
            if (mmsNotificationOpt) {
                std::string number = numberFromAddress(mmsNotificationOpt->fromAddress);
                const auto number = numberFromAddress(mmsNotificationOpt->fromAddress);
                // NOTE: number may be empty
                decodedMessage = UTF8("[MMS]");
                smsNumber      = UTF8(number);


@@ 1111,7 1109,7 @@ auto ServiceCellular::receiveSMS(std::string messageNumber) -> bool
bool ServiceCellular::getOwnNumber(std::string &destination)
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (not channel) {
    if (channel == nullptr) {
        LOG_ERROR("ServiceCellular::getOwnNumber failed because no cmux channel provided");
        return false;
    }


@@ 1143,7 1141,7 @@ bool ServiceCellular::getOwnNumber(std::string &destination)
bool ServiceCellular::getIMSI(std::string &destination, bool fullNumber)
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (!channel) {
    if (channel == nullptr) {
        LOG_ERROR("no cmux channel provided");
        return false;
    }


@@ 1172,7 1170,7 @@ std::vector<std::string> ServiceCellular::getNetworkInfo()
{
    std::vector<std::string> data;
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {
    if (channel != nullptr) {
        auto resp = channel->cmd(at::AT::CSQ);
        if (resp.code == at::Result::Code::OK) {
            data.push_back(resp.response[0]);


@@ 1227,7 1225,7 @@ std::vector<std::string> get_last_AT_error(DLCChannel *channel)

void log_last_AT_error(DLCChannel *channel)
{
    std::vector<std::string> atErrors(get_last_AT_error(channel));
    const std::vector<std::string> atErrors(get_last_AT_error(channel));
    int i = 1;
    for (auto &msg_line : atErrors) {
        LOG_ERROR("%d/%d: %s", i, static_cast<int>(atErrors.size()), msg_line.c_str());


@@ 1240,12 1238,12 @@ bool is_SIM_detection_enabled(DLCChannel *channel)
    auto ret = channel->cmd(at::AT::SIM_DET);
    if (ret) {
        if (ret.response[0].find("+QSIMDET: 1") != std::string::npos) {
            LOG_DEBUG("SIM detecition enabled!");
            LOG_DEBUG("SIM detection enabled!");
            return true;
        }
    }
    else {
        LOG_FATAL("Cant check sim detection status!");
        LOG_FATAL("Can't check sim detection status!");
        log_last_AT_error(channel);
    }
    return false;


@@ 1297,26 1295,26 @@ void save_SIM_detection_status(DLCChannel *channel)

bool sim_check_hot_swap(DLCChannel *channel)
{
    bool reboot_needed = false;
    auto rebootNeeded = false;

    if (!channel) {
    if (channel == nullptr) {
        LOG_ERROR("no cmux channel provided");
        return reboot_needed;
        return rebootNeeded;
    }

    if (!is_SIM_detection_enabled(channel)) {
        reboot_needed = true;
        rebootNeeded = true;
    }
    if (!is_SIM_status_enabled(channel)) {
        reboot_needed = true;
        rebootNeeded = true;
    }
    if (reboot_needed) {
    if (rebootNeeded) {
        enable_SIM_detection(channel);
        enable_SIM_status(channel);
        save_SIM_detection_status(channel);
        LOG_FATAL("Modem reboot required, Please remove battery!");
    }
    return !reboot_needed;
    return !rebootNeeded;
}

bool ServiceCellular::handle_sim_sanity_check()


@@ 1335,7 1333,7 @@ bool ServiceCellular::handle_sim_sanity_check()
bool ServiceCellular::handle_modem_on()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (!channel) {
    if (channel == nullptr) {
        LOG_ERROR("no cmux channel provided");
        return false;
    }


@@ 1352,13 1350,12 @@ bool ServiceCellular::handle_modem_on()
bool ServiceCellular::handle_URCReady()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (!channel) {
    if (channel == nullptr) {
        LOG_ERROR("no cmux channel provided");
        return false;
    }

    bool ret     = true;

    bool ret = true;
    ret = ret && channel->cmd(at::AT::ENABLE_NETWORK_REGISTRATION_URC);

    bus.sendMulticast<cellular::msg::notification::ModemStateChanged>(cellular::api::ModemState::Ready);


@@ 1395,7 1392,7 @@ bool ServiceCellular::handleTextMessagesInit()
SMSRecord ServiceCellular::createSMSRecord(const UTF8 &decodedMessage,
                                           const UTF8 &receivedNumber,
                                           const time_t messageDate,
                                           const SMSType &smsType) const noexcept
                                           [[maybe_unused]] const SMSType &smsType) const noexcept
{
    SMSRecord record{};
    record.body   = decodedMessage;


@@ 1444,16 1441,14 @@ bool ServiceCellular::receiveAllMessages()
                auto endPos   = ret.response[i].find_first_of(',');
                if (receiveSMS(ret.response[i].substr(startPos, endPos - startPos))) {
                    LOG_WARN("Cannot receive text message - %" PRIu32 " / %" PRIu32,
                             static_cast<uint32_t>(i),
                             static_cast<uint32_t>(ret.response.size()));
                             static_cast<std::uint32_t>(i),
                             static_cast<std::uint32_t>(ret.response.size()));
                }
            }
        }
        return true;
    }
    else {
        return false;
    }
    return false;
}

bool ServiceCellular::handle_failure()


@@ 1479,10 1474,10 @@ bool ServiceCellular::handle_ready()
    return true;
}

bool ServiceCellular::SetScanMode(std::string mode)
bool ServiceCellular::SetScanMode(const std::string &mode)
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {
    if (channel != nullptr) {
        auto command = at::factory(at::AT::SET_SCANMODE);

        auto resp = channel->cmd(command.getCmd() + mode + ",1", command.getTimeout(), 1);


@@ 1493,14 1488,13 @@ bool ServiceCellular::SetScanMode(std::string mode)
    return false;
}

std::string ServiceCellular::GetScanMode(void)
std::string ServiceCellular::GetScanMode()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {

    if (channel != nullptr) {
        auto resp = channel->cmd(at::AT::GET_SCANMODE);
        if (resp.code == at::Result::Code::OK) {
            auto beg = resp.response[0].find(",");
            auto beg = resp.response[0].find(',');
            if (beg != std::string::npos) {
                auto response = resp.response[0].substr(beg + 1, 1);
                return response;


@@ 1517,7 1511,7 @@ bool ServiceCellular::transmitDtmfTone(DTMFCode code)
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    at::Result resp;
    if (channel) {
    if (channel != nullptr) {
        auto command = at::factory(at::AT::QLDTMF);
        resp         = channel->cmd(command.getCmd() + std::string(code));
        if (resp) {


@@ 1528,12 1522,12 @@ bool ServiceCellular::transmitDtmfTone(DTMFCode code)
    return resp.code == at::Result::Code::OK;
}

bool ServiceCellular::handle_status_check(void)
bool ServiceCellular::handle_status_check()
{
    LOG_INFO("Checking modem status.");
    auto modemActive = cmux->isModemActive();
    if (modemActive) {
        // modem is already turned on, call configutarion procedure
        // modem is already turned on, call configuration procedure
        LOG_INFO("Modem is already turned on.");
        LOG_DEBUG("RT1051 - hot start");
        priv->state->set(State::ST::PowerUpInProgress);


@@ 1544,7 1538,7 @@ bool ServiceCellular::handle_status_check(void)
    return true;
}

void ServiceCellular::startStateTimer(uint32_t timeout)
void ServiceCellular::startStateTimer(std::uint32_t timeout)
{
    stateTimeout = timeout;
    stateTimer.start();


@@ 1556,7 1550,7 @@ void ServiceCellular::stopStateTimer()
    stateTimer.stop();
}

void ServiceCellular::handleStateTimer(void)
void ServiceCellular::handleStateTimer()
{
    stateTimeout--;
    if (stateTimeout == 0) {


@@ 1631,10 1625,11 @@ bool ServiceCellular::handle_apn_conf_procedure()
    return true;
}

void ServiceCellular::handleCellularRequestCurrentOperatorName(cellular::RequestCurrentOperatorNameMessage *msg)
void ServiceCellular::handleCellularRequestCurrentOperatorName(
    [[maybe_unused]] cellular::RequestCurrentOperatorNameMessage *msg)
{
    LOG_INFO("CellularRequestCurrentOperatorName handled");
    NetworkSettings networkSettings(*this);
    const NetworkSettings networkSettings(*this);
    const auto currentNetworkOperatorName = networkSettings.getCurrentOperatorName();
    Store::GSM::get()->setNetworkOperatorName(currentNetworkOperatorName);
    auto notification = std::make_shared<cellular::CurrentOperatorNameNotification>(currentNetworkOperatorName);


@@ 1686,7 1681,7 @@ std::shared_ptr<cellular::SetDataTransferResponse> ServiceCellular::handleCellul
}

std::shared_ptr<cellular::GetDataTransferResponse> ServiceCellular::handleCellularGetDataTransferMessage(
    cellular::GetDataTransferMessage *msg)
    [[maybe_unused]] cellular::GetDataTransferMessage *msg)
{
    return std::make_shared<cellular::GetDataTransferResponse>(packetData->getDataTransfer());
}


@@ 1706,13 1701,13 @@ std::shared_ptr<cellular::DeactivateContextResponse> ServiceCellular::handleCell
}

std::shared_ptr<cellular::GetActiveContextsResponse> ServiceCellular::handleCellularGetActiveContextsMessage(
    cellular::GetActiveContextsMessage *msg)
    [[maybe_unused]] cellular::GetActiveContextsMessage *msg)
{
    return std::make_shared<cellular::GetActiveContextsResponse>(packetData->getActiveContexts());
}

std::shared_ptr<cellular::SetOperatorAutoSelectResponse> ServiceCellular::handleCellularSetOperatorAutoSelect(
    cellular::SetOperatorAutoSelectMessage *msg)
    [[maybe_unused]] cellular::SetOperatorAutoSelectMessage *msg)
{
    LOG_INFO("CellularSetOperatorAutoSelect handled");



@@ 1738,7 1733,7 @@ void ServiceCellular::apnListChanged(const std::string &value)
    }
}

auto ServiceCellular::handleCellularAnswerIncomingCallMessage(CellularMessage *msg)
auto ServiceCellular::handleCellularAnswerIncomingCallMessage([[maybe_unused]] CellularMessage *msg)
    -> std::shared_ptr<cellular::ResponseMessage>
{
    LOG_INFO("%s", __PRETTY_FUNCTION__);


@@ 1803,7 1798,7 @@ auto ServiceCellular::handleCellularCallRequestMessage(cellular::CallRequestMess
    LOG_INFO("isHandled %d, %s", static_cast<int>(request->isHandled()), utils::enumToString(result.code).c_str());

    if (!request->isHandled()) {
        cellular::CallRequestGeneralError::ErrorType errorType = translate(result.code);
        const auto errorType = translate(result.code);
        auto message = std::make_shared<cellular::CallRequestGeneralError>(errorType);
        bus.sendUnicast(message, ::service::name::appmgr);
    }


@@ 1811,7 1806,7 @@ auto ServiceCellular::handleCellularCallRequestMessage(cellular::CallRequestMess
    return std::make_shared<cellular::ResponseMessage>(request->isHandled());
}

void ServiceCellular::handleCellularHangupCallMessage(cellular::HangupCallMessage *msg)
void ServiceCellular::handleCellularHangupCallMessage([[maybe_unused]] cellular::HangupCallMessage *msg)
{
    LOG_INFO("%s", __PRETTY_FUNCTION__);
    if (!ongoingCall->handle(call::event::Reject{})) {


@@ 1836,16 1831,15 @@ auto ServiceCellular::handleDBQueryResponseMessage(db::QueryResponse *msg) -> st
    if (responseHandled) {
        return std::make_shared<sys::ResponseMessage>();
    }
    else {
        return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
    }
    return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
}

auto ServiceCellular::handleCellularListCallsMessage(CellularMessage *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularListCallsMessage([[maybe_unused]] CellularMessage *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    at::cmd::CLCC cmd;
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (!channel) {
    if (channel == nullptr) {
        LOG_ERROR("no cmux channel provided");
        return std::make_shared<cellular::ResponseMessage>(false);
    }


@@ 1885,7 1879,8 @@ auto ServiceCellular::handleCellularRingingMessage(cellular::RingingMessage *msg
        ongoingCall->handle(call::event::StartCall{CallType::CT_OUTGOING, msg->number}));
}

auto ServiceCellular::handleCellularGetIMSIMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularGetIMSIMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    std::string temp;
    if (getIMSI(temp)) {


@@ 1894,7 1889,8 @@ auto ServiceCellular::handleCellularGetIMSIMessage(sys::Message *msg) -> std::sh
    return std::make_shared<cellular::ResponseMessage>(false);
}

auto ServiceCellular::handleCellularGetOwnNumberMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularGetOwnNumberMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    std::string temp;
    if (getOwnNumber(temp)) {


@@ 1925,7 1921,7 @@ auto ServiceCellular::handleCellularSelectAntennaMessage(sys::Message *msg) -> s
    else {
        LOG_INFO("High band antenna set");
    }
    bool changedAntenna = (actualAntenna == message->antenna);
    const auto changedAntenna = (actualAntenna == message->antenna);

    auto notification = std::make_shared<AntennaChangedMessage>();
    bus.sendMulticast(notification, sys::BusChannel::AntennaNotifications);


@@ 1935,14 1931,14 @@ auto ServiceCellular::handleCellularSelectAntennaMessage(sys::Message *msg) -> s
auto ServiceCellular::handleCellularSetScanModeMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    auto message = static_cast<cellular::SetScanModeMessage *>(msg);
    bool ret     = SetScanMode(message->data);
    const auto ret = SetScanMode(message->data);

    return std::make_shared<cellular::ResponseMessage>(ret);
}
auto ServiceCellular::handleCellularGetScanModeMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    auto mode = GetScanMode();
    if (mode != "") {
    if (!mode.empty()) {
        auto response = std::make_shared<cellular::RawCommandRespAsync>(CellularMessage::Type::GetScanModeResult);
        response->data.push_back(mode);
        bus.sendUnicast(response, msg->sender);


@@ 1951,12 1947,12 @@ auto ServiceCellular::handleCellularGetScanModeMessage(sys::Message *msg) -> std
    return std::make_shared<cellular::ResponseMessage>(false);
}

auto ServiceCellular::handleCellularGetFirmwareVersionMessage(sys::Message *msg)
auto ServiceCellular::handleCellularGetFirmwareVersionMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    std::string response;
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {
    if (channel != nullptr) {
        auto resp = channel->cmd(at::AT::QGMR);
        if (resp.code == at::Result::Code::OK) {
            response = resp.response[0];


@@ 1987,10 1983,11 @@ auto ServiceCellular::handleEVMStatusMessage(sys::Message *msg) -> std::shared_p
    return std::make_shared<cellular::ResponseMessage>(true);
}

auto ServiceCellular::handleCellularGetCsqMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularGetCsqMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {
    if (channel != nullptr) {
        auto modemResponse = channel->cmd(at::AT::CSQ);
        if (modemResponse.code == at::Result::Code::OK) {
            return std::make_shared<cellular::ResponseMessage>(true, modemResponse.response[0]);


@@ 1999,10 1996,11 @@ auto ServiceCellular::handleCellularGetCsqMessage(sys::Message *msg) -> std::sha
    return std::make_shared<cellular::ResponseMessage>(false);
}

auto ServiceCellular::handleCellularGetCregMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularGetCregMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {
    if (channel != nullptr) {
        auto resp = channel->cmd(at::AT::CREG);
        if (resp.code == at::Result::Code::OK) {
            return std::make_shared<cellular::ResponseMessage>(true, resp.response[0]);


@@ 2011,10 2009,11 @@ auto ServiceCellular::handleCellularGetCregMessage(sys::Message *msg) -> std::sh
    return std::make_shared<cellular::ResponseMessage>(false);
}

auto ServiceCellular::handleCellularGetNwinfoMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularGetNwinfoMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel) {
    if (channel != nullptr) {
        auto resp = channel->cmd(at::AT::QNWINFO);
        if (resp.code == at::Result::Code::OK) {
            return std::make_shared<cellular::ResponseMessage>(true, resp.response[0]);


@@ 2023,7 2022,8 @@ auto ServiceCellular::handleCellularGetNwinfoMessage(sys::Message *msg) -> std::
    return std::make_shared<cellular::ResponseMessage>(false);
}

auto ServiceCellular::handleCellularGetAntennaMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularGetAntennaMessage([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    auto antenna = cmux->getAntenna();
    return std::make_shared<cellular::AntennaResponseMessage>(true, antenna, CellularMessage::Type::GetAntenna);


@@ 2047,10 2047,11 @@ auto ServiceCellular::handleStateRequestMessage(sys::Message *msg) -> std::share
    return std::make_shared<cellular::ResponseMessage>(true);
}

auto ServiceCellular::handleCallActiveNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCallActiveNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    auto ret = std::make_shared<cellular::ResponseMessage>(true);
    NetworkSettings networkSettings(*this);
    const NetworkSettings networkSettings(*this);
    auto currentNAT = networkSettings.getCurrentNAT();
    if (currentNAT) {
        auto currentSimpleNAT = NetworkSettings::toSimpleNAT(*currentNAT);


@@ 2070,7 2071,7 @@ auto ServiceCellular::handleCallActiveNotification(sys::Message *msg) -> std::sh
    return ret;
}

auto ServiceCellular::handlePowerUpProcedureCompleteNotification(sys::Message *msg)
auto ServiceCellular::handlePowerUpProcedureCompleteNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    if (board == bsp::Board::Linux) {


@@ 2078,7 2079,7 @@ auto ServiceCellular::handlePowerUpProcedureCompleteNotification(sys::Message *m
    }
    return std::make_shared<cellular::ResponseMessage>(true);
}
auto ServiceCellular::handlePowerDownDeregisteringNotification(sys::Message *msg)
auto ServiceCellular::handlePowerDownDeregisteringNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    if (priv->state->get() != State::ST::PowerDownWaiting) {


@@ 2087,7 2088,7 @@ auto ServiceCellular::handlePowerDownDeregisteringNotification(sys::Message *msg
    }
    return std::make_shared<cellular::ResponseMessage>(false);
}
auto ServiceCellular::handlePowerDownDeregisteredNotification(sys::Message *msg)
auto ServiceCellular::handlePowerDownDeregisteredNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    priv->state->set(State::ST::PowerDownWaiting);


@@ 2101,21 2102,25 @@ auto ServiceCellular::handleNewIncomingSMSNotification(sys::Message *msg) -> std
    return std::make_shared<cellular::ResponseMessage>(true);
}

auto ServiceCellular::handleSmsDoneNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleSmsDoneNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    auto resp = handleTextMessagesInit();
    return std::make_shared<cellular::ResponseMessage>(resp);
}
auto ServiceCellular::handleSignalStrengthUpdateNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleSignalStrengthUpdateNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    return std::make_shared<cellular::ResponseMessage>(false);
}
auto ServiceCellular::handleNetworkStatusUpdateNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleNetworkStatusUpdateNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    return std::make_shared<cellular::ResponseMessage>(false);
}

auto ServiceCellular::handleUrcIncomingNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleUrcIncomingNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    WakeUpHandler();
    // if there is no response from the host to incoming URC,


@@ 2127,14 2132,16 @@ auto ServiceCellular::handleUrcIncomingNotification(sys::Message *msg) -> std::s
auto ServiceCellular::handleCellularSetFlightModeMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    auto setMsg = static_cast<cellular::SetFlightModeMessage *>(msg);
    settings->setValue(
        settings::Cellular::offlineMode, std::to_string(setMsg->flightModeOn), settings::SettingsScope::Global);
    settings->setValue(settings::Cellular::offlineMode,
                       std::to_string(static_cast<int>(setMsg->flightModeOn)),
                       settings::SettingsScope::Global);
    connectionManager->setFlightMode(setMsg->flightModeOn);
    connectionManager->onPhoneModeChange(phoneModeObserver->getCurrentPhoneMode());
    return std::make_shared<cellular::ResponseMessage>(true);
}

auto ServiceCellular::handleCellularRingNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
auto ServiceCellular::handleCellularRingNotification([[maybe_unused]] sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    LOG_INFO("%s", __PRETTY_FUNCTION__);
    ongoingCall->handle(call::event::RING{});

M module-services/service-cellular/include/service-cellular/api/common.hpp => module-services/service-cellular/include/service-cellular/api/common.hpp +0 -1
@@ 9,7 9,6 @@

namespace cellular
{

    namespace api
    {
        enum class CallMode

M module-services/service-cellular/requests/PasswordRegistrationRequest.cpp => module-services/service-cellular/requests/PasswordRegistrationRequest.cpp +3 -8
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <string>


@@ 10,11 10,6 @@
#include "service-cellular/requests/PasswordRegistrationRequest.hpp"
#include "service-cellular/requests/CallBarringRequest.hpp" // for barringServiceToFacility map

namespace
{
    constexpr inline std::string_view changeNetworkPasswordServiceCode = "03";
}

namespace cellular
{



@@ 26,13 21,13 @@ namespace cellular

    auto PasswordRegistrationRequest::command() -> at::Cmd
    {
        std::vector<commandBuilderFunc> commandParts = {
        const std::vector<commandBuilderFunc> commandParts = {
            [this]() { return getCommandFacility(); },
            [this]() { return getOldPassword(); },
            [this]() { return getNewPassword(); },
        };

        return at::Cmd(buildCommand(at::AT::CPWD, commandParts));
        return buildCommand(at::AT::CPWD, commandParts);
    }

    auto PasswordRegistrationRequest::getCommandFacility() const noexcept -> std::string

M module-services/service-cellular/service-cellular/CellularMessage.hpp => module-services/service-cellular/service-cellular/CellularMessage.hpp +14 -14
@@ 280,7 280,7 @@ namespace cellular
    class RequestMessage : public CellularMessage
    {
      public:
        RequestMessage(Type type, std::string data = "") : CellularMessage(type), data(data)
        RequestMessage(Type type, std::string data = "") : CellularMessage(type), data(std::move(data))
        {}

        std::string data;


@@ 339,7 339,7 @@ namespace cellular
        ResponseMessage(bool retCode,
                        std::string retdata              = std::string(),
                        CellularMessage::Type responseTo = CellularMessage::Type::Uninitialized)
            : sys::ResponseMessage(sys::ReturnCodes::Success), retCode(retCode), data(retdata),
            : sys::ResponseMessage(sys::ReturnCodes::Success), retCode(retCode), data(std::move(retdata)),
              cellResponse(responseTo){};

        ResponseMessage(bool retCode, CellularMessage::Type responseTo)


@@ 403,7 403,7 @@ namespace cellular
        app::manager::actions::MMIParams params;

      public:
        explicit MMIDataMessage(std::string mmiData) : CellularMessage(Type::MMIData), params(mmiData)
        explicit MMIDataMessage(std::string mmiData) : CellularMessage(Type::MMIData), params(std::move(mmiData))
        {}
    };
    class MMIResponseMessage : public MMIDataMessage, public app::manager::actions::ConvertibleToAction


@@ 466,7 466,7 @@ namespace cellular
    class NoSimNotification : public ResponseMessage, public app::manager::actions::ConvertibleToAction
    {
      public:
        NoSimNotification(std::string data) : ResponseMessage(false, data)
        NoSimNotification(std::string data) : ResponseMessage(false, std::move(data))
        {}

        [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>


@@ 481,7 481,7 @@ namespace cellular
    class NotAnEmergencyNotification : public ResponseMessage, public app::manager::actions::ConvertibleToAction
    {
      public:
        NotAnEmergencyNotification(std::string data) : ResponseMessage(false, data)
        NotAnEmergencyNotification(std::string data) : ResponseMessage(false, std::move(data))
        {}

        [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>


@@ 493,10 493,10 @@ namespace cellular
        }
    };

    class NoNetworkConenctionNotification : public ResponseMessage, public app::manager::actions::ConvertibleToAction
    class NoNetworkConnectionNotification : public ResponseMessage, public app::manager::actions::ConvertibleToAction
    {
      public:
        NoNetworkConenctionNotification() : ResponseMessage(false)
        NoNetworkConnectionNotification() : ResponseMessage(false)
        {}

        [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>


@@ 845,7 845,7 @@ namespace cellular
    {
      public:
        explicit GetSimContactsResponse(std::shared_ptr<std::vector<SimContact>> contacts)
            : sys::ResponseMessage(sys::ReturnCodes::Success), contacts(contacts)
            : sys::ResponseMessage(sys::ReturnCodes::Success), contacts(std::move(contacts))
        {}
        GetSimContactsResponse() : sys::ResponseMessage(sys::ReturnCodes::Failure)
        {}


@@ 868,7 868,7 @@ namespace cellular
    {
      public:
        explicit GetImeiResponse(std::shared_ptr<std::string> imei)
            : sys::ResponseMessage(sys::ReturnCodes::Success), imei(imei)
            : sys::ResponseMessage(sys::ReturnCodes::Success), imei(std::move(imei))
        {}
        GetImeiResponse() : sys::ResponseMessage(sys::ReturnCodes::Failure)
        {}


@@ 905,7 905,7 @@ namespace cellular
    class URCCounterMessage : public sys::DataMessage
    {
      public:
        explicit URCCounterMessage(const uint32_t urcCounter)
        explicit URCCounterMessage(const std::uint32_t urcCounter)
            : sys::DataMessage(MessageType::MessageTypeUninitialized), urcCounter(urcCounter){};
        auto getCounter()
        {


@@ 913,7 913,7 @@ namespace cellular
        }

      private:
        uint32_t urcCounter;
        std::uint32_t urcCounter;
    };

    class RetrySwitchCSQMode : public sys::DataMessage


@@ 969,7 969,7 @@ namespace cellular
    {
      public:
        CallStartedNotification(utils::PhoneNumber phoneNumber, bool isIncoming)
            : sys::DataMessage(MessageType::MessageTypeUninitialized), phoneNumber(phoneNumber),
            : sys::DataMessage(MessageType::MessageTypeUninitialized), phoneNumber(std::move(phoneNumber)),
              isIncoming(isIncoming){};
        utils::PhoneNumber getNumber()
        {


@@ 1022,9 1022,9 @@ namespace cellular
    class CallDurationNotification : public sys::DataMessage
    {
      public:
        explicit CallDurationNotification(const time_t duration)
        explicit CallDurationNotification(const std::time_t duration)
            : sys::DataMessage(MessageType::MessageTypeUninitialized), callDuration(duration){};
        time_t callDuration;
        std::time_t callDuration;
    };
    class CallerIdMessage : public CellularMessage
    {

M module-services/service-cellular/service-cellular/CellularServiceAPI.hpp => module-services/service-cellular/service-cellular/CellularServiceAPI.hpp +1 -1
@@ 93,7 93,7 @@ namespace CellularServiceAPI
     */
    bool TransmitDtmfTones(sys::Service *serv, DTMFCode code);

    bool USSDRequest(sys::Service *serv, cellular::USSDMessage::RequestType type, std::string data = "");
    bool USSDRequest(sys::Service *serv, cellular::USSDMessage::RequestType type, const std::string &data = "");

    /**
     * @brief get all APNs from phone configuration

M module-services/service-cellular/service-cellular/RequestFactory.hpp => module-services/service-cellular/service-cellular/RequestFactory.hpp +11 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 18,6 18,12 @@ namespace cellular
{
    using CreateCallback = std::function<std::unique_ptr<IRequest>(const std::string &, GroupMatch)>;

    enum class SimRequirement
    {
        NotRequired,
        Required
    };

    class RequestFactory
    {
      public:


@@ 28,12 34,14 @@ namespace cellular
        std::unique_ptr<IRequest> create();

      private:
        void registerRequest(std::string regex, CreateCallback);
        void registerRequest(const std::string &regex,
                             const CreateCallback &callback,
                             SimRequirement simRequirement = SimRequirement::Required);
        std::unique_ptr<IRequest> emergencyCheck();
        bool isConnectedToNetwork();

        std::string request;
        std::vector<std::pair<std::string, CreateCallback>> requestMap;
        std::vector<std::tuple<std::string, CreateCallback, SimRequirement>> requestMap;

        at::BaseChannel &channel;
        const cellular::api::CallMode callMode;

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +3 -11
@@ 201,19 201,17 @@ class ServiceCellular : public sys::Service

    bool transmitDtmfTone(DTMFCode code);

    bool SetScanMode(std::string mode);
    bool SetScanMode(const std::string &mode);
    std::string GetScanMode();

    uint32_t stateTimeout = 0;
    void startStateTimer(uint32_t timeout);
    std::uint32_t stateTimeout = 0;
    void startStateTimer(std::uint32_t timeout);
    void stopStateTimer();
    void handleStateTimer();

    // db response handlers
    auto handle(db::query::SMSSearchByTypeResult *response) -> bool;

    bool handleIMEIRequest();

    std::shared_ptr<cellular::RawCommandRespAsync> handleCellularStartOperatorsScan(
        cellular::StartOperatorsScanMessage *msg);



@@ 250,14 248,12 @@ class ServiceCellular : public sys::Service
    auto handleCellularCallRequestMessage(cellular::CallRequestMessage *msg)
        -> std::shared_ptr<cellular::ResponseMessage>;
    void handleCellularHangupCallMessage(cellular::HangupCallMessage *msg);
    void handleCellularDismissCallMessage(sys::Message *msg);
    auto handleDBQueryResponseMessage(db::QueryResponse *msg) -> std::shared_ptr<sys::ResponseMessage>;
    /// when we start call from Pure -> to the calee, then we poll for the moment that the calee answered the call
    auto handleCellularListCallsMessage(CellularMessage *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleDBNotificationMessage(db::NotificationMessage *msg) -> std::shared_ptr<sys::ResponseMessage>;
    /// handle mudita phone -> world ringing (not AT RING!)
    auto handleCellularRingingMessage(cellular::RingingMessage *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularCallerIdMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularGetIMSIMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularGetOwnNumberMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularGetNetworkInfoMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;


@@ 272,7 268,6 @@ class ServiceCellular : public sys::Service
    auto handleCellularGetAntennaMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularDtmfRequestMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularUSSDMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleSimStateMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleStateRequestMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;

    auto handleCallActiveNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;


@@ 280,13 275,11 @@ class ServiceCellular : public sys::Service
    auto handlePowerDownDeregisteringNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handlePowerDownDeregisteredNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleNewIncomingSMSNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleRawCommandNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleSmsDoneNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleSignalStrengthUpdateNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleNetworkStatusUpdateNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleUrcIncomingNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularSetFlightModeMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularSetRadioOnOffMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularRingNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularCallerIdNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularSetConnectionFrequencyMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;


@@ 297,7 290,6 @@ class ServiceCellular : public sys::Service

    auto tetheringTurnOffURC() -> bool;
    auto tetheringTurnOnURC() -> bool;
    auto logTetheringCalls() -> void;
    std::unique_ptr<cellular::internal::ServiceCellularPriv> priv;
    TaskHandle_t getTaskHandle();
};

M module-services/service-cellular/src/ServiceCellularPriv.cpp => module-services/service-cellular/src/ServiceCellularPriv.cpp +17 -11
@@ 515,8 515,8 @@ namespace cellular::internal
            return std::nullopt;
        };

        csqHandler->onPropagateCSQ = [this](uint32_t csq) {
            SignalStrength signalStrength(static_cast<int>(csq));
        csqHandler->onPropagateCSQ = [this](std::uint32_t csq) {
            const SignalStrength signalStrength(static_cast<int>(csq));
            Store::GSM::get()->setSignalStrength(signalStrength.data);
            auto message = std::make_shared<cellular::SignalStrengthUpdateNotification>("");
            owner->bus.sendMulticast(message, sys::BusChannel::ServiceCellularNotifications);


@@ 555,36 555,43 @@ namespace cellular::internal
    void ServiceCellularPriv::initUSSDHandler()
    {
        ussdHandler->onOpenPushSession = [this]() -> bool {
            auto channel = owner->cmux->get(CellularMux::Channel::Commands);
            const auto &channel = owner->cmux->get(CellularMux::Channel::Commands);
            if (channel == nullptr) {
                LOG_ERROR("No cmux channel provided!");
                return false;
            }
            auto result = channel->cmd(at::AT::CUSD_OPEN_SESSION);
            const auto &result = channel->cmd(at::AT::CUSD_OPEN_SESSION);
            return result.code == at::Result::Code::OK;
        };

        ussdHandler->onAbortSession = [this]() -> bool {
            auto channel = owner->cmux->get(CellularMux::Channel::Commands);
        ussdHandler->onAbortSession = [this](bool ussdSessionTimeout) -> bool {
            const auto &channel = owner->cmux->get(CellularMux::Channel::Commands);
            if (channel == nullptr) {
                LOG_ERROR("No cmux channel provided!");
                return false;
            }
            auto result = channel->cmd(at::AT::CUSD_CLOSE_SESSION);

            if (ussdSessionTimeout) {
                auto msg =
                    std::make_shared<cellular::MMIResultMessage>(mmiactions::MMIResultParams::MMIResult::Timeout);
                owner->bus.sendUnicast(std::move(msg), ::service::name::appmgr);
            }

            const auto &result = channel->cmd(at::AT::CUSD_CLOSE_SESSION);
            return result.code == at::Result::Code::OK;
        };

        ussdHandler->onSendUssdCode = [this](const std::string &request) -> bool {
            const std::string commandDcs(",15");
            auto channel = owner->cmux->get(CellularMux::Channel::Commands);
            const auto &channel = owner->cmux->get(CellularMux::Channel::Commands);
            if (channel == nullptr) {
                LOG_ERROR("No cmux channel provided!");
                return false;
            }

            channel->cmd(at::AT::SMS_GSM);
            std::string command = at::factory(at::AT::CUSD_SEND) + request + commandDcs;
            const auto result   = channel->cmd(command, std::chrono::seconds(120));
            const auto &command = at::factory(at::AT::CUSD_SEND) + request + commandDcs;
            const auto &result  = channel->cmd(command, std::chrono::seconds(120));
            if (result.code == at::Result::Code::OK) {
                owner->bus.sendUnicast(std::make_shared<cellular::MMIConfirmationMessage>(), ::service::name::appmgr);
                return true;


@@ 683,5 690,4 @@ namespace cellular::internal
        simContacts->setChannel(nullptr);
        imeiGetHandler->setChannel(nullptr);
    }

} // namespace cellular::internal

M module-services/service-cellular/src/ussd/USSDHandler.cpp => module-services/service-cellular/src/ussd/USSDHandler.cpp +25 -11
@@ 5,7 5,6 @@

namespace cellular::ussd
{

    bool USSDHandler::handleUSSDRequest(cellular::USSDMessage::RequestType requestType, const std::string &request)
    {
        if (requestType == cellular::USSDMessage::RequestType::pullSessionRequest) {


@@ 17,21 16,22 @@ namespace cellular::ussd
        }

        if (requestType == cellular::USSDMessage::RequestType::abortSession) {
            if (onAbortSession && onAbortSession()) {
            if (onAbortSession && onAbortSession(ussdSessionTimeout())) {
                ussdState = ussd::State::sessionAborted;
                setUSSDTimer();
                if (onRequestOpenPushSession)
                if (onRequestOpenPushSession) {
                    onRequestOpenPushSession();
                }
            }
            else {
                if (onRequestAbortSession)
                if (onRequestAbortSession) {
                    onRequestAbortSession();
                }
            }
            return true;
        }

        if (requestType == cellular::USSDMessage::RequestType::pushSessionRequest) {

            if (onOpenPushSession && onOpenPushSession()) {
                ussdState = ussd::State::pushSession;
                setUSSDTimer();


@@ 41,18 41,21 @@ namespace cellular::ussd

        return false;
    }

    void USSDHandler::handleUSSDTimer()
    {
        if (ussdTimeout > 0) {
            ussdTimeout -= 1;
            --ussdTimeout;
        }
        else {
            LOG_WARN("USSD timeout occurred, aborting current session");
            onTimerStop();
            if (onRequestAbortSession)
            if (onRequestAbortSession) {
                onRequestAbortSession();
            }
        }
    }

    void USSDHandler::setUSSDTimer()
    {
        if (not onTimerStart || not onTimerStop) {


@@ 64,7 67,7 @@ namespace cellular::ussd
            ussdTimeout = pullResponseTimeout;
            break;
        case ussd::State::pullResponseReceived:
            ussdTimeout = pullSesionTimeout;
            ussdTimeout = pullSessionTimeout;
            break;
        case ussd::State::pushSession:
        case ussd::State::sessionAborted:


@@ 78,25 81,36 @@ namespace cellular::ussd
        }
        onTimerStart();
    }

    void USSDHandler::externalRequestHandled()
    {
        ussdState = ussd::State::pullRequestSent;
        setUSSDTimer();
    }

    auto USSDHandler::handleURC() -> bool
    bool USSDHandler::handleURC()
    {
        switch (ussdState) {
        case ussd::State::pullRequestSent:
            ussdState = State::pullResponseReceived;
            [[fallthrough]];
        case ussd::State::pushSession: {
        case ussd::State::pushSession:
            setUSSDTimer();
            return true;
        }
        default:
            LOG_WARN("unexpected URC handling state: %s", magic_enum::enum_name(ussdState).data());
            return false;
        }
    }

    bool USSDHandler::ussdSessionTimeout()
    {
        if (!onTimerGetState) {
            LOG_ERROR("No onTimerGetState callback provided!");
            return false;
        }

        const auto timerRunning = onTimerGetState();
        return (!timerRunning) && (ussdTimeout == 0);
    }
}; // namespace cellular::ussd

M module-services/service-cellular/src/ussd/USSDHandler.hpp => module-services/service-cellular/src/ussd/USSDHandler.hpp +14 -7
@@ 2,14 2,14 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <service-cellular/CellularMessage.hpp>
#include <cstdint>

namespace cellular::ussd
{

    constexpr std::uint32_t pullResponseTimeout = 30;
    constexpr std::uint32_t pullSesionTimeout   = 60;
    constexpr std::uint32_t pullSessionTimeout  = 60;
    constexpr std::uint32_t noTimeout           = 0;

    enum class State


@@ 27,29 27,36 @@ namespace cellular::ussd
        bool handleUSSDRequest(cellular::USSDMessage::RequestType requestType, const std::string &request = "");
        void handleUSSDTimer();
        void externalRequestHandled();
        auto handleURC() -> bool;
        bool handleURC();
        void setUSSDTimer();
        bool ussdSessionTimeout();

        void setTimerStartCallback(std::function<void(void)> callback)
        {
            onTimerStart = callback;
            onTimerStart = std::move(callback);
        }

        void setTimerGetStateCallback(std::function<bool(void)> callback)
        {
            onTimerGetState = std::move(callback);
        }

        void setTimerStopCallback(std::function<void(void)> callback)
        {
            onTimerStop = callback;
            onTimerStop = std::move(callback);
        }

        std::function<void(void)> onTimerStop;
        std::function<void(void)> onTimerStart;
        std::function<bool(void)> onTimerGetState;
        std::function<bool(void)> onOpenPushSession;
        std::function<bool(void)> onAbortSession;
        std::function<bool(bool)> onAbortSession;
        std::function<bool(const std::string &)> onSendUssdCode;
        std::function<void(void)> onRequestAbortSession;
        std::function<void(void)> onRequestOpenPushSession;

      private:
        State ussdState      = State::none;
        uint32_t ussdTimeout = 0;
        std::uint32_t ussdTimeout = 0;
    };
} // namespace cellular::ussd

M module-services/service-cellular/tests/unittest_ussdHandler.cpp => module-services/service-cellular/tests/unittest_ussdHandler.cpp +2 -2
@@ 24,7 24,7 @@ TEST_CASE("ussd handler")
        return true;
    };

    handler.onAbortSession = [&onAbortSessionCalled]() -> bool {
    handler.onAbortSession = [&onAbortSessionCalled]([[maybe_unused]] bool ussdSessionTimeout) -> bool {
        onAbortSessionCalled++;
        return true;
    };


@@ 90,7 90,7 @@ TEST_CASE("ussd handler")

    SECTION("HandleUSSDRequest - failed abort session request")
    {
        handler.onAbortSession = [&onAbortSessionCalled]() -> bool {
        handler.onAbortSession = [&onAbortSessionCalled]([[maybe_unused]] bool ussdSessionTimeout) -> bool {
            onAbortSessionCalled++;
            return false;
        };

M products/PurePhone/services/appmgr/ApplicationManager.cpp => products/PurePhone/services/appmgr/ApplicationManager.cpp +1 -1
@@ 405,7 405,7 @@ namespace app::manager
        connect(typeid(cellular::MMIConfirmationMessage), convertibleToActionHandler);
        connect(typeid(cellular::NoSimNotification), convertibleToActionHandler);
        connect(typeid(cellular::NotAnEmergencyNotification), convertibleToActionHandler);
        connect(typeid(cellular::NoNetworkConenctionNotification), convertibleToActionHandler);
        connect(typeid(cellular::NoNetworkConnectionNotification), convertibleToActionHandler);
        connect(typeid(cellular::CallRequestGeneralError), convertibleToActionHandler);
        connect(typeid(cellular::SmsNoSimRequestMessage), convertibleToActionHandler);
        connect(typeid(cellular::SMSRejectedByOfflineNotification), convertibleToActionHandler);

M pure_changelog.md => pure_changelog.md +1 -0
@@ 7,6 7,7 @@
* Added VoLTE support in Poland, Germany, Denmark, United Kingdom, Netherlands, Canada and Austria
* Added extended information to crashdump filename
* Added extended information to log filename
* Added GUI screens informing about failed MMI/USSD request

### Changed / Improved