~aleteoryx/muditaos

cb593f45c32f6a2d5f39489674ef60fa63a7f532 — Michał Kamoń 5 years ago 26c0321
[EGD-4367] sim passcodes flow implementation (#1033)

31 files changed, 1151 insertions(+), 504 deletions(-)

M changelog.md
M image/assets/lang/lang_en.json
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/ApplicationDesktop.hpp
M module-apps/application-desktop/data/AppDesktopStyle.hpp
M module-apps/application-desktop/data/LockPhoneData.hpp
M module-apps/application-desktop/widgets/PinLock.cpp
M module-apps/application-desktop/widgets/PinLock.hpp
M module-apps/application-desktop/widgets/PinLockHandler.cpp
M module-apps/application-desktop/widgets/PinLockHandler.hpp
M module-apps/application-desktop/windows/DesktopMainWindow.cpp
M module-apps/application-desktop/windows/DesktopMainWindow.hpp
M module-apps/application-desktop/windows/PinLockBaseWindow.cpp
M module-apps/application-desktop/windows/PinLockBaseWindow.hpp
M module-apps/application-desktop/windows/PinLockBox.hpp
M module-apps/application-desktop/windows/PinLockWindow.cpp
M module-apps/application-desktop/windows/PinLockWindow.hpp
M module-apps/application-desktop/windows/PukLockBox.cpp
M module-apps/application-desktop/windows/PukLockBox.hpp
M module-apps/application-desktop/windows/ScreenLockBox.cpp
M module-apps/application-desktop/windows/ScreenLockBox.hpp
M module-apps/application-desktop/windows/SimLockBox.cpp
M module-apps/application-desktop/windows/SimLockBox.hpp
M module-services/service-appmgr/CMakeLists.txt
A module-services/service-appmgr/data/SimActionsParams.cpp
M module-services/service-appmgr/model/ApplicationManager.cpp
M module-services/service-appmgr/service-appmgr/Actions.hpp
A module-services/service-appmgr/service-appmgr/data/SimActionsParams.hpp
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp
M module-services/service-cellular/service-cellular/CellularMessage.hpp
M module-services/service-desktop/ServiceDesktop.cpp
M changelog.md => changelog.md +1 -0
@@ 4,6 4,7 @@

### Added

* `[gui][desktop]` Added SIM PIN basic flow implementation
* `[cellular]` Added CLIR, CLIP, COLP, call waiting MMI support

## [0.47.1 2020-11-20]

M image/assets/lang/lang_en.json => image/assets/lang/lang_en.json +3 -0
@@ 163,6 163,8 @@
    "app_desktop_sim_card": "card",
    "app_desktop_sim_type_pin": "please type a PIN code:",
    "app_desktop_sim_blocked": "The SIM card is blocked.",
    "app_desktop_sim_enter_pin": "Enter new PIN code",
    "app_desktop_sim_confirm_pin": "Enter new PIN code",
    "app_desktop_sim_type_puk": "To unblock it, type the PUK code:",
    "app_desktop_no_pin_lock": "<text>Press <b>Unlock</b> and then <b>#</b></text>",
    "app_desktop_sim_wrong_pin": "Wrong PIN code",


@@ 175,6 177,7 @@
    "app_desktop_sim_warning3": "have to contact the operator",
    "app_desktop_sim_blocked_info1": "Sorry, SIM card permanently blocked.",
    "app_desktop_sim_blocked_info2": "Please contact your service provider",
    "app_desktop_sim_cme_error": "<text>SIM card\nCME error:</text>",

    "app_desktop_unread_messages": "<text>Unread <b>messages</b></text>",
    "app_desktop_missed_calls": "<text>Missed <b>calls</b></text>",

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +30 -6
@@ 19,6 19,7 @@
#include <application-settings/ApplicationSettings.hpp>
#include <service-appmgr/Controller.hpp>
#include <service-cellular/ServiceCellular.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <application-calllog/ApplicationCallLog.hpp>
#include <service-db/QueryMessage.hpp>
#include <module-db/queries/notifications/QueryNotificationsClear.hpp>


@@ 30,6 31,31 @@ namespace app
        : Application(name, parent, startInBackground), lockHandler(this, settings)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);

        addActionReceiver(app::manager::actions::RequestPin, [this](auto &&data) {
            lockHandler.handlePinRequest(std::move(data));
            return msgHandled();
        });

        addActionReceiver(app::manager::actions::RequestPuk, [this](auto &&data) {
            lockHandler.handlePukRequest(std::move(data));
            return msgHandled();
        });

        addActionReceiver(app::manager::actions::RequestPinChange, [this](auto &&data) {
            lockHandler.handlePinChangeRequest(std::move(data));
            return msgHandled();
        });

        addActionReceiver(app::manager::actions::BlockSim, [this](auto &&data) {
            lockHandler.handleSimBlocked(std::move(data));
            return msgHandled();
        });

        addActionReceiver(app::manager::actions::DisplayCMEError, [this](auto &&data) {
            lockHandler.handleCMEError(std::move(data));
            return msgHandled();
        });
    }

    ApplicationDesktop::~ApplicationDesktop()


@@ 63,9 89,6 @@ namespace app
        else if (auto msg = dynamic_cast<sdesktop::UpdateOsMessage *>(msgl)) {
            handled = handle(msg);
        }
        else if (auto msg = dynamic_cast<CellularSimResponseMessage *>(msgl)) {
            handled = lockHandler.handle(msg);
        }

        // handle database response
        if (resp != nullptr) {


@@ 100,7 123,8 @@ namespace app
    auto ApplicationDesktop::handle(sdesktop::developerMode::ScreenlockCheckEvent *event) -> bool
    {
        if (event != nullptr) {
            auto event = std::make_unique<sdesktop::developerMode::ScreenlockCheckEvent>(lockHandler.lock.isLocked());
            auto event =
                std::make_unique<sdesktop::developerMode::ScreenlockCheckEvent>(true); // lockHandler.lock.isLocked());
            auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
            sys::Bus::SendUnicast(std::move(msg), service::name::service_desktop, this);
        }


@@ 167,7 191,7 @@ namespace app
    {
        assert(msg);
        if (msg->request == cellular::State::ST::URCReady) {
            if (need_sim_select && !lockHandler.lock.isLocked()) {
            if (need_sim_select && !lockHandler.isScreenLocked()) {
                app::manager::Controller::switchApplication(this, app::name_settings, app::sim_select, nullptr);
                return true;
            }


@@ 280,7 304,7 @@ namespace app
            return std::make_unique<gui::DesktopMainWindow>(app);
        });
        windowsFactory.attach(desktop_pin_lock, [&](Application *app, const std::string newname) {
            return std::make_unique<gui::PinLockWindow>(app, desktop_pin_lock, lockHandler.lock);
            return std::make_unique<gui::PinLockWindow>(app, desktop_pin_lock);
        });
        windowsFactory.attach(desktop_menu, [](Application *app, const std::string newname) {
            return std::make_unique<gui::MenuWindow>(app);

M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +12 -1
@@ 15,6 15,11 @@
#include <service-desktop/ServiceDesktop.hpp>
#include <service-desktop/DesktopMessages.hpp>

namespace cellular
{
    class StateChange;
}

namespace app
{
    inline constexpr auto name_desktop = "ApplicationDesktop";


@@ 83,7 88,13 @@ namespace app
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
            return {{manager::actions::Launch,
                     manager::actions::RequestPin,
                     manager::actions::RequestPuk,
                     manager::actions::RequestPinChange,
                     manager::actions::UnlockSim,
                     manager::actions::BlockSim,
                     manager::actions::DisplayCMEError}};
        }
    };


M module-apps/application-desktop/data/AppDesktopStyle.hpp => module-apps/application-desktop/data/AppDesktopStyle.hpp +13 -13
@@ 7,17 7,17 @@

namespace style::window::pin_lock
{
    const inline uint32_t image_x            = 177;
    const inline uint32_t image_y            = 132;
    const inline uint32_t title_label_y      = 60;
    const inline uint32_t title_label_h      = 40;
    const inline uint32_t label_size         = 30;
    const inline uint32_t label_size_screen  = 60;
    const inline uint32_t pin_label_x        = 85;
    const inline uint32_t pin_label_x_screen = 100;
    const inline uint32_t pin_label_y        = 450;
    const inline uint32_t info_text_y        = 294;
    const inline uint32_t info_text_h_screen = 60;
    const inline uint32_t info_text_h_sim    = 150;
    const inline uint32_t info_text_h_puk    = 180;
    constexpr inline auto image_x            = 177;
    constexpr inline auto image_y            = 132;
    constexpr inline auto title_label_y      = 60;
    constexpr inline auto title_label_h      = 40;
    constexpr inline auto label_size         = 60;
    constexpr inline auto label_margins      = 10;
    constexpr inline auto pin_label_x        = 85;
    constexpr inline auto pin_label_y        = 450;
    constexpr inline auto pin_label_y_screen = 400;
    constexpr inline auto info_text_y        = 294;
    constexpr inline auto info_text_h_screen = 60;
    constexpr inline auto info_text_h_sim    = 150;
    constexpr inline auto info_text_h_puk    = 180;
} // namespace style::window::pin_lock

M module-apps/application-desktop/data/LockPhoneData.hpp => module-apps/application-desktop/data/LockPhoneData.hpp +10 -10
@@ 9,6 9,8 @@
#include <service-desktop/ServiceDesktop.hpp>
#include <filesystem>

#include "application-desktop/widgets/PinLock.hpp"

namespace gui
{



@@ 16,17 18,10 @@ namespace gui
    class LockPhoneData : public gui::SwitchData
    {
        std::string previousApplication;
        LockPhoneData() = default;
        std::unique_ptr<PinLock> lock;

      public:
        enum class Request
        {
            NoPin,
            Pin,
            ShowPrompt,
        } request;

        LockPhoneData(Request request) : SwitchData(), request(request)
        LockPhoneData(std::unique_ptr<PinLock> &&lock) : SwitchData(), lock(std::move(lock))
        {
            description = "LockPhoneData";
        }


@@ 37,10 32,15 @@ namespace gui
        {
            previousApplication = prevApp;
        };
        const std::string &getPreviousApplication()
        [[nodiscard]] const std::string &getPreviousApplication()
        {
            return previousApplication;
        };

        [[nodiscard]] std::unique_ptr<PinLock> getLock()
        {
            return std::make_unique<PinLock>(*lock.get());
        }
    };

    class UpdateSwitchData : public gui::SwitchData

M module-apps/application-desktop/widgets/PinLock.cpp => module-apps/application-desktop/widgets/PinLock.cpp +25 -55
@@ 6,83 6,53 @@

namespace gui
{
    PinLock::PinLock(gui::PinLockHandler *handler) : handler(handler)
    {}

    void PinLock::consumeInvalidPinState() noexcept
    void PinLock::consumeState() noexcept
    {
        if (state == State::InvalidPin) {
            state = State::EnterPin;
        if (lockState == LockState::PasscodeInvalidRetryRequired) {
            lockState = LockState::PasscodeRequired;
        }
    }

    void PinLock::putNextChar(unsigned int c) noexcept
    {
        if (state == State::EnterPin && charCount < pinValue.size()) {
            pinValue[charCount++] = c;
        else if (lockState == LockState::NewPasscodeInvalid) {
            lockState = LockState::NewPasscodeRequired;
        }
    }

    void PinLock::verifyPin() noexcept
    void PinLock::setNewPasscodeInvalidState() noexcept
    {
        if (charCount == pinValue.size()) {
            handler->handle(pinValue);
            clearAttempt();
        if (lockState == LockState::NewPasscodeRequired) {
            lockState = LockState::NewPasscodeInvalid;
        }
    }

    void PinLock::popChar() noexcept
    void PinLock::putNextChar(unsigned int c)
    {
        if (state == State::EnterPin && charCount > 0) {
            charCount--;
            pinValue[charCount] = 0;
        if (maxPinSize > pinValue.size()) {
            pinValue.push_back(c);
        }
    }

    void PinLock::clearAttempt() noexcept
    {
        for (auto &c : pinValue) {
            c = 0;
        if (canVerify() && autoActivate && onActivatedCallback != nullptr) {
            onActivatedCallback(pinValue);
        }
        charCount = 0;
    }

    bool PinLock::unlock() noexcept
    void PinLock::popChar()
    {
        if (state == State::VerifiedPin || pinValue.size() == 0) {
            state = State::Unlocked;
            return true;
        if (pinValue.size() > 0) {
            pinValue.pop_back();
        }
        return false;
    }

    void PinLock::lock() noexcept
    {
        if (state == State::Unlocked) {
            state = State::EnterPin;
        }
    }

    bool PinLock::isLocked() const noexcept
    void PinLock::clearAttempt() noexcept
    {
        return state != State::Unlocked;
        pinValue.clear();
    }

    std::string PinLock::getLockInfo(const InfoName name) const
    void PinLock::verify()
    {
        try {
            return additionalLockInfo.at(name);
        auto pinCopy = std::move(pinValue);
        clearAttempt();
        if (!onActivatedCallback) {
            LOG_ERROR("Passcode verification callback null");
            return;
        }
        catch (std::out_of_range &) {
            return std::string{};
        }
    }

    void PinLock::reset(LockType newType, State newState, unsigned int attempts, unsigned int size) noexcept
    {
        type              = newType;
        state             = newState;
        remainingAttempts = attempts;
        pinValue          = std::vector<unsigned int>(size, 0);
        onActivatedCallback(pinCopy);
    }
} // namespace gui

M module-apps/application-desktop/widgets/PinLock.hpp => module-apps/application-desktop/widgets/PinLock.hpp +71 -49
@@ 2,8 2,9 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "PhoneNumber.hpp"
#include <vector>
#include <string>
#include <functional>

namespace gui
{


@@ 14,82 15,103 @@ namespace gui
      public:
        enum class LockType
        {
            Screen,
            SIM,
            PUK,
            Unknown
            SimPin,
            SimPuk,
            Screen
        };
        enum class InfoName
        enum class LockState
        {
            LockName,
            PhoneNum
            Unlocked,
            PasscodeRequired,
            PasscodeInvalidRetryRequired,
            Blocked,
            NewPasscodeRequired,
            NewPasscodeInvalid,
            ErrorOccurred
        };
        enum class State
        enum class SimCard
        {
            EnterPin,
            InvalidPin,
            VerifiedPin,
            Blocked,
            Unlocked
            SIM1,
            SIM2,
            NoCard
        };

        [[nodiscard]] State getState() const noexcept
        [[nodiscard]] LockState getState() const noexcept
        {
            return state;
            return lockState;
        }
        [[nodiscard]] unsigned int getPinSize() const noexcept
        [[nodiscard]] LockType getLockType() const noexcept
        {
            return pinValue.size();
            return lockType;
        }
        [[nodiscard]] unsigned int getMaxPinSize() const noexcept
        {
            return maxPinSize;
        }
        /// returns current position of a PIN character to be inserted
        [[nodiscard]] unsigned int getCharCount() const noexcept
        {
            return charCount;
            return pinValue.size();
        }
        [[nodiscard]] bool canPut() const noexcept
        {
            return getCharCount() < getMaxPinSize();
        }
        [[nodiscard]] unsigned int getRemainingAttempts() const noexcept
        [[nodiscard]] bool canVerify() const noexcept
        {
            return remainingAttempts;
            return getCharCount() >= minPinSize;
        }
        [[nodiscard]] bool canPut() const noexcept
        [[nodiscard]] std::vector<unsigned int> getPin() const
        {
            return getCharCount() != getPinSize();
            return pinValue;
        }
        void putNextChar(unsigned int c) noexcept;
        void verifyPin() noexcept;
        [[nodiscard]] unsigned int getValue() const noexcept
        {
            return value;
        }

        void putNextChar(unsigned int c);
        /// removes a last character passed to Lock via putNextChar. The last character can not be popped
        void popChar() noexcept;
        void popChar();
        /// clear all characters passed to the Lock
        void clearAttempt() noexcept;
        /// if Lock is in the State::InvalidPin state, changes it's state to the State::EnterPin
        void consumeInvalidPinState() noexcept;
        /// consumes LockState::PasscodeInvalidRetryRequired state and LockState::NewPasscodeInvalid)
        void consumeState() noexcept;
        void setNewPasscodeInvalidState() noexcept;

        [[nodiscard]] bool isLocked() const noexcept;
        bool unlock() noexcept;
        void lock() noexcept;
        void verify();

        [[nodiscard]] std::string getLockInfo(const InfoName name) const;
        [[nodiscard]] LockType getLockType() const noexcept
        {
            return type;
        }
        PinLock(gui::PinLockHandler *);
        PinLock(SimCard sim, LockState state, LockType type, unsigned int value)
            : sim{sim}, lockState{state}, lockType{type}, value{value}
        {}
        PinLock(const PinLock &other) = default;

        std::function<void(const std::vector<unsigned int> &)> onActivatedCallback = nullptr;

      private:
        /// for PIN verification purposes as PIN storage and management is out of scope of PinLock class
        gui::PinLockHandler *handler;
        SimCard sim         = SimCard::NoCard;
        LockState lockState = LockState::Unlocked;
        LockType lockType   = LockType::Screen;
        unsigned int value  = 0;

        LockType type                  = LockType::Unknown;
        State state                    = State::EnterPin;
        unsigned int remainingAttempts = 0;
        /// code of the entered character on specified position
        std::vector<unsigned int> pinValue;
        /// flag defines number of entered pin characters
        unsigned int charCount = 0;
        std::map<InfoName, std::string> additionalLockInfo;
        unsigned int maxPinSize = defaultPasscodeSize;
        unsigned int minPinSize = defaultPasscodeSize;
        bool autoActivate       = false;

        static constexpr unsigned int defaultPasscodeSize = 4;

        void reset(LockType, State, unsigned int remainingAttempts, unsigned int pinSize) noexcept;
        void setAutoActivate(bool _autoActivate)
        {
            autoActivate = _autoActivate;
        }
        void setPinSizeBounds(unsigned int _minPinSize, unsigned int _maxPinSize)
        {
            minPinSize = _minPinSize;
            maxPinSize = _maxPinSize;
        }

        friend class gui::PinLockHandler;
        friend class PinLockHandler;
    };

} // namespace gui

M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +174 -95
@@ 1,139 1,218 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
//// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
//// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PinLockHandler.hpp"
#include "PinHash.hpp"
#include "application-desktop/ApplicationDesktop.hpp"
#include <service-cellular/ServiceCellular.hpp>
#include "application-desktop/data/LockPhoneData.hpp"
#include "application-desktop/windows/Names.hpp"

#include <module-utils/common_data/EventStore.hpp>

#include <service-appmgr/service-appmgr/data/SimActionsParams.hpp>
#include <service-cellular/CellularMessage.hpp>

namespace gui
{
    constexpr unsigned int default_screen_pin_size = 4;
    constexpr unsigned int default_screen_attempts = 4;
    namespace
    {
        constexpr unsigned int default_screen_pin_size = 4;
        constexpr unsigned int screen_nopin_size       = 0;
        constexpr unsigned int default_attempts        = 4;
        constexpr unsigned int blocked_sim_attempts    = 0;
        constexpr unsigned int sim_max_passcode_size   = 8;
        constexpr unsigned int sim_min_passcode_size   = 4;
    } // namespace

    PinLockHandler::PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings)
        : app(app), appSettings(settings), lock(this)
        : app(app), appSettings(settings), screenLock(PinLock::SimCard::NoCard,
                                                      PinLock::LockState::PasscodeRequired,
                                                      PinLock::LockType::Screen,
                                                      default_attempts),
          simLock(PinLock::SimCard::NoCard, PinLock::LockState::Unlocked, PinLock::LockType::SimPin, default_attempts)
    {
        reloadScreenLock();
        screenLock.setAutoActivate(true);

        simLock.setPinSizeBounds(sim_min_passcode_size, sim_max_passcode_size);
    }

    auto PinLockHandler::handle(CellularSimResponseMessage *msg) -> bool
    void PinLockHandler::handleScreenPin(const std::vector<unsigned int> &pin)
    {
        assert(msg);
        if (screenLock.getMaxPinSize() == screen_nopin_size) {
            screenLock.lockState = gui::PinLock::LockState::Unlocked;
        }
        else if (screenLock.value > 0) {
            std::hash<std::vector<unsigned int>> hashEngine;
            uint32_t hash = hashEngine(pin);
            screenLock.value--;
            if (hash == appSettings.lockPassHash) {
                screenLock.lockState = gui::PinLock::LockState::Unlocked;
                screenLock.value     = default_attempts;
            }
            else if (screenLock.value > 0) {
                screenLock.lockState = gui::PinLock::LockState::PasscodeInvalidRetryRequired;
            }
            else {
                screenLock.lockState = gui::PinLock::LockState::Blocked;
            }
        }
    }

        parseSimCard(msg);
        parseSimState(msg);
        parseAttemptsAndPinSize(msg);
    void PinLockHandler::handleScreenConfirm()
    {
        simLock.consumeState();
    }

        app->getWindow(app::window::name::desktop_pin_lock)->rebuild();
        app->switchWindow(gui::name::window::main_window);
        return true;
    void PinLockHandler::reloadScreenLock()
    {
        screenLock.lockState = gui::PinLock::LockState::PasscodeRequired;
        unsigned int pinSize = appSettings.lockPassHash == 0 ? screen_nopin_size : default_screen_pin_size;
        screenLock.setPinSizeBounds(pinSize, pinSize);
        screenLock.value = default_attempts;
    }

    void PinLockHandler::handle(const std::vector<unsigned int> &pin)
    auto PinLockHandler::handlePasscodeParams(app::manager::actions::ActionParamsPtr &&data) const -> gui::PinLock
    {
        if (lock.getLockType() == gui::PinLock::LockType::Screen) {
            handleScreenPin(pin);
        }
        else {
            handleSimPinOrPuk(pin);
        auto passcodeData = static_cast<app::manager::actions::PasscodeParams *>(data.get());

        gui::PinLock lock(parseSimCard(passcodeData->getSim()),
                          gui::PinLock::LockState::PasscodeRequired,
                          simLock.getLockType(),
                          passcodeData->getAttempts());

        if (simLock.getLockType() == lock.getLockType() && simLock.getState() == lock.getState() &&
            simLock.getValue() > lock.getValue()) {
            lock.lockState = PinLock::LockState::PasscodeInvalidRetryRequired;
        }
        lock.setPinSizeBounds(sim_min_passcode_size, sim_max_passcode_size);

        return lock;
    }

    void PinLockHandler::parseSimState(CellularSimResponseMessage *msg)
    {
        assert(msg);
        switch (msg->getSimState()) {
        case CellularSimResponseMessage::SimState::SIMUnlocked:
            lock.type  = gui::PinLock::LockType::Screen;
            lock.state = gui::PinLock::State::EnterPin;
            break;
        case CellularSimResponseMessage::SimState::PINRequired:
            lock.type  = gui::PinLock::LockType::SIM;
            lock.state = gui::PinLock::State::EnterPin;
            break;
        case CellularSimResponseMessage::SimState::PINInvalidRetryPossible:
            lock.type  = gui::PinLock::LockType::SIM;
            lock.state = gui::PinLock::State::InvalidPin;
            break;
        case CellularSimResponseMessage::SimState::PUKRequired:
            lock.type  = gui::PinLock::LockType::PUK;
            lock.state = gui::PinLock::State::EnterPin;
            break;
        case CellularSimResponseMessage::SimState::PUKInvalidRetryPossible:
            lock.type  = gui::PinLock::LockType::PUK;
            lock.state = gui::PinLock::State::InvalidPin;
            break;
        case CellularSimResponseMessage::SimState::SIMBlocked:
            lock.type  = gui::PinLock::LockType::PUK;
            lock.state = gui::PinLock::State::Blocked;
            break;
        }
    void PinLockHandler::handlePinRequest(app::manager::actions::ActionParamsPtr &&data)
    {
        simLock          = handlePasscodeParams(std::move(data));
        simLock.lockType = gui::PinLock::LockType::SimPin;

        auto onActivatedCallback = [this](const std::vector<unsigned int> &data) { handlePasscode(data); };
        switchToPinlockWindow(onActivatedCallback);
    }

    void PinLockHandler::parseSimCard(CellularSimResponseMessage *msg)
    {
        assert(msg);
        switch (msg->getSimCard()) {
        case Store::GSM::SIM::SIM1:
            lock.additionalLockInfo[gui::PinLock::InfoName::LockName] = "SIM1";
            break;
        case Store::GSM::SIM::SIM2:
            lock.additionalLockInfo[gui::PinLock::InfoName::LockName] = "SIM2";
            break;
        default:
            LOG_ERROR("Unknown SIM");
            break;
        }
    void PinLockHandler::handlePukRequest(app::manager::actions::ActionParamsPtr &&data)
    {
        simLock          = handlePasscodeParams(std::move(data));
        simLock.lockType = gui::PinLock::LockType::SimPuk;

        auto onActivatedCallback = [this](const std::vector<unsigned int> &data) { handlePasscodeChange(data); };
        switchToPinlockWindow(onActivatedCallback);
    }

    void PinLockHandler::parseAttemptsAndPinSize(CellularSimResponseMessage *msg)
    void PinLockHandler::switchToPinlockWindow(
        std::function<void(const std::vector<unsigned int> &)> onLockActivatedCallback)
    {
        if (msg->getSimState() == CellularSimResponseMessage::SimState::SIMUnlocked) {
            reloadScreenLock();
        auto lock = std::make_unique<gui::PinLock>(simLock);

        if (lock->getState() == PinLock::LockState::PasscodeInvalidRetryRequired) {
            lock->onActivatedCallback = [this, onLockActivatedCallback](const std::vector<unsigned int> &) {
                simLock.consumeState();
                switchToPinlockWindow(onLockActivatedCallback);
            };
        }
        else {
            lock.pinValue          = std::vector<unsigned int>(msg->getPinSize(), 0);
            lock.remainingAttempts = msg->getAttemptsLeft();
            lock->onActivatedCallback = onLockActivatedCallback;
        }

        app->switchWindow(app::window::name::desktop_pin_lock,
                          gui::ShowMode::GUI_SHOW_INIT,
                          std::make_unique<gui::LockPhoneData>(std::move(lock)));
    }

    void PinLockHandler::handleScreenPin(const std::vector<unsigned int> &pin)
    void PinLockHandler::handlePinChangeRequest(app::manager::actions::ActionParamsPtr &&data)
    {
        if (lock.remainingAttempts > 0) {
            std::hash<std::vector<unsigned int>> hashEngine;
            uint32_t hash = hashEngine(pin);
            lock.remainingAttempts--;
            if (hash == appSettings.lockPassHash) {
                lock.remainingAttempts = default_screen_attempts;
                lock.state             = gui::PinLock::State::VerifiedPin;
            }
            else if (lock.remainingAttempts > 0) {
                lock.state = gui::PinLock::State::InvalidPin;
            }
            else {
                lock.state = gui::PinLock::State::Blocked;
            }
        simLock          = handlePasscodeParams(std::move(data));
        simLock.lockType = gui::PinLock::LockType::SimPin;

            app->switchWindow(app::window::name::desktop_pin_lock);
        }
        auto onActivatedCallback = [this](const std::vector<unsigned int> &data) { handlePasscodeChange(data); };
        switchToPinlockWindow(onActivatedCallback);
    }

    void PinLockHandler::handleSimPinOrPuk(const std::vector<unsigned int> &pin)
    void PinLockHandler::handleSimBlocked(app::manager::actions::ActionParamsPtr &&data)
    {
        auto sim = Store::GSM::SIM::SIM1;
        sys::Bus::SendUnicast(
            std::make_shared<CellularSimVerifyPinRequestMessage>(sim, pin), ServiceCellular::serviceName, app);
        auto params = static_cast<app::manager::actions::SimStateParams *>(data.get());
        simLock     = PinLock(parseSimCard(params->getSim()),
                          gui::PinLock::LockState::Blocked,
                          gui::PinLock::LockType::SimPin,
                          blocked_sim_attempts);

        auto lock = std::make_unique<gui::PinLock>(simLock);
        app->switchWindow(app::window::name::desktop_pin_lock,
                          gui::ShowMode::GUI_SHOW_INIT,
                          std::make_unique<gui::LockPhoneData>(std::move(lock)));
    }

    void PinLockHandler::reloadScreenLock()
    void PinLockHandler::handleCMEError(app::manager::actions::ActionParamsPtr &&data) const
    {
        lock.type  = gui::PinLock::LockType::Screen;
        lock.state = gui::PinLock::State::EnterPin;
        auto params = static_cast<app::manager::actions::UnhandledCMEParams *>(data.get());

        auto lock = std::make_unique<gui::PinLock>(parseSimCard(params->getSim()),
                                                   PinLock::LockState::ErrorOccurred,
                                                   PinLock::LockType::SimPin,
                                                   params->getCMECode());

        unsigned int pinSize   = appSettings.lockPassHash == 0 ? 0 : default_screen_pin_size;
        lock.pinValue          = std::vector<unsigned int>(pinSize, 0);
        lock.remainingAttempts = default_screen_attempts;
        app->switchWindow(app::window::name::desktop_pin_lock,
                          gui::ShowMode::GUI_SHOW_INIT,
                          std::make_unique<gui::LockPhoneData>(std::move(lock)));
    }

    void PinLockHandler::handlePasscode(const std::vector<unsigned int> passcode) const
    {
        if (simLock.getLockType() == PinLock::LockType::SimPin) {
            sys::Bus::SendUnicast(
                std::make_shared<CellularSimPinDataMessage>(Store::GSM::SIM::SIM1, passcode), "ServiceCellular", app);
        }
        else if (simLock.getLockType() == PinLock::LockType::SimPuk) {
            handlePasscodeChange(passcode);
        }
    }
    void PinLockHandler::handlePasscodeChange(const std::vector<unsigned int> passcode) const
    {
        auto lock       = std::make_unique<gui::PinLock>(simLock);
        lock->lockState = PinLock::LockState::NewPasscodeRequired;

        lock->onActivatedCallback = [this, passcode](const std::vector<unsigned int> &pin) {
            handleNewPasscodeConfirmed(passcode, pin);
        };

        app->switchWindow(app::window::name::desktop_pin_lock,
                          gui::ShowMode::GUI_SHOW_INIT,
                          std::make_unique<gui::LockPhoneData>(std::move(lock)));
    }

    void PinLockHandler::handleNewPasscodeConfirmed(const std::vector<unsigned int> &passcode,
                                                    const std::vector<unsigned int> &pin) const
    {
        if (simLock.getLockType() == PinLock::LockType::SimPin) {
            sys::Bus::SendUnicast(std::make_shared<CellularSimNewPinDataMessage>(Store::GSM::SIM::SIM1, passcode, pin),
                                  "ServiceCellular",
                                  app);
        }
        else if (simLock.getLockType() == PinLock::LockType::SimPuk) {
            sys::Bus::SendUnicast(std::make_shared<CellularSimPukDataMessage>(Store::GSM::SIM::SIM1, passcode, pin),
                                  "ServiceCellular",
                                  app);
        }
    }

    auto PinLockHandler::parseSimCard(Store::GSM::SIM sim) const noexcept -> PinLock::SimCard
    {
        if (sim == Store::GSM::SIM::SIM1) {
            return gui::PinLock::SimCard::SIM1;
        }
        else if (sim == Store::GSM::SIM::SIM2) {
            return gui::PinLock::SimCard::SIM2;
        }
        return gui::PinLock::SimCard::NoCard;
    }

} // namespace gui

M module-apps/application-desktop/widgets/PinLockHandler.hpp => module-apps/application-desktop/widgets/PinLockHandler.hpp +32 -9
@@ 4,9 4,12 @@
#pragma once

#include "PinLock.hpp"
#include <service-cellular/CellularMessage.hpp>

#include "Interface/SettingsRecord.hpp"

#include <module-services/service-appmgr/service-appmgr/messages/ActionRequest.hpp>
#include <module-services/service-appmgr/service-appmgr/Actions.hpp>

namespace app
{
    class ApplicationDesktop;


@@ 19,19 22,39 @@ namespace gui
        app::ApplicationDesktop *app = nullptr;
        const SettingsRecord &appSettings;

        void parseSimCard(CellularSimResponseMessage *msg);
        void parseSimState(CellularSimResponseMessage *msg);
        void parseAttemptsAndPinSize(CellularSimResponseMessage *msg);
        auto parseSimCard(Store::GSM::SIM sim) const noexcept -> PinLock::SimCard;

        void handleScreenPin(const std::vector<unsigned int> &pin);
        void handleSimPinOrPuk(const std::vector<unsigned int> &pin);
        void handlePasscode(const std::vector<unsigned int> passcode) const;
        void handlePasscodeChange(const std::vector<unsigned int> passcode) const;
        void handleNewPasscodeConfirmed(const std::vector<unsigned int> &passcode,
                                        const std::vector<unsigned int> &pin) const;
        auto handlePasscodeParams(app::manager::actions::ActionParamsPtr &&data) const -> gui::PinLock;

        void switchToPinlockWindow(std::function<void(const std::vector<unsigned int> &)> onLockActivatedCallback);

      public:
        PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings);
        void reloadScreenLock();
        auto handle(CellularSimResponseMessage *msg) -> bool;
        void handle(const std::vector<unsigned int> &pin);

        gui::PinLock lock;
        void handleScreenPin(const std::vector<unsigned int> &pin);
        void handleScreenConfirm();
        void handlePinRequest(app::manager::actions::ActionParamsPtr &&data);
        void handlePukRequest(app::manager::actions::ActionParamsPtr &&data);
        void handlePinChangeRequest(app::manager::actions::ActionParamsPtr &&data);

        void handleSimBlocked(app::manager::actions::ActionParamsPtr &&data);
        void handleCMEError(app::manager::actions::ActionParamsPtr &&data) const;

        [[nodiscard]] bool isScreenLocked() const noexcept
        {
            return screenLock.getState() != PinLock::LockState::Unlocked;
        }
        void lockScreen() noexcept
        {
            screenLock.lockState = PinLock::LockState::PasscodeRequired;
        }

        gui::PinLock screenLock;
        gui::PinLock simLock;
    };
} // namespace gui

M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +70 -34
@@ 89,9 89,7 @@ namespace gui
    void DesktopMainWindow::setVisibleState()
    {
        auto app = getAppDesktop();

        if (app->lockHandler.lock.isLocked() && app->lockHandler.lock.getLockType() == PinLock::LockType::Screen) {

        if (app->lockHandler.isScreenLocked()) {
            bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_desktop_unlock"));
            bottomBar->setActive(BottomBar::Side::LEFT, false);
            bottomBar->setActive(BottomBar::Side::RIGHT, false);


@@ 103,12 101,6 @@ namespace gui
            sys::Bus::SendUnicast(
                std::make_shared<TimersProcessingStopMessage>(), service::name::service_time, application);
        }
        else if (app->lockHandler.lock.isLocked()) {
            application->switchWindow(app::window::name::desktop_pin_lock);

            sys::Bus::SendUnicast(
                std::make_shared<TimersProcessingStopMessage>(), service::name::service_time, application);
        }
        else {
            topBar->setActive(TopBar::Elements::LOCK, false);



@@ 135,36 127,47 @@ namespace gui
        // check if there was a signal to lock the pone due to inactivity.
        if ((data != nullptr) && (data->getDescription() == "LockPhoneData")) {
            auto app = getAppDesktop();
            if (app->lockHandler.lock.isLocked()) {
            if (app->lockHandler.isScreenLocked()) {
                return;
            }

            auto *lockData          = dynamic_cast<LockPhoneData *>(data);
            lockTimeoutApplilcation = lockData->getPreviousApplication();

            application->setSuspendFlag(true);
        }

        if (mode == ShowMode::GUI_SHOW_RETURN) {
            auto lock = getScreenLock();
            if (lock->getState() == PinLock::LockState::Unlocked) {
                setVisibleState();
                return;
            }
            switchToPinLockWindow(std::move(lock));
        }

        setVisibleState();
    }

    bool DesktopMainWindow::processLongPressEvent(const InputEvent &inputEvent)
    {
        auto *app = getAppDesktop();
        auto app = getAppDesktop();

        if (inputEvent.is(KeyCode::KEY_PND) && (!app->lockHandler.lock.isLocked())) {
            app->lockHandler.lock.lock();
            setVisibleState();
            application->setSuspendFlag(true);
            return true;
        if (!app->lockHandler.isScreenLocked()) {
            if (inputEvent.is(KeyCode::KEY_PND)) {
                app->lockHandler.lockScreen();
                setVisibleState();
                application->setSuspendFlag(true);
                return true;
            }
            // long press of '0' key is translated to '+'
            else if (inputEvent.is(KeyCode::KEY_0)) {
                return app::prepareCall(application, "+");
            }
        }
        else if (inputEvent.is(KeyCode::KEY_RF)) {

        if (inputEvent.is(KeyCode::KEY_RF)) {
            application->switchWindow("PowerOffWindow");
            return true;
        }
        // long press of '0' key is translated to '+'
        else if (inputEvent.is(KeyCode::KEY_0)) {
            return app::prepareCall(application, "+");
        }
        // check if any of the lower inheritance onInput methods catch the event
        return AppWindow::onInput(inputEvent);
    }


@@ 195,18 198,16 @@ namespace gui
        if (enter_cache.cached() && inputEvent.is(KeyCode::KEY_PND)) {
            // if interval between enter and pnd keys is less than time defined for unlocking
            // display pin lock screen or simply refresh current window to update labels
            std::unique_ptr<LockPhoneData> data = std::make_unique<LockPhoneData>(LockPhoneData::Request::Pin);
            // if there was no application on to before closing proceed normally to pin protection
            if (lockTimeoutApplilcation.empty()) {
                application->switchWindow(app::window::name::desktop_pin_lock, std::move(data));
                return true;
            }
            else {
                data->setPrevApplication(lockTimeoutApplilcation);
                lockTimeoutApplilcation = "";
                application->switchWindow(app::window::name::desktop_pin_lock, std::move(data));

            auto lock = getScreenLock();
            // if there is no pin,
            if (lock->getMaxPinSize() == 0) {
                lock->verify();
                return true;
            }

            switchToPinLockWindow(std::move(lock));
            return true;
        }
        else if (enter_cache.storeEnter(inputEvent)) {
            return true;


@@ 227,7 228,7 @@ namespace gui
            return processLongPressEvent(inputEvent);
        }
        else if (inputEvent.isShortPress()) {
            if (app->lockHandler.lock.isLocked()) {
            if (app->lockHandler.isScreenLocked()) {
                return processShortPressEventOnLocked(inputEvent);
            }
            else {


@@ 343,4 344,39 @@ namespace gui
        assert(app);
        return app;
    }

    auto DesktopMainWindow::getScreenLock() -> std::unique_ptr<PinLock>
    {
        auto lock = std::make_unique<PinLock>(getAppDesktop()->lockHandler.screenLock);
        auto app  = getAppDesktop();
        if (lock->getState() == PinLock::LockState::PasscodeRequired) {
            lock->onActivatedCallback = [app](const std::vector<unsigned int> &data) {
                app->lockHandler.handleScreenPin(data);
                app->switchWindow(app::window::name::desktop_main_window, ShowMode::GUI_SHOW_RETURN);
            };
        }
        else if (lock->getState() == PinLock::LockState::PasscodeInvalidRetryRequired) {
            lock->onActivatedCallback = [app](const std::vector<unsigned int> &) {
                app->lockHandler.screenLock.consumeState();
                app->switchWindow(app::window::name::desktop_main_window, ShowMode::GUI_SHOW_RETURN);
            };
        }
        else if (lock->getState() == PinLock::LockState::Blocked) {
            lock->onActivatedCallback = [app](const std::vector<unsigned int> &) {
                app->switchWindow(app::window::name::desktop_main_window, ShowMode::GUI_SHOW_INIT);
            };
        }
        return lock;
    }

    void DesktopMainWindow::switchToPinLockWindow(std::unique_ptr<PinLock> &&lock)
    {
        auto data = std::make_unique<LockPhoneData>(std::move(lock));
        if (!lockTimeoutApplilcation.empty()) {
            // if there was no application on to before closing proceed normally to pin protection
            data->setPrevApplication(lockTimeoutApplilcation);
            lockTimeoutApplilcation.clear();
        }
        application->switchWindow(app::window::name::desktop_pin_lock, std::move(data));
    }
} /* namespace gui */

M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +4 -0
@@ 17,6 17,7 @@ namespace app
namespace gui
{
    class NotificationsBox;
    class PinLock;

    class DesktopMainWindow : public AppWindow
    {


@@ 69,6 70,9 @@ namespace gui
        bool processLongPressEvent(const InputEvent &inputEvent);
        bool processShortPressEventOnUnlocked(const InputEvent &inputEvent);
        bool processShortPressEventOnLocked(const InputEvent &inputEvent);

        auto getScreenLock() -> std::unique_ptr<PinLock>;
        void switchToPinLockWindow(std::unique_ptr<PinLock> &&data);
        app::ApplicationDesktop *getAppDesktop() const;

      public:

M module-apps/application-desktop/windows/PinLockBaseWindow.cpp => module-apps/application-desktop/windows/PinLockBaseWindow.cpp +14 -16
@@ 47,24 47,28 @@ namespace gui
        infoText->setVisible(true);
        infoText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
    }
    void PinLockBaseWindow::buildPinLabels(gui::Label *labelsBox, unsigned int pinSize, unsigned int singleLabelWidth)
    void PinLockBaseWindow::buildPinLabels(std::function<Rect *()> itemBuilder,
                                           unsigned int pinSize,
                                           unsigned int offsetX,
                                           unsigned int offsetY,
                                           unsigned int boxWidth)
    {
        if (pinSize * singleLabelWidth > labelsBox->getWidth()) {
            singleLabelWidth = labelsBox->getWidth() / pinSize;
        pinLabelsBox = new gui::HBox(this, offsetX, offsetY, boxWidth, lock_style::label_size);
        pinLabelsBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

        if (pinSize == 0) {
            return;
        }
        const uint32_t pinLabelSpacing = (labelsBox->getWidth() - pinSize * singleLabelWidth) / (pinSize - 1);

        uint32_t pinLabelX = 0;
        for (uint32_t i = 0; i < pinSize; i++) {
            gui::Label *label = new gui::Label(labelsBox, pinLabelX, 0, singleLabelWidth, lock_style::label_size);
            auto label = itemBuilder();
            label->setFilled(false);
            label->setBorderColor(gui::ColorFullBlack);
            label->setPenWidth(2);
            label->setFont(style::window::font::largelight);
            label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Bottom));
            label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
            label->setVisible(true);
            this->pinLabels.push_back(label);
            pinLabelX += singleLabelWidth + pinLabelSpacing;
            label->activeItem = false;
            pinLabelsBox->addWidget(label);
        }
    }
    void PinLockBaseWindow::buildImages(const std::string &lockImg, const std::string &infoImg)


@@ 88,10 92,4 @@ namespace gui
    {
        bottomBar->setText(side, txt, false);
    }
    void PinLockBaseWindow::clearPinLabels()
    {
        for (auto label : pinLabels) {
            label->clear();
        }
    }
} // namespace gui

M module-apps/application-desktop/windows/PinLockBaseWindow.hpp => module-apps/application-desktop/windows/PinLockBaseWindow.hpp +8 -6
@@ 16,25 16,27 @@ namespace gui
    class PinLockBaseWindow : public AppWindow
    {
      public:
        PinLockBaseWindow(app::Application *app, std::string name, PinLock &lock) : AppWindow(app, name), lock(lock)
        PinLockBaseWindow(app::Application *app, std::string name) : AppWindow(app, name)
        {}
        void build();
        void buildInfoText(unsigned int textHight);
        void buildPinLabels(gui::Label *labelBox, unsigned int pinSize, unsigned int singleLabelWidth);
        void buildPinLabels(std::function<Rect *()> itemBuilder,
                            unsigned int pinSize,
                            unsigned int offsetX,
                            unsigned int offsetY,
                            unsigned int boxWidth);
        void buildImages(const std::string &lockImg, const std::string &infoImg);
        void setBottomBarWidgetsActive(bool left, bool center, bool right);
        void setImagesVisible(bool lockImg, bool infoImg);
        void setBottomBarWidgetText(BottomBar::Side side, const UTF8 &txt);
        void clearPinLabels();

        gui::Label *titleLabel = nullptr;
        gui::Text *infoText    = nullptr;
        gui::Label *pinLabel   = nullptr;
        std::vector<gui::Label *> pinLabels;
        gui::Image *lockImage = nullptr;
        gui::Image *infoImage = nullptr;
        gui::HBox *pinLabelsBox = nullptr;

        PinLock &lock;
        std::unique_ptr<PinLock> lock = nullptr;

      private:
        void buildBottomBar();

M module-apps/application-desktop/windows/PinLockBox.hpp => module-apps/application-desktop/windows/PinLockBox.hpp +19 -4
@@ 10,12 10,27 @@ namespace gui
    class PinLockBox
    {
      public:
        virtual void popChar(uint32_t charNum) = 0;
        virtual void putChar(uint32_t charNum) = 0;
        enum class EnterPasscodeType
        {
            ProvidePasscode,
            ProvideNewPasscode,
            ConfirmNewPasscode
        };

        virtual void setVisibleStateEnterPin()    = 0;
        enum class PasscodeErrorType
        {
            InvalidPasscode,
            NewPasscodeConfirmFailed,
            UnhandledError
        };

        virtual void popChar(unsigned int charNum) = 0;
        virtual void putChar(unsigned int charNum) = 0;
        virtual void clear()                       = 0;

        virtual void setVisibleStateEnterPin(EnterPasscodeType type)                       = 0;
        virtual void setVisibleStateVerifiedPin() = 0;
        virtual void setVisibleStateInvalidPin()  = 0;
        virtual void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) = 0;
        virtual void setVisibleStateBlocked()     = 0;

        virtual void buildLockBox(unsigned int pinSize) = 0;

M module-apps/application-desktop/windows/PinLockWindow.cpp => module-apps/application-desktop/windows/PinLockWindow.cpp +85 -55
@@ 19,8 19,8 @@
namespace gui
{

    PinLockWindow::PinLockWindow(app::Application *app, const std::string &window_name, PinLock &lock)
        : PinLockBaseWindow(app, window_name, lock), this_window_name(window_name)
    PinLockWindow::PinLockWindow(app::Application *app, const std::string &window_name)
        : PinLockBaseWindow(app, window_name), this_window_name(window_name)
    {
        buildInterface();
    }


@@ 32,14 32,11 @@ namespace gui
        buildInterface();
        // set state
        focusItem = nullptr;
        setVisibleState(lock.getState());
    }
    void PinLockWindow::buildInterface()
    {
        AppWindow::buildInterface();
        PinLockBaseWindow::build();
        buildPinLockBox();
        LockBox->buildLockBox(lock.getPinSize());
    }

    void PinLockWindow::destroyInterface()


@@ 54,94 51,127 @@ namespace gui
        lockImage  = nullptr;
        infoImage  = nullptr;
        infoText   = nullptr;
        pinLabel   = nullptr;
        pinLabels.clear();
        pinLabelsBox = nullptr;
    }

    void PinLockWindow::setVisibleState(const PinLock::State state)
    void PinLockWindow::setVisibleState(const PinLock::LockState state)
    {
        if (state == PinLock::State::EnterPin) {
            LockBox->setVisibleStateEnterPin();
        if (state == PinLock::LockState::PasscodeRequired) {
            currentPasscodeType = PinLockBox::EnterPasscodeType::ProvidePasscode;
            LockBox->setVisibleStateEnterPin(currentPasscodeType);
        }
        else if (state == PinLock::State::VerifiedPin) {
            LockBox->setVisibleStateVerifiedPin();
        else if (state == PinLock::LockState::PasscodeInvalidRetryRequired) {
            LockBox->setVisibleStateInvalidPin(PinLockBox::PasscodeErrorType::InvalidPasscode, lock->getValue());
        }
        else if (state == PinLock::State::InvalidPin) {
            LockBox->setVisibleStateInvalidPin();
        }
        else if (state == PinLock::State::Blocked) {
        else if (state == PinLock::LockState::Blocked) {
            LockBox->setVisibleStateBlocked();
        }
        else if (state == PinLock::LockState::NewPasscodeRequired) {
            LockBox->setVisibleStateEnterPin(currentPasscodeType);
        }
        else if (state == PinLock::LockState::NewPasscodeInvalid) {
            LockBox->setVisibleStateInvalidPin(PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed,
                                               lock->getValue());
        }
        else if (state == PinLock::LockState::ErrorOccurred) {
            LockBox->setVisibleStateInvalidPin(PinLockBox::PasscodeErrorType::UnhandledError, lock->getValue());
        }
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
    }

    void PinLockWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (mode == ShowMode::GUI_SHOW_INIT) {
            rebuild();
        }
        if (auto lockData = dynamic_cast<LockPhoneData *>(data)) {
            assert(lockData);
            lockTimeoutApplication = lockData->getPreviousApplication();
            lock                   = lockData->getLock();
            assert(lock);

            buildPinLockBox();
            LockBox->buildLockBox(lock->getMaxPinSize());

            auto state = lock->getState();
            if (state == PinLock::LockState::PasscodeRequired) {
                currentPasscodeType = PinLockBox::EnterPasscodeType::ProvidePasscode;
            }
            else if (state == PinLock::LockState::NewPasscodeRequired) {
                currentPasscodeType = PinLockBox::EnterPasscodeType::ProvideNewPasscode;
            }
            setVisibleState(lock->getState());
        }
        if (lock.unlock()) {
            setVisibleState(PinLock::State::VerifiedPin);
            application->switchWindow(gui::name::window::main_window);
        }
        setVisibleState(lock.getState());
    }

    bool PinLockWindow::onInput(const InputEvent &inputEvent)
    {
        auto state = lock.getState();
        if (!inputEvent.isShortPress() || state == PinLock::State::VerifiedPin) {
        auto state = lock->getState();
        if (!inputEvent.isShortPress()) {
            return AppWindow::onInput(inputEvent);
        }
        // accept only LF, enter, RF, #, and numeric values;
        if (inputEvent.keyCode == KeyCode::KEY_LF && bottomBar->isActive(BottomBar::Side::LEFT)) {
        if (inputEvent.is(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
            app::manager::Controller::switchApplication(
                application, app::name_phonebook, gui::window::name::ice_contacts, nullptr);
            return true;
        }
        else if (inputEvent.keyCode == KeyCode::KEY_RF && bottomBar->isActive(BottomBar::Side::RIGHT)) {
            if (state == PinLock::State::EnterPin) {
                lock.clearAttempt();
                clearPinLabels();
        else if (inputEvent.is(KeyCode::KEY_RF) && bottomBar->isActive(BottomBar::Side::RIGHT)) {
            if (state == PinLock::LockState::PasscodeRequired || state == PinLock::LockState::NewPasscodeRequired) {
                lock->clearAttempt();
            }
            else if (state == PinLock::State::InvalidPin) {
                LockBox->setVisibleStateInvalidPin();
                lock.consumeInvalidPinState();
            else if (state == PinLock::LockState::PasscodeInvalidRetryRequired) {
                lock->consumeState();
            }
            application->switchWindow(gui::name::window::main_window);
            return true;
        }
        else if (inputEvent.keyCode == KeyCode::KEY_PND) {
            if (state == PinLock::State::EnterPin) {
                lock.popChar();
                LockBox->popChar(lock.getCharCount());
        else if (inputEvent.is(KeyCode::KEY_PND)) {
            if (state == PinLock::LockState::PasscodeRequired || state == PinLock::LockState::NewPasscodeRequired) {
                lock->popChar();
                LockBox->popChar(lock->getCharCount());
                bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify());
                return true;
            }
        }
        else if (0 <= gui::toNumeric(inputEvent.keyCode) && gui::toNumeric(inputEvent.keyCode) <= 9) {
            if (state == PinLock::State::EnterPin && lock.canPut()) {
                LockBox->putChar(lock.getCharCount());
                lock.putNextChar(gui::toNumeric(inputEvent.keyCode));
                if (lock.getLockType() == PinLock::LockType::Screen) {
                    lock.verifyPin();
                }
                else if (!lock.canPut()) {
                    bottomBar->setActive(BottomBar::Side::CENTER, true);
                }
            if ((state == PinLock::LockState::PasscodeRequired || state == PinLock::LockState::NewPasscodeRequired) &&
                lock->canPut()) {
                LockBox->putChar(lock->getCharCount());
                lock->putNextChar(gui::toNumeric(inputEvent.keyCode));
                bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify());
                return true;
            }
        }
        else if (inputEvent.keyCode == KeyCode::KEY_ENTER && bottomBar->isActive(BottomBar::Side::CENTER)) {
            if (state == PinLock::State::InvalidPin) {
                lock.consumeInvalidPinState();
                application->switchWindow(this_window_name);
        else if (inputEvent.is(KeyCode::KEY_ENTER) && bottomBar->isActive(BottomBar::Side::CENTER)) {
            if (state == PinLock::LockState::NewPasscodeInvalid) {
                lock->consumeState();
                setVisibleState(lock->getState());
                return true;
            }
            else if (state == PinLock::State::EnterPin) {
                lock.verifyPin();
            else if (currentPasscodeType == PinLockBox::EnterPasscodeType::ProvideNewPasscode) {
                buffer = lock->getPin();
                lock->clearAttempt();
                LockBox->clear();

                currentPasscodeType = PinLockBox::EnterPasscodeType::ConfirmNewPasscode;
                setVisibleState(lock->getState());
                return true;
            }
            else if (state == PinLock::State::Blocked) {
                application->switchWindow(gui::name::window::main_window);
            else if (currentPasscodeType == PinLockBox::EnterPasscodeType::ConfirmNewPasscode) {
                if (buffer == lock->getPin()) {
                    lock->verify();
                }
                else {
                    currentPasscodeType = PinLockBox::EnterPasscodeType::ProvideNewPasscode;
                    lock->clearAttempt();
                    lock->setNewPasscodeInvalidState();
                    LockBox->clear();
                    setVisibleState(lock->getState());
                }
                return true;
            }
            lock->verify();
            return true;
        }
        // check if any of the lower inheritance onInput methods catch the event


@@ 150,14 180,14 @@ namespace gui

    void PinLockWindow::buildPinLockBox()
    {
        auto lockType = lock.getLockType();
        auto lockType = lock->getLockType();
        if (lockType == PinLock::LockType::Screen) {
            LockBox = std::make_unique<ScreenLockBox>(this);
        }
        else if (lockType == PinLock::LockType::PUK) {
        else if (lockType == PinLock::LockType::SimPuk) {
            LockBox = std::make_unique<PukLockBox>(this);
        }
        else if (lockType == PinLock::LockType::SIM) {
        else if (lockType == PinLock::LockType::SimPin) {
            LockBox = std::make_unique<SimLockBox>(this);
        }
        assert(LockBox != nullptr);

M module-apps/application-desktop/windows/PinLockWindow.hpp => module-apps/application-desktop/windows/PinLockWindow.hpp +6 -3
@@ 19,15 19,18 @@ namespace gui
        const std::string this_window_name;
        std::string lockTimeoutApplication  = "";
        std::unique_ptr<PinLockBox> LockBox = nullptr;
        PinLock::LockType currentLock       = PinLock::LockType::Unknown;
        PinLockBox::EnterPasscodeType currentPasscodeType = PinLockBox::EnterPasscodeType::ProvidePasscode;

        std::vector<unsigned int> buffer;
        std::function<void(const std::vector<unsigned int> &)> callbackBuffer = nullptr;

        // method hides or show widgets and sets bars according to provided state
        void setVisibleState(const PinLock::State state);
        void setVisibleState(const PinLock::LockState state);
        void buildPinLockBox();
        void invalidate() noexcept;

      public:
        PinLockWindow(app::Application *app, const std::string &window_name, PinLock &lock);
        PinLockWindow(app::Application *app, const std::string &window_name);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const InputEvent &inputEvent) override;


M module-apps/application-desktop/windows/PukLockBox.cpp => module-apps/application-desktop/windows/PukLockBox.cpp +74 -45
@@ 15,42 15,58 @@ namespace lock_style = style::window::pin_lock;

namespace gui
{
    void PukLockBox::popChar(uint32_t charNum)
    void PukLockBox::popChar(unsigned int charNum)
    {
        LockWindow->pinLabels[charNum]->clear();
        rebuildPinLabels(charNum);
    }
    void PukLockBox::putChar(uint32_t charNum)
    void PukLockBox::putChar(unsigned int charNum)
    {
        LockWindow->pinLabels[charNum]->setText("*");
        rebuildPinLabels(++charNum);
    }
    void PukLockBox::buildLockBox(unsigned int pinSize)
    {
        LockWindow->buildImages("pin_lock", "pin_lock_info");
        LockWindow->buildInfoText(lock_style::info_text_h_puk);
        buildPinLabels(pinSize);
        buildPinLabels(0);
    }
    void PukLockBox::buildPinLabels(unsigned int pinSize)
    {
        // labels with stars for displaying entered digits
        const uint32_t pinLabelWidth = style::window_width - 2 * lock_style::pin_label_x;
        LockWindow->pinLabel         = new gui::Label(
            LockWindow, lock_style::pin_label_x, lock_style::pin_label_y, pinLabelWidth, lock_style::label_size);
        LockWindow->pinLabel->setEdges(RectangleEdge::Bottom);

        LockWindow->buildPinLabels(LockWindow->pinLabel, pinSize, lock_style::label_size);
        for (auto label : LockWindow->pinLabels) {
            label->setEdges(RectangleEdge::None);
        }
        auto itemBuilder = []() {
            auto label = new gui::Image("dot_12px_hard_alpha_W_G");
            return label;
        };

        LockWindow->buildPinLabels(itemBuilder,
                                   pinSize,
                                   lock_style::pin_label_x,
                                   lock_style::pin_label_y,
                                   style::window_width - 2 * lock_style::pin_label_x);
        LockWindow->pinLabelsBox->setEdges(RectangleEdge::Bottom);
    }
    void PukLockBox::setVisibleStateEnterPin()

    void PukLockBox::rebuildPinLabels(unsigned int pinSize)
    {
        LockWindow->clearPinLabels();
        LockWindow->pinLabel->setVisible(true);
        LockWindow->pinLabelsBox->erase();
        buildPinLabels(pinSize);
    }

    void PukLockBox::setVisibleStateEnterPin(EnterPasscodeType type)
    {
        LockWindow->pinLabelsBox->setVisible(true);
        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_blocked"));
        LockWindow->infoText->addText("\n");
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_puk"));

        switch (type) {
        case PinLockBox::EnterPasscodeType::ProvidePasscode:
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_blocked"));
            LockWindow->infoText->addText("\n");
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_puk"));
            break;
        case PinLockBox::EnterPasscodeType::ProvideNewPasscode:
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_enter_pin"));
            break;
        case PinLockBox::EnterPasscodeType::ConfirmNewPasscode:
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_confirm_pin"));
        }
        LockWindow->infoText->setVisible(true);

        LockWindow->setImagesVisible(true, false);


@@ 58,43 74,52 @@ namespace gui
    }
    void PukLockBox::setVisibleStateVerifiedPin()
    {
        LockWindow->clearPinLabels();
        LockWindow->pinLabel->setVisible(false);
        LockWindow->pinLabelsBox->setVisible(false);
        LockWindow->infoText->setVisible(false);
    }
    void PukLockBox::setVisibleStateInvalidPin()
    void PukLockBox::setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value)
    {
        LockWindow->clearPinLabels();
        LockWindow->pinLabel->setVisible(false);

        LockWindow->pinLabelsBox->setVisible(false);
        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_wrong_puk"));
        LockWindow->infoText->addText("\n");
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_you_have"));
        LockWindow->infoText->addText(" ");
        LockWindow->infoText->addText(std::to_string(LockWindow->lock.getRemainingAttempts()));
        LockWindow->infoText->addText(" ");

        if (LockWindow->lock.getRemainingAttempts() > 1) {
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural"));
        }
        else {
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular"));
            LockWindow->infoText->addText("\n\n");
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning1"));
            LockWindow->infoText->addText("\n");
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning2"));
        switch (type) {
        case PinLockBox::PasscodeErrorType::InvalidPasscode:

            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_wrong_puk"));
            LockWindow->infoText->addText("\n");
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning3"));
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_you_have"));
            LockWindow->infoText->addText(" ");
            LockWindow->infoText->addText(std::to_string(value));
            LockWindow->infoText->addText(" ");

            if (value > 1) {
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural"));
            }
            else {
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular"));
                LockWindow->infoText->addText("\n\n");
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning1"));
                LockWindow->infoText->addText("\n");
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning2"));
                LockWindow->infoText->addText("\n");
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning3"));
            }
            break;
        case PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed:
            LockWindow->infoText->setText(utils::localize.get("app_desktop_sim_wrong_pin"));
            break;
        case PinLockBox::PasscodeErrorType::UnhandledError:
            LOG_ERROR("No use case for UnhandledError in PukLockBox");
            break;
        }
        LockWindow->infoText->setVisible(true);

        LockWindow->infoText->setVisible(true);
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(true, true, false);
    }
    void PukLockBox::setVisibleStateBlocked()
    {
        LockWindow->pinLabel->setVisible(false);
        LockWindow->pinLabelsBox->setVisible(false);

        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_blocked_info1"));


@@ 106,4 131,8 @@ namespace gui
        LockWindow->setBottomBarWidgetsActive(true, false, false);
    }

    void PukLockBox::clear()
    {
        rebuildPinLabels(0);
    }
} // namespace gui

M module-apps/application-desktop/windows/PukLockBox.hpp => module-apps/application-desktop/windows/PukLockBox.hpp +9 -8
@@ 4,7 4,6 @@
#pragma once

#include "PinLockBox.hpp"
#include "Label.hpp"

namespace gui
{


@@ 21,15 20,17 @@ namespace gui

      private:
        PinLockBaseWindow *LockWindow;
        void popChar(uint32_t charNum) override final;
        void putChar(uint32_t charNum) override final;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;
        virtual void clear() final;

        void setVisibleStateEnterPin() override final;
        void setVisibleStateVerifiedPin() override final;
        void setVisibleStateInvalidPin() override final;
        void setVisibleStateBlocked() override final;
        void setVisibleStateEnterPin(EnterPasscodeType type) final;
        void setVisibleStateVerifiedPin() final;
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final;
        void setVisibleStateBlocked() final;

        void buildLockBox(unsigned int pinSize) override final;
        void buildLockBox(unsigned int pinSize) final;
        void buildPinLabels(unsigned int pinSize);
        void rebuildPinLabels(unsigned int pinSize);
    };
} // namespace gui

M module-apps/application-desktop/windows/ScreenLockBox.cpp => module-apps/application-desktop/windows/ScreenLockBox.cpp +83 -28
@@ 14,13 14,34 @@ namespace lock_style = style::window::pin_lock;

namespace gui
{
    void ScreenLockBox::popChar(uint32_t charNum)

    ScreenLockBox::PinLabel::PinLabel(Item *parent, uint32_t w, uint32_t h) : HBox(parent, 0, 0, w, h)
    {}
    void ScreenLockBox::PinLabel::setVisibleState(bool isImageVisible)
    {
        LockWindow->pinLabels[charNum]->clear();
        if (isImageVisible && image == nullptr) {
            image = new gui::Image("dot_12px_hard_alpha_W_G");
            image->setVisible(true);
            image->activeItem = false;
            addWidget(image);
        }
        else if (!isImageVisible && image != nullptr) {
            erase(image);
            image = nullptr;
        }
    }
    void ScreenLockBox::putChar(uint32_t charNum)

    void ScreenLockBox::popChar(unsigned int charNum)
    {
        LockWindow->pinLabels[charNum]->setText("*");
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(false);
        }
    }
    void ScreenLockBox::putChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(true);
        }
    }
    void ScreenLockBox::buildLockBox(unsigned int pinSize)
    {


@@ 30,20 51,35 @@ namespace gui
    }
    void ScreenLockBox::buildPinLabels(unsigned int pinSize)
    {
        // labels with stars for displaying entered digits
        const uint32_t pinLabelWidth = style::window_width - 2 * lock_style::pin_label_x_screen;
        LockWindow->pinLabel         = new gui::Label(
            LockWindow, lock_style::pin_label_x_screen, lock_style::pin_label_y, pinLabelWidth, lock_style::label_size);
        LockWindow->pinLabel->setEdges(RectangleEdge::None);

        LockWindow->buildPinLabels(LockWindow->pinLabel, pinSize, lock_style::label_size_screen);
        for (auto label : LockWindow->pinLabels) {
            label->setEdges(RectangleEdge::Bottom);
        constexpr auto pinLabelWidth = style::window::default_body_width;
        pinLabels.clear();

        if (pinSize == 0) {
            return;
        }

        unsigned int singleLabelWidth        = lock_style::label_size;
        unsigned int maxNoMarginsLabelsWidth = pinLabelWidth - pinSize * 2 * lock_style::label_margins;

        if (pinSize * singleLabelWidth > maxNoMarginsLabelsWidth) {
            singleLabelWidth = maxNoMarginsLabelsWidth / pinSize;
        }

        auto itemBuilder = [this, singleLabelWidth]() {
            auto label = new PinLabel(nullptr, singleLabelWidth, lock_style::label_size);
            label->setEdges(RectangleEdge::Bottom);
            label->setMargins(Margins(lock_style::label_margins, 0, lock_style::label_margins, 0));
            pinLabels.push_back(label);
            return label;
        };

        LockWindow->buildPinLabels(
            itemBuilder, pinSize, style::window::default_left_margin, lock_style::pin_label_y_screen, pinLabelWidth);
        LockWindow->pinLabelsBox->setEdges(RectangleEdge::None);
    }
    void ScreenLockBox::setVisibleStateEnterPin()
    void ScreenLockBox::setVisibleStateEnterPin(EnterPasscodeType type)
    {
        LockWindow->pinLabel->setVisible(true);
        LockWindow->pinLabelsBox->setVisible(true);

        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get("app_desktop_screen_enter_passcode"));


@@ 54,30 90,42 @@ namespace gui
    }
    void ScreenLockBox::setVisibleStateVerifiedPin()
    {
        LockWindow->clearPinLabels();
        LockWindow->pinLabel->setVisible(false);
        clear();
        LockWindow->pinLabelsBox->setVisible(false);
        LockWindow->titleLabel->setVisible(false);
    }
    void ScreenLockBox::setVisibleStateInvalidPin()
    void ScreenLockBox::setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value)
    {
        LockWindow->clearPinLabels();
        LockWindow->pinLabel->setVisible(false);

        clear();
        LockWindow->pinLabelsBox->setVisible(false);
        LockWindow->infoText->clear();
        LockWindow->titleLabel->setVisible(true);
        LockWindow->titleLabel->setText(utils::localize.get("app_desktop_screen_wrong_pin"));
        switch (type) {
        case PinLockBox::PasscodeErrorType::InvalidPasscode:
            LockWindow->titleLabel->setText(utils::localize.get("app_desktop_screen_wrong_pin"));

        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_screen_allowed_attempts")));
        LockWindow->infoText->addText("\n");
        LockWindow->infoText->addText(std::to_string(LockWindow->lock.getRemainingAttempts()));
        LockWindow->infoText->setVisible(true);
            LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_you_have")));
            LockWindow->infoText->addText(" ");
            LockWindow->infoText->addText(std::to_string(value));
            LockWindow->infoText->addText(" ");
            LockWindow->infoText->addText(
                utils::localize.get(utils::localize.get("app_desktop_sim_attempt_left_plural")));
            break;
        case PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed:
            LockWindow->titleLabel->setText(utils::localize.get("app_desktop_screen_wrong_passcode"));
            break;
        case PinLockBox::PasscodeErrorType::UnhandledError:
            LOG_ERROR("No use case for UnhandledError");
            break;
        }

        LockWindow->infoText->setVisible(true);
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, true);
    }
    void ScreenLockBox::setVisibleStateBlocked()
    {
        LockWindow->pinLabel->setVisible(false);
        LockWindow->pinLabelsBox->setVisible(false);
        LockWindow->titleLabel->setVisible(false);

        LockWindow->infoText->clear();


@@ 87,4 135,11 @@ namespace gui
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, false);
    }

    void ScreenLockBox::clear()
    {
        for (unsigned i = 0; i < pinLabels.size(); i++) {
            popChar(i);
        }
    }
} // namespace gui

M module-apps/application-desktop/windows/ScreenLockBox.hpp => module-apps/application-desktop/windows/ScreenLockBox.hpp +19 -9
@@ 4,8 4,8 @@
#pragma once

#include "PinLockBox.hpp"
#include "Label.hpp"

#include "BoxLayout.hpp"
#include "Image.hpp"
namespace gui
{
    class PinLockBaseWindow;


@@ 20,16 20,26 @@ namespace gui
        {}

      private:
        struct PinLabel : public HBox
        {
            gui::Image *image = nullptr;
            PinLabel(Item *parent, uint32_t w, uint32_t h);
            void setVisibleState(bool isImageVisible);
        };

        std::vector<PinLabel *> pinLabels;

        PinLockBaseWindow *LockWindow;
        void popChar(uint32_t charNum) override final;
        void putChar(uint32_t charNum) override final;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;
        virtual void clear() final;

        void setVisibleStateEnterPin() override final;
        void setVisibleStateVerifiedPin() override final;
        void setVisibleStateInvalidPin() override final;
        void setVisibleStateBlocked() override final;
        void setVisibleStateEnterPin(EnterPasscodeType type) final;
        void setVisibleStateVerifiedPin() final;
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final;
        void setVisibleStateBlocked() final;

        void buildLockBox(unsigned int pinSize) override final;
        void buildLockBox(unsigned int pinSize) final;
        void buildPinLabels(unsigned int pinSize);
    };
} // namespace gui

M module-apps/application-desktop/windows/SimLockBox.cpp => module-apps/application-desktop/windows/SimLockBox.cpp +80 -48
@@ 7,6 7,9 @@
#include "application-desktop/widgets/PinLock.hpp"
#include "application-desktop/data/AppDesktopStyle.hpp"
#include "gui/widgets/Label.hpp"
#include "RichTextParser.hpp"
#include "FontManager.hpp"

#include <i18/i18.hpp>
#include <Style.hpp>



@@ 15,50 18,60 @@ namespace lock_style = style::window::pin_lock;
namespace gui
{

    void SimLockBox::popChar(uint32_t charNum)
    void SimLockBox::popChar(unsigned int charNum)
    {
        LockWindow->pinLabels[charNum]->clear();
        rebuildPinLabels(charNum);
    }
    void SimLockBox::putChar(uint32_t charNum)
    void SimLockBox::putChar(unsigned int charNum)
    {
        LockWindow->pinLabels[charNum]->setText("*");
        rebuildPinLabels(++charNum);
    }

    void SimLockBox::buildLockBox(unsigned int pinSize)
    {
        LockWindow->buildImages("pin_lock", "pin_lock_info");
        LockWindow->buildInfoText(lock_style::info_text_h_sim);
        buildPinLabels(pinSize);
        buildPinLabels(0);
    }
    void SimLockBox::buildPinLabels(unsigned int pinSize)
    {
        // labels with stars for displaying entered digits
        const uint32_t pinLabelWidth = style::window_width - 2 * lock_style::pin_label_x;
        LockWindow->pinLabel         = new gui::Label(
            LockWindow, lock_style::pin_label_x, lock_style::pin_label_y, pinLabelWidth, lock_style::label_size);
        LockWindow->pinLabel->setEdges(RectangleEdge::Bottom);

        LockWindow->buildPinLabels(LockWindow->pinLabel, pinSize, lock_style::label_size);
        for (auto label : LockWindow->pinLabels) {
            label->setEdges(RectangleEdge::None);
        }
        auto itemBuilder = []() {
            auto label = new gui::Image("dot_12px_hard_alpha_W_G");
            return label;
        };

        LockWindow->buildPinLabels(itemBuilder,
                                   pinSize,
                                   lock_style::pin_label_x,
                                   lock_style::pin_label_y,
                                   style::window_width - 2 * lock_style::pin_label_x);
        LockWindow->pinLabelsBox->setEdges(RectangleEdge::Bottom);
    }
    void SimLockBox::setVisibleStateEnterPin()

    void SimLockBox::rebuildPinLabels(unsigned int pinSize)
    {
        LockWindow->pinLabel->setVisible(true);
        LockWindow->pinLabelsBox->erase();
        buildPinLabels(pinSize);
    }

    void SimLockBox::setVisibleStateEnterPin(EnterPasscodeType type)
    {
        LockWindow->pinLabelsBox->setVisible(true);
        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_to_unlock"));
        LockWindow->infoText->addText(" ");
        LockWindow->infoText->addText(LockWindow->lock.getLockInfo(PinLock::InfoName::LockName));
        LockWindow->infoText->addText(" ");
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_card"));
        LockWindow->infoText->addText("\n");
        LockWindow->infoText->addText("( ");
        LockWindow->infoText->addText(LockWindow->lock.getLockInfo(PinLock::InfoName::PhoneNum));
        LockWindow->infoText->addText(" )");
        LockWindow->infoText->addText("\n");
        LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_pin"));

        switch (type) {
        case PinLockBox::EnterPasscodeType::ProvidePasscode:
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_to_unlock"));
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_card"));
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_pin"));
            break;
        case PinLockBox::EnterPasscodeType::ProvideNewPasscode:
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_enter_pin"));
            break;
        case PinLockBox::EnterPasscodeType::ConfirmNewPasscode:
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_confirm_pin"));
            break;
        }
        LockWindow->infoText->setVisible(true);

        LockWindow->setImagesVisible(true, false);


@@ 66,37 79,51 @@ namespace gui
    }
    void SimLockBox::setVisibleStateVerifiedPin()
    {
        LockWindow->clearPinLabels();
        LockWindow->infoText->clear();
        LockWindow->infoText->setVisible(false);
        LockWindow->pinLabel->setVisible(false);
        LockWindow->pinLabelsBox->setVisible(false);
    }
    void SimLockBox::setVisibleStateInvalidPin()
    void SimLockBox::setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value)
    {
        LockWindow->clearPinLabels();
        LockWindow->pinLabel->setVisible(false);
        LockWindow->pinLabelsBox->setVisible(false);

        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_wrong_pin")));
        LockWindow->infoText->addText("\n");
        LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_you_have")));
        LockWindow->infoText->addText(" ");
        LockWindow->infoText->addText(std::to_string(LockWindow->lock.getRemainingAttempts()));
        LockWindow->infoText->addText(" ");
        if (LockWindow->lock.getRemainingAttempts() > 1) {
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural"));

        switch (type) {
        case PinLockBox::PasscodeErrorType::InvalidPasscode:
            LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_wrong_pin")));
            LockWindow->infoText->addText("\n");
            LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_you_have")));
            LockWindow->infoText->addText(" ");
            LockWindow->infoText->addText(std::to_string(value));
            LockWindow->infoText->addText(" ");
            if (value > 1) {
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural"));
            }
            else {
                LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular"));
            }
            LockWindow->infoText->setVisible(true);

            LockWindow->setImagesVisible(false, true);
            LockWindow->setBottomBarWidgetsActive(true, true, true);
            break;
        case PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed:
            LockWindow->infoText->setText(utils::localize.get("app_desktop_sim_wrong_pin"));
            break;
        case PinLockBox::PasscodeErrorType::UnhandledError: {
            TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
            text::RichTextParser rtParser;
            auto parsedText = rtParser.parse(utils::localize.get("app_desktop_sim_cme_error"), &format);
            LockWindow->infoText->setText(std::move(parsedText));
            LockWindow->infoText->addText(std::to_string(value));
            break;
        }
        else {
            LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular"));
        }
        LockWindow->infoText->setVisible(true);

        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(true, true, true);
    }
    void SimLockBox::setVisibleStateBlocked()
    {
        LockWindow->pinLabel->setVisible(false);
        LockWindow->pinLabelsBox->setVisible(false);
        LockWindow->infoText->clear();
        LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_puk_lock1")));
        LockWindow->infoText->setVisible(true);


@@ 104,4 131,9 @@ namespace gui
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(true, true, true);
    }

    void SimLockBox::clear()
    {
        rebuildPinLabels(0);
    }
} // namespace gui

M module-apps/application-desktop/windows/SimLockBox.hpp => module-apps/application-desktop/windows/SimLockBox.hpp +9 -8
@@ 4,7 4,6 @@
#pragma once

#include "PinLockBox.hpp"
#include "Label.hpp"

namespace gui
{


@@ 21,15 20,17 @@ namespace gui

      private:
        PinLockBaseWindow *LockWindow;
        void popChar(uint32_t charNum) override final;
        void putChar(uint32_t charNum) override final;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;
        virtual void clear() final;

        void setVisibleStateEnterPin() override final;
        void setVisibleStateVerifiedPin() override final;
        void setVisibleStateInvalidPin() override final;
        void setVisibleStateBlocked() override final;
        void setVisibleStateEnterPin(EnterPasscodeType type) final;
        void setVisibleStateVerifiedPin() final;
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final;
        void setVisibleStateBlocked() final;

        void buildLockBox(unsigned int pinSize) override final;
        void buildLockBox(unsigned int pinSize) final;
        void buildPinLabels(unsigned int pinSize);
        void rebuildPinLabels(unsigned int pinSize);
    };
} // namespace gui

M module-services/service-appmgr/CMakeLists.txt => module-services/service-appmgr/CMakeLists.txt +1 -0
@@ 4,6 4,7 @@ message( "${PROJECT_NAME}  ${CMAKE_CURRENT_LIST_DIR}" )
set(SOURCES
    ApplicationManifest.cpp
    Controller.cpp
    data/SimActionsParams.cpp
    model/ApplicationManager.cpp
    model/ApplicationHandle.cpp
    model/ApplicationsRegistry.cpp

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

#include <service-appmgr/data/SimActionsParams.hpp>

using namespace app::manager::actions;

PasscodeParams::PasscodeParams(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName)
    : sim{_sim}, attempts{_attempts}, passcodeName{std::move(_passcodeName)}
{}

Store::GSM::SIM PasscodeParams::getSim() const noexcept
{
    return sim;
}
unsigned int PasscodeParams::getAttempts() const noexcept
{
    return attempts;
}
const std::string &PasscodeParams::getPasscodeName() const noexcept
{
    return passcodeName;
}

SimStateParams::SimStateParams(Store::GSM::SIM _sim) : sim{_sim}
{}

Store::GSM::SIM SimStateParams::getSim() const noexcept
{
    return sim;
}

UnhandledCMEParams::UnhandledCMEParams(Store::GSM::SIM _sim, unsigned int _cmeCode) : sim{_sim}, cmeCode{_cmeCode}
{}

Store::GSM::SIM UnhandledCMEParams::getSim() const noexcept
{
    return sim;
}
unsigned int UnhandledCMEParams::getCMECode() const noexcept
{
    return cmeCode;
}

M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +19 -0
@@ 260,6 260,13 @@ namespace app::manager
            handleAction(actionMsg);
            return std::make_shared<sys::ResponseMessage>();
        });

        auto convertibleToActionHandler = [this](sys::Message *request) { return handleMessageAsAction(request); };
        connect(typeid(CellularSimRequestPinMessage), convertibleToActionHandler);
        connect(typeid(CellularSimRequestPukMessage), convertibleToActionHandler);
        connect(typeid(CellularUnlockSimMessage), convertibleToActionHandler);
        connect(typeid(CellularBlockSimMessage), convertibleToActionHandler);
        connect(typeid(CellularDisplayCMEMessage), convertibleToActionHandler);
    }

    sys::ReturnCodes ApplicationManager::SwitchPowerModeHandler(const sys::ServicePowerMode mode)


@@ 643,6 650,18 @@ namespace app::manager
        return true;
    }

    auto ApplicationManager::handleMessageAsAction(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>
    {
        auto actionMsg = dynamic_cast<manager::actions::ConvertibleToAction *>(request);
        if (!actionMsg) {
            return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Failure);
        }
        auto action = actionMsg->toAction();
        handleAction(action.get());

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

    void ApplicationManager::onPhoneLocked()
    {
#ifdef AUTO_PHONE_LOCK_ENABLED

M module-services/service-appmgr/service-appmgr/Actions.hpp => module-services/service-appmgr/service-appmgr/Actions.hpp +6 -1
@@ 24,8 24,13 @@ namespace app::manager
        {
            Launch,
            Call,
            RequestPin,
            RequestPuk,
            RequestPinChange,
            UnlockSim,
            BlockSim,
            DisplayCMEError,
            UserAction // The last enumerator in the Action enum.
                       // All user-defined actions shall have values greater than UserAction.
        };

        class ConvertibleToAction

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

#pragma once

#include <service-appmgr/service-appmgr/Actions.hpp>
#include <module-utils/common_data/EventStore.hpp>

namespace app::manager::actions
{
    /** Action parameters for
     * RequestPinAction
     * RequestPukAction
     * ChangePinAction
     */
    class PasscodeParams : public ActionParams
    {
        Store::GSM::SIM sim;
        unsigned int attempts;
        /// passcodeName stands for PIN1/PIN2 or PUK1/PUK2 type
        std::string passcodeName;

      public:
        PasscodeParams(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName);

        [[nodiscard]] Store::GSM::SIM getSim() const noexcept;
        [[nodiscard]] unsigned int getAttempts() const noexcept;
        [[nodiscard]] const std::string &getPasscodeName() const noexcept;
    };

    /** Action parameters for
     * SimUnlockedAction
     * SimBlockedAction
     */
    class SimStateParams : public ActionParams
    {
        Store::GSM::SIM sim;

      public:
        explicit SimStateParams(Store::GSM::SIM _sim);

        [[nodiscard]] Store::GSM::SIM getSim() const noexcept;
    };

    /** Action parameters for
     * UnhandledCMEError
     */
    class UnhandledCMEParams : public ActionParams
    {
        Store::GSM::SIM sim;
        unsigned int cmeCode;

      public:
        UnhandledCMEParams(Store::GSM::SIM _sim, unsigned int _cmeCode);

        [[nodiscard]] Store::GSM::SIM getSim() const noexcept;
        [[nodiscard]] unsigned int getCMECode() const noexcept;
    };
} // namespace app::manager::actions

M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +1 -1
@@ 120,6 120,7 @@ namespace app::manager
        auto handleDisplayLanguageChange(DisplayLanguageChangeRequest *msg) -> bool;
        auto handleInputLanguageChange(InputLanguageChangeRequest *msg) -> bool;
        auto handlePowerSavingModeInit() -> bool;
        auto handleMessageAsAction(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;

        void requestApplicationClose(ApplicationHandle &app, bool isCloseable);
        void onApplicationSwitch(ApplicationHandle &app,


@@ 140,7 141,6 @@ namespace app::manager
                                                   // defined in settings database application
                                                   // manager is sending signal to power manager and changing window to
                                                   // the desktop window in the blocked state.

        // Temporary solution - to be replaced with ActionsMiddleware.
        std::tuple<ApplicationName, actions::ActionId, actions::ActionParamsPtr> pendingAction;
    };

M module-services/service-cellular/service-cellular/CellularMessage.hpp => module-services/service-cellular/service-cellular/CellularMessage.hpp +170 -0
@@ 17,6 17,10 @@
#include <memory>
#include <string>

#include <service-appmgr/service-appmgr/messages/ActionRequest.hpp>
#include <service-appmgr/service-appmgr/Actions.hpp>
#include <service-appmgr/service-appmgr/data/SimActionsParams.hpp>

class CellularMessage : public sys::DataMessage
{
  public:


@@ 293,6 297,172 @@ class CellularSimVerifyPinRequestMessage : public CellularSimMessage
    std::vector<unsigned int> pukValue;
};

class CellularSimPasscodeRequest : public CellularMessage
{
  protected:
    app::manager::actions::PasscodeParams params;

    CellularSimPasscodeRequest(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName)
        : CellularMessage(MessageType::CellularSimResponse), params(_sim, _attempts, std::move(_passcodeName))
    {}
};

class CellularSimRequestPinMessage : public CellularSimPasscodeRequest,
                                     public app::manager::actions::ConvertibleToAction
{
  public:
    CellularSimRequestPinMessage(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName)
        : CellularSimPasscodeRequest(_sim, _attempts, std::move(_passcodeName))
    {}

    [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
    {
        return std::make_unique<app::manager::ActionRequest>(
            sender, app::manager::actions::RequestPin, std::make_unique<app::manager::actions::PasscodeParams>(params));
    }
};

class CellularSimRequestPukMessage : public CellularSimPasscodeRequest,
                                     public app::manager::actions::ConvertibleToAction
{
  public:
    CellularSimRequestPukMessage(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName)
        : CellularSimPasscodeRequest(_sim, _attempts, std::move(_passcodeName))
    {}

    [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
    {
        return std::make_unique<app::manager::ActionRequest>(
            sender, app::manager::actions::RequestPuk, std::make_unique<app::manager::actions::PasscodeParams>(params));
    }
};

class CellularUnlockSimMessage : public CellularMessage, public app::manager::actions::ConvertibleToAction
{
    app::manager::actions::SimStateParams params;

  public:
    CellularUnlockSimMessage(Store::GSM::SIM _sim) : CellularMessage(MessageType::CellularSimResponse), params(_sim)
    {}

    [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
    {
        return std::make_unique<app::manager::ActionRequest>(
            sender, app::manager::actions::UnlockSim, std::make_unique<app::manager::actions::SimStateParams>(params));
    }
};

class CellularBlockSimMessage : public CellularMessage, public app::manager::actions::ConvertibleToAction
{
    app::manager::actions::SimStateParams params;

  public:
    explicit CellularBlockSimMessage(Store::GSM::SIM _sim)
        : CellularMessage(MessageType::CellularSimResponse), params(_sim)
    {}

    [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
    {
        return std::make_unique<app::manager::ActionRequest>(
            sender, app::manager::actions::BlockSim, std::make_unique<app::manager::actions::SimStateParams>(params));
    }
};

class CellularDisplayCMEMessage : public CellularMessage, public app::manager::actions::ConvertibleToAction
{
    app::manager::actions::UnhandledCMEParams params;

  public:
    CellularDisplayCMEMessage(Store::GSM::SIM _sim, unsigned int _cmeCode)
        : CellularMessage(MessageType::CellularSimResponse), params(_sim, _cmeCode)
    {}

    [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
    {
        return std::make_unique<app::manager::ActionRequest>(
            sender,
            app::manager::actions::DisplayCMEError,
            std::make_unique<app::manager::actions::UnhandledCMEParams>(params));
    }
};

class CellularSimDataMessage : public CellularMessage
{
    Store::GSM::SIM sim = Store::GSM::SIM::NONE;

  public:
    explicit CellularSimDataMessage(Store::GSM::SIM _sim) : CellularMessage{MessageType::CellularSimResponse}, sim{_sim}
    {}
    [[nodiscard]] Store::GSM::SIM getSim() const noexcept
    {
        return sim;
    }
};

class CellularSimPinDataMessage : public CellularSimDataMessage
{
    std::vector<unsigned int> pinValue;

  public:
    CellularSimPinDataMessage(Store::GSM::SIM _sim, std::vector<unsigned int> _pinValue)
        : CellularSimDataMessage{_sim}, pinValue{std::move(_pinValue)}
    {}

    [[nodiscard]] const std::vector<unsigned int> &getPin() const noexcept
    {
        return pinValue;
    }
};

class CellularSimNewPinDataMessage : public CellularSimDataMessage
{
    std::vector<unsigned int> oldPin;
    std::vector<unsigned int> newPin;

  public:
    CellularSimNewPinDataMessage(Store::GSM::SIM _sim,
                                 std::vector<unsigned int> _oldPin,
                                 std::vector<unsigned int> _newPin)
        : CellularSimDataMessage{_sim}, oldPin{std::move(_oldPin)}, newPin{std::move(_newPin)}
    {}

    [[nodiscard]] const std::vector<unsigned int> &getOldPin() const noexcept
    {
        return oldPin;
    }
    [[nodiscard]] const std::vector<unsigned int> &getNewPin() const noexcept
    {
        return newPin;
    }
};

class CellularSimPukDataMessage : public CellularSimDataMessage
{
    std::vector<unsigned int> puk;
    std::vector<unsigned int> newPin;

  public:
    CellularSimPukDataMessage(Store::GSM::SIM _sim, std::vector<unsigned int> _puk, std::vector<unsigned int> _newPin)
        : CellularSimDataMessage{_sim}, puk{std::move(_puk)}, newPin{std::move(_newPin)}
    {}

    [[nodiscard]] const std::vector<unsigned int> &getPuk() const noexcept
    {
        return puk;
    }
    [[nodiscard]] const std::vector<unsigned int> &getNewPin() const noexcept
    {
        return newPin;
    }
};

class CellularSimAbortMessage : public CellularSimDataMessage
{
  public:
    explicit CellularSimAbortMessage(Store::GSM::SIM _sim) : CellularSimDataMessage{_sim}
    {}
};

class CellularGetChannelMessage : public sys::DataMessage
{
  public:

M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +1 -0
@@ 4,6 4,7 @@
#include "service-desktop/DesktopMessages.hpp"
#include "service-desktop/ServiceDesktop.hpp"
#include "service-desktop/WorkerDesktop.hpp"
#include "service-cellular/CellularMessage.hpp"
#include "endpoints/factoryReset/FactoryReset.hpp"
#include "endpoints/backup/BackupRestore.hpp"
#include "endpoints/update/UpdateMuditaOS.hpp"