~aleteoryx/muditaos

ef63ee267c78136773ed23156ad85a75e650a7b6 — Wojtek Rzepecki 4 years ago f9945cb
[EGD-5304] Add new way of system close

Unified method of closing
the system orchestrated by
system manager
65 files changed, 639 insertions(+), 158 deletions(-)

M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/ApplicationLauncher.hpp
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/ApplicationDesktop.hpp
M module-apps/application-desktop/CMakeLists.txt
A module-apps/application-desktop/presenter/PowerOffPresenter.cpp
A module-apps/application-desktop/presenter/PowerOffPresenter.hpp
M module-apps/application-desktop/windows/DeadBatteryWindow.cpp
M module-apps/application-desktop/windows/DeadBatteryWindow.hpp
A module-apps/application-desktop/windows/LogoWindow.cpp
A module-apps/application-desktop/windows/LogoWindow.hpp
M module-apps/application-desktop/windows/Names.hpp
M module-apps/application-desktop/windows/PowerOffWindow.cpp
M module-apps/application-desktop/windows/PowerOffWindow.hpp
M module-apps/application-desktop/windows/Reboot.cpp
M module-apps/application-desktop/windows/Reboot.hpp
M module-services/service-antenna/ServiceAntenna.cpp
M module-services/service-antenna/service-antenna/ServiceAntenna.hpp
M module-services/service-appmgr/model/ApplicationManager.cpp
M module-services/service-appmgr/service-appmgr/Actions.hpp
A module-services/service-appmgr/service-appmgr/messages/UserPowerDownRequest.hpp
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp
M module-services/service-audio/ServiceAudio.cpp
M module-services/service-audio/service-audio/ServiceAudio.hpp
M module-services/service-bluetooth/ServiceBluetooth.cpp
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/service-cellular/ServiceCellular.hpp
M module-services/service-db/ServiceDB.cpp
M module-services/service-db/ServiceDB.hpp
M module-services/service-db/test/test-settings/test-service-db-settings-api.cpp
M module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp
M module-services/service-desktop/ServiceDesktop.cpp
M module-services/service-desktop/endpoints/backup/BackupRestore.cpp
M module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp
M module-services/service-eink/ServiceEink.cpp
M module-services/service-eink/ServiceEink.hpp
M module-services/service-evtmgr/EventManager.cpp
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp
M module-services/service-fota/ServiceFota.cpp
M module-services/service-fota/service-fota/ServiceFota.hpp
M module-services/service-gui/ServiceGUI.cpp
M module-services/service-gui/ServiceGUI.hpp
M module-services/service-lwip/ServiceLwIP.cpp
M module-services/service-lwip/service-lwip/ServiceLwIP.hpp
M module-services/service-time/ServiceTime.cpp
M module-services/service-time/ServiceTime.hpp
M module-sys/Service/Common.hpp
M module-sys/Service/Message.cpp
M module-sys/Service/Message.hpp
M module-sys/Service/Service.cpp
M module-sys/Service/Service.hpp
M module-sys/Service/Timer.cpp
M module-sys/Service/Timer.hpp
M module-sys/SystemManager/SystemManager.cpp
M module-sys/SystemManager/SystemManager.hpp
A module-sys/SystemManager/doc/SystemCloseSequence.md
A module-sys/SystemManager/doc/system_close_procedure_brownout.puml
A module-sys/SystemManager/doc/system_close_procedure_brownout.svg
A module-sys/SystemManager/doc/system_close_procedure_user.puml
A module-sys/SystemManager/doc/system_close_procedure_user.svg
M module-sys/SystemManager/messages/SystemManagerMessage.hpp
M source/main.cpp
M module-apps/Application.cpp => module-apps/Application.cpp +4 -1
@@ 22,6 22,7 @@
#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/EVMessages.hpp>
#include <service-appmgr/service-appmgr/messages/DOMRequest.hpp>
#include <service-appmgr/messages/UserPowerDownRequest.hpp>
#include "service-gui/messages/DrawMessage.hpp" // for DrawMessage
#include "task.h"                               // for xTaskGetTic...
#include "windows/AppWindow.hpp"                // for AppWindow


@@ 158,12 159,14 @@ namespace app
            window->updateTime();

            auto message = std::make_shared<service::gui::DrawMessage>(window->buildDrawList(), mode);
            if (shutdownInProgress) {

            if (systemCloseInProgress) {
                message->setCommandType(service::gui::DrawMessage::Type::SHUTDOWN);
            }
            else if (suspendInProgress) {
                message->setCommandType(service::gui::DrawMessage::Type::SUSPEND);
            }

            bus.sendUnicast(std::move(message), service::name::gui);
        }


M module-apps/Application.hpp => module-apps/Application.hpp +7 -8
@@ 267,11 267,12 @@ namespace app
        {
            suspendInProgress = val;
        };
        /// see shutdownInProgress documentation
        virtual void setShutdownFlag()

        // Latching close system in progress flag
        virtual void setSystemCloseInProgress()
        {
            shutdownInProgress = true;
        };
            systemCloseInProgress = true;
        }

        bool setVolume(const audio::Volume &value,
                       const audio::Profile::Type &profileType,


@@ 368,10 369,8 @@ namespace app
        /// sent to gui service. If suspend is true, application manager will receive information from both eink and gui
        /// services if last rendering mesage will be processed.
        bool suspendInProgress = false;
        /// Flag defines case when display needs to be refreshed before closing the system. If flag is set to true next
        /// set of rendering commands will carry information to GUI service that system needs to be closed. After
        /// displaying the screen GUI will notify application manager to request system shutdown.
        bool shutdownInProgress = false;

        bool systemCloseInProgress = false;
        /// Storage for asynchronous tasks callbacks.
        std::unique_ptr<CallbackStorage> callbackStorage;
        friend class AsyncTask; // Async tasks need access to application internals, e.g. callback storage, to make

M module-apps/ApplicationLauncher.hpp => module-apps/ApplicationLauncher.hpp +2 -2
@@ 93,14 93,14 @@ namespace app
        {
            parent = (caller == nullptr ? "" : caller->GetName());
            handle = std::make_shared<T>(name, parent);
            return sys::SystemManager::RunService(handle, caller);
            return sys::SystemManager::RunApplication(handle, caller);
        }

        bool runBackground(sys::Service *caller) override
        {
            parent = (caller == nullptr ? "" : caller->GetName());
            handle = std::make_shared<T>(name, parent, true);
            return sys::SystemManager::RunService(handle, caller);
            return sys::SystemManager::RunApplication(handle, caller);
        }
    };


M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +16 -2
@@ 9,6 9,7 @@
#include "windows/PinLockWindow.hpp"
#include "windows/PowerOffWindow.hpp"
#include "windows/DeadBatteryWindow.hpp"
#include "windows/LogoWindow.hpp"
#include "windows/LockedInfoWindow.hpp"
#include "windows/Reboot.hpp"
#include "windows/Update.hpp"


@@ 17,6 18,7 @@
#include "windows/MmiPullWindow.hpp"
#include "windows/MmiPushWindow.hpp"
#include "windows/MmiInternalMsgWindow.hpp"
#include "presenter/PowerOffPresenter.hpp"

#include "AppWindow.hpp"
#include "data/LockPhoneData.hpp"


@@ 105,10 107,17 @@ namespace app
        });

        addActionReceiver(app::manager::actions::SystemBrownout, [this](auto &&data) {
            setSystemCloseInProgress();
            switchWindow(app::window::name::dead_battery, std::move(data));
            return actionHandled();
        });

        addActionReceiver(app::manager::actions::DisplayLogoAtExit, [this](auto &&data) {
            setSystemCloseInProgress();
            switchWindow(app::window::name::logo_window, std::move(data));
            return actionHandled();
        });

        addActionReceiver(app::manager::actions::AutoLock, [this](auto &&data) {
            if (lockHandler.isScreenLocked()) {
                return actionHandled();


@@ 401,16 410,21 @@ namespace app
            return std::make_unique<gui::MenuWindow>(app);
        });
        windowsFactory.attach(desktop_poweroff, [](Application *app, const std::string newname) {
            return std::make_unique<gui::PowerOffWindow>(app);
            auto presenter = std::make_unique<gui::PowerOffPresenter>(app);
            return std::make_unique<gui::PowerOffWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(dead_battery, [](Application *app, const std::string newname) {
            return std::make_unique<gui::DeadBatteryWindow>(app);
        });
        windowsFactory.attach(logo_window, [](Application *app, const std::string newname) {
            return std::make_unique<gui::LogoWindow>(app);
        });
        windowsFactory.attach(desktop_locked, [](Application *app, const std::string newname) {
            return std::make_unique<gui::LockedInfoWindow>(app);
        });
        windowsFactory.attach(desktop_reboot, [](Application *app, const std::string newname) {
            return std::make_unique<gui::RebootWindow>(app);
            auto presenter = std::make_unique<gui::PowerOffPresenter>(app);
            return std::make_unique<gui::RebootWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(desktop_update, [](Application *app, const std::string newname) {
            return std::make_unique<gui::UpdateWindow>(app);

M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +2 -1
@@ 123,7 123,8 @@ namespace app
                     manager::actions::ShowMMIResult,
                     manager::actions::DisplayCMEError,
                     manager::actions::DisplayLowBatteryNotification,
                     manager::actions::SystemBrownout}};
                     manager::actions::SystemBrownout,
                     manager::actions::DisplayLogoAtExit}};
        }
    };


M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +2 -0
@@ 28,6 28,7 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MenuWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PowerOffWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/DeadBatteryWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LogoWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockedInfoWindow.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/windows/Reboot.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/Update.cpp"


@@ 38,6 39,7 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiInternalMsgWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/ScreenLockBaseBox.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/presenter/PowerOffPresenter.cpp"
	PUBLIC
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationDesktop.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/LockPhoneData.hpp"

A module-apps/application-desktop/presenter/PowerOffPresenter.cpp => module-apps/application-desktop/presenter/PowerOffPresenter.cpp +19 -0
@@ 0,0 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PowerOffPresenter.hpp"
#include <module-services/service-appmgr/service-appmgr/messages/UserPowerDownRequest.hpp>
#include <module-sys/SystemManager/Constants.hpp>

namespace gui
{
    PowerOffPresenter::PowerOffPresenter(app::Application *app) : application(app)
    {}

    void PowerOffPresenter::powerOff()
    {
        auto msg = std::make_shared<app::UserPowerDownRequest>();
        application->bus.sendUnicast(std::move(msg), service::name::system_manager);
    }

} // namespace gui

A module-apps/application-desktop/presenter/PowerOffPresenter.hpp => module-apps/application-desktop/presenter/PowerOffPresenter.hpp +20 -0
@@ 0,0 1,20 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-apps/Application.hpp>

namespace gui
{
    class PowerOffPresenter
    {
      public:
        PowerOffPresenter(app::Application *app);
        void powerOff();

      private:
        app::Application *application;
    };

} // namespace gui

M module-apps/application-desktop/windows/DeadBatteryWindow.cpp => module-apps/application-desktop/windows/DeadBatteryWindow.cpp +1 -10
@@ 8,8 8,6 @@
#include "gui/widgets/TopBar.hpp"
#include "log/log.hpp"
#include <application-desktop/windows/Names.hpp>
#include <service-appmgr/model/ApplicationManager.hpp>
#include <service-appmgr/Controller.hpp>

namespace gui
{


@@ 36,18 34,11 @@ namespace gui
        AppWindow::buildInterface();
        bottomBar->setVisible(false);
        topBar->setVisible(false);

        image = new gui::Image(this, IMG_POS_X, IMG_POS_Y, 0, 0, "dead_battery_W_G");
    }

    void DeadBatteryWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        app::manager::Controller::sendAction(application, app::manager::actions::CloseSystem);
        new gui::Image(this, IMG_POS_X, IMG_POS_Y, 0, 0, "dead_battery_W_G");
    }

    void DeadBatteryWindow::destroyInterface()
    {
        erase();
        image = nullptr;
    }
} /* namespace gui */

M module-apps/application-desktop/windows/DeadBatteryWindow.hpp => module-apps/application-desktop/windows/DeadBatteryWindow.hpp +0 -4
@@ 15,10 15,6 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;

      private:
        gui::Image *image = nullptr;
    };

} /* namespace gui */

A module-apps/application-desktop/windows/LogoWindow.cpp => module-apps/application-desktop/windows/LogoWindow.cpp +36 -0
@@ 0,0 1,36 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "LogoWindow.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "log/log.hpp"
#include <application-desktop/windows/Names.hpp>

namespace gui
{
    LogoWindow::LogoWindow(app::Application *app) : AppWindow(app, app::window::name::logo_window)
    {
        buildInterface();
    }

    void LogoWindow::rebuild()
    {
        destroyInterface();
        buildInterface();
    }

    void LogoWindow::buildInterface()
    {
        AppWindow::buildInterface();
        bottomBar->setVisible(false);
        topBar->setVisible(false);
        new gui::Image(this, 0, 0, 0, 0, "logo");
    }

    void LogoWindow::destroyInterface()
    {
        erase();
    }
} /* namespace gui */

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

#pragma once

#include "AppWindow.hpp"

namespace gui
{
    class LogoWindow : public AppWindow
    {
      public:
        explicit LogoWindow(app::Application *app);
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
    };

} /* namespace gui */

M module-apps/application-desktop/windows/Names.hpp => module-apps/application-desktop/windows/Names.hpp +1 -0
@@ 11,6 11,7 @@ namespace app::window::name
    inline constexpr auto desktop_reboot             = "Reboot";
    inline constexpr auto desktop_poweroff           = "PowerOffWindow";
    inline constexpr auto dead_battery               = "DeadBatteryWindow";
    inline constexpr auto logo_window                = "LogoWindow";
    inline constexpr auto desktop_pin_lock           = "PinLockWindow";
    inline constexpr auto desktop_locked             = "LockedInfoWindow";
    inline constexpr auto desktop_update             = "Update";

M module-apps/application-desktop/windows/PowerOffWindow.cpp => module-apps/application-desktop/windows/PowerOffWindow.cpp +7 -20
@@ 10,7 10,6 @@
#include <i18n/i18n.hpp>

#include "PowerOffWindow.hpp"
#include "../ApplicationDesktop.hpp"

// services
#include <service-appmgr/model/ApplicationManager.hpp>


@@ 18,11 17,13 @@

#include "service-cellular/ServiceCellular.hpp"
#include <Style.hpp>
#include <application-desktop/windows/Names.hpp>

namespace gui
{

    PowerOffWindow::PowerOffWindow(app::Application *app) : AppWindow(app, app::window::name::desktop_poweroff)
    PowerOffWindow::PowerOffWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter)
        : AppWindow(app, app::window::name::desktop_poweroff), presenter(std::move(presenter))
    {
        buildInterface();
    }


@@ 50,8 51,6 @@ namespace gui
        bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));

        powerImage     = new gui::Image(this, 177, 132, 0, 0, "pin_lock_info");
        powerDownImage = new gui::Image(this, 0, 0, 0, 0, "logo");
        powerDownImage->setVisible(false);

        // title label
        titleLabel = new gui::Label(this, 0, 60, 480, 40);


@@ 128,21 127,10 @@ namespace gui
        };

        selectionLabels[1]->activatedCallback = [=](gui::Item &item) {
            LOG_INFO("Closing system");
            application->setShutdownFlag();

            bottomBar->setVisible(false);
            topBar->setVisible(false);
            selectionLabels[0]->setVisible(false);
            selectionLabels[1]->setVisible(false);
            eventMgrLabel->setVisible(false);
            powerImage->setVisible(false);
            powerDownImage->setVisible(true);
            titleLabel->setVisible(false);
            infoLabel->setVisible(false);

            application->refreshWindow(RefreshModes::GUI_REFRESH_DEEP);
            app::manager::Controller::sendAction(application, app::manager::actions::CloseSystem);
            LOG_INFO("User call close system");

            presenter->powerOff();

            return true;
        };



@@ 172,7 160,6 @@ namespace gui
        infoLabel      = nullptr;
        eventMgrLabel  = nullptr;
        powerImage     = nullptr;
        powerDownImage = nullptr;
        selectionLabels.clear();
    }


M module-apps/application-desktop/windows/PowerOffWindow.hpp => module-apps/application-desktop/windows/PowerOffWindow.hpp +3 -1
@@ 8,6 8,7 @@
#include "gui/widgets/Label.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "../presenter/PowerOffPresenter.hpp"

namespace gui
{


@@ 22,13 23,14 @@ namespace gui
        gui::Label *titleLabel = nullptr;
        gui::Label *infoLabel  = nullptr;

        std::unique_ptr<PowerOffPresenter> presenter;
        std::vector<gui::Label *> selectionLabels;
        gui::Label *eventMgrLabel  = nullptr;
        gui::Image *powerImage     = nullptr;
        gui::Image *powerDownImage = nullptr;
        State state                = State::Return;
      public:
        PowerOffWindow(app::Application *app);
        PowerOffWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const InputEvent &inputEvent) override;


M module-apps/application-desktop/windows/Reboot.cpp => module-apps/application-desktop/windows/Reboot.cpp +3 -7
@@ 9,7 9,8 @@
namespace gui
{

    RebootWindow::RebootWindow(app::Application *app) : AppWindow(app, app::window::name::desktop_reboot)
    RebootWindow::RebootWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter)
        : AppWindow(app, app::window::name::desktop_reboot), presenter(std::move(presenter))
    {
        buildInterface();
    }


@@ 58,12 59,7 @@ namespace gui

    bool RebootWindow::onInput(const InputEvent &inputEvent)
    {
        text->setText("!!! Shutdown !!!");
        application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        /// needed to actually have time to show stuff on screen before system close
        ulTaskNotifyTake(pdTRUE, 1000);
        // shutdown
        sys::SystemManager::CloseSystem(application);
        presenter->powerOff();
        return true;
    }


M module-apps/application-desktop/windows/Reboot.hpp => module-apps/application-desktop/windows/Reboot.hpp +3 -1
@@ 6,13 6,14 @@
#include <vector>
#include "AppWindow.hpp"
#include <Text.hpp>
#include "../presenter/PowerOffPresenter.hpp"

namespace gui
{
    class RebootWindow : public AppWindow
    {
      public:
        RebootWindow(app::Application *app);
        RebootWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter);
        ~RebootWindow() override = default;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const InputEvent &inputEvent) override;


@@ 23,6 24,7 @@ namespace gui
      private:
        void invalidate() noexcept;

        std::unique_ptr<PowerOffPresenter> presenter;
        Text *text = nullptr;
    };


M module-services/service-antenna/ServiceAntenna.cpp => module-services/service-antenna/ServiceAntenna.cpp +5 -0
@@ 175,6 175,11 @@ sys::ReturnCodes ServiceAntenna::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void ServiceAntenna::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::ReturnCodes ServiceAntenna::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
{
    LOG_FATAL("[ServiceEvtMgr] PowerModeHandler: %s", c_str(mode));

M module-services/service-antenna/service-antenna/ServiceAntenna.hpp => module-services/service-antenna/service-antenna/ServiceAntenna.hpp +2 -0
@@ 92,6 92,8 @@ class ServiceAntenna : public sys::Service

    sys::ReturnCodes DeinitHandler() override;

    void ProcessCloseReason(sys::CloseReason closeReason) override;

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

    void storeCurrentState(void);

M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +17 -25
@@ 37,10 37,7 @@ namespace app::manager
{
    namespace
    {
        constexpr auto shutdown_delay_ms               = 500;

        constexpr auto timerBlock         = "BlockTimer";
        constexpr auto timerShutdownDelay = "ShutdownDelay";
    } // namespace

    ApplicationManagerBase::ApplicationManagerBase(std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers)


@@ 111,7 108,6 @@ namespace app::manager
                                                                             this,
                                                                             std::numeric_limits<sys::ms>::max(),
                                                                             sys::Timer::Type::SingleShot)},
          shutdownDelay{std::make_unique<sys::Timer>(timerShutdownDelay, this, shutdown_delay_ms)},
          settings(std::make_unique<settings::Settings>(this)),
          phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
    {


@@ 189,10 185,25 @@ namespace app::manager
    {
        settings->unregisterValueChange();
        closeApplications();
        closeServices();
        return sys::ReturnCodes::Success;
    }

    auto ApplicationManager::ProcessCloseReason(sys::CloseReason closeReason) -> void
    {
        ActionRequest act = ActionRequest{this->GetName(), app::manager::actions::DisplayLogoAtExit, nullptr};
        switch (closeReason) {
        case sys::CloseReason::SystemBrownout:
            act = ActionRequest{this->GetName(), app::manager::actions::SystemBrownout, nullptr};
            break;
        case sys::CloseReason::RegularPowerDown:
            break;
        case sys::CloseReason::Reboot:
            break;
        }
        handleActionRequest(&act);
        sendCloseReadyMessage(this);
    }

    auto ApplicationManager::DataReceivedHandler([[maybe_unused]] sys::DataMessage *msgl,
                                                 [[maybe_unused]] sys::ResponseMessage *resp) -> sys::MessagePointer
    {


@@ 284,7 295,6 @@ namespace app::manager
        });
        connect(typeid(ShutdownRequest), [this](sys::Message *) {
            closeApplications();
            closeServices();
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(ActionRequest), [this](sys::Message *request) {


@@ 323,7 333,6 @@ namespace app::manager
        connect(typeid(CellularNoSimNotification), convertibleToActionHandler);
        connect(typeid(CellularNotAnEmergencyNotification), convertibleToActionHandler);
        connect(typeid(sys::CriticalBatteryLevelNotification), convertibleToActionHandler);
        connect(typeid(sys::SystemBrownoutMesssage), convertibleToActionHandler);
        connect(typeid(CellularSmsNoSimRequestMessage), convertibleToActionHandler);
        connect(typeid(sdesktop::passcode::ScreenPasscodeRequest), convertibleToActionHandler);
    }


@@ 360,13 369,6 @@ namespace app::manager
        return true;
    }

    auto ApplicationManager::closeServices() -> bool
    {
        closeService(service::name::gui);
        closeService(service::name::eink);
        return true;
    }

    auto ApplicationManager::closeApplications() -> bool
    {
        for (const auto &app : getApplications()) {


@@ 398,7 400,7 @@ namespace app::manager

    void ApplicationManager::closeService(const std::string &name)
    {
        bool ret = sys::SystemManager::DestroyService(name, this);
        bool ret = sys::SystemManager::DestroyApplication(name, this);
        if (ret) {
            LOG_INFO("Service/Application %s closed", name.c_str());
        }


@@ 490,8 492,6 @@ namespace app::manager
            return handleHomeAction(action);
        case actions::Launch:
            return handleLaunchAction(action);
        case actions::CloseSystem:
            return handleCloseSystem();
        default:
            return handleCustomAction(action);
        }


@@ 517,14 517,6 @@ namespace app::manager
        return handleSwitchApplication(&switchRequest);
    }

    auto ApplicationManager::handleCloseSystem() -> bool
    {
        shutdownDelay->connect([&](sys::Timer &) { sys::SystemManager::CloseSystem(this); });
        shutdownDelay->start();

        return true;
    }

    auto ApplicationManager::handleCustomAction(ActionEntry &action) -> bool
    {
        const auto actionHandlers = applications.findByAction(action.actionId);

M module-services/service-appmgr/service-appmgr/Actions.hpp => module-services/service-appmgr/service-appmgr/Actions.hpp +1 -1
@@ 25,7 25,6 @@ namespace app::manager
            Home,
            AutoLock,
            Launch,
            CloseSystem,
            Call,
            NotAnEmergencyNotification,
            NoSimNotification,


@@ 56,6 55,7 @@ namespace app::manager
            DisplayLowBatteryNotification,
            SystemBrownout,
            RequestScreenPasscode,
            DisplayLogoAtExit,
            UserAction // The last enumerator in the Action enum.
                       // All user-defined actions shall have values greater than UserAction.
                       // All system-wide actions shall have values lesser than UserAction.

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

#pragma once

#include "BaseMessage.hpp"

namespace app
{
    class UserPowerDownRequest : public sys::Message
    {};

} // namespace app

M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +1 -3
@@ 100,6 100,7 @@ namespace app::manager

        auto InitHandler() -> sys::ReturnCodes override;
        auto DeinitHandler() -> sys::ReturnCodes override;
        auto ProcessCloseReason(sys::CloseReason closeReason) -> void override;
        auto SwitchPowerModeHandler(const sys::ServicePowerMode mode) -> sys::ReturnCodes override;
        auto DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) -> sys::MessagePointer override;



@@ 108,7 109,6 @@ namespace app::manager
        void startBackgroundApplications();
        void rebuildActiveApplications();
        void suspendSystemServices();
        auto closeServices() -> bool;
        auto closeApplications() -> bool;
        auto closeApplicationsOnUpdate() -> bool;
        void closeService(const std::string &name);


@@ 120,7 120,6 @@ namespace app::manager
        void handleActionRequest(ActionRequest *actionMsg);
        auto handleHomeAction(ActionEntry &action) -> bool;
        auto handleLaunchAction(ActionEntry &action) -> bool;
        auto handleCloseSystem() -> bool;
        auto handleCustomAction(ActionEntry &action) -> bool;
        auto handleSwitchApplication(SwitchRequest *msg, bool closeCurrentlyFocusedApp = true) -> bool;
        auto handleCloseConfirmation(CloseConfirmation *msg) -> bool;


@@ 166,7 165,6 @@ namespace app::manager
                                                   // If it reaches time defined in settings database application
                                                   // manager is sending signal to Application Desktop in order to
                                                   // lock screen.
        std::unique_ptr<sys::Timer> shutdownDelay;
        std::unique_ptr<settings::Settings> settings;
        std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;
        void displayLanguageChanged(std::string value);

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +5 -0
@@ 179,6 179,11 @@ sys::ReturnCodes ServiceAudio::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void ServiceAudio::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

std::optional<std::string> ServiceAudio::AudioServicesCallback(const sys::Message *msg)
{
    if (const auto *eof = dynamic_cast<const AudioServiceMessage::EndOfFile *>(msg); eof) {

M module-services/service-audio/service-audio/ServiceAudio.hpp => module-services/service-audio/service-audio/ServiceAudio.hpp +2 -0
@@ 42,6 42,8 @@ class ServiceAudio : public sys::Service

    sys::ReturnCodes DeinitHandler() override;

    void ProcessCloseReason(sys::CloseReason closeReason) override;

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

  private:

M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +5 -0
@@ 176,6 176,11 @@ sys::ReturnCodes ServiceBluetooth::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void ServiceBluetooth::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp)
{
    try {

M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +1 -0
@@ 33,6 33,7 @@ class ServiceBluetooth : public sys::Service
    virtual sys::MessagePointer DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) override;
    sys::ReturnCodes InitHandler() override;
    sys::ReturnCodes DeinitHandler() override;
    void ProcessCloseReason(sys::CloseReason closeReason) override;
    virtual sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;
    void sendWorkerCommand(bluetooth::Command command);
    QueueHandle_t workerQueue = nullptr;

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +5 -1
@@ 270,10 270,14 @@ sys::ReturnCodes ServiceCellular::InitHandler()

sys::ReturnCodes ServiceCellular::DeinitHandler()
{

    return sys::ReturnCodes::Success;
}

void ServiceCellular::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::ReturnCodes ServiceCellular::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
{
    LOG_FATAL("[ServiceCellular] PowerModeHandler: %s", c_str(mode));

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +1 -0
@@ 72,6 72,7 @@ class ServiceCellular : public sys::Service
    // Invoked during initialization
    sys::ReturnCodes InitHandler() override;
    sys::ReturnCodes DeinitHandler() override;
    void ProcessCloseReason(sys::CloseReason closeReason) override;
    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

    /** Register message handlers.

M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +5 -0
@@ 563,6 563,11 @@ sys::ReturnCodes ServiceDB::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void ServiceDB::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::ReturnCodes ServiceDB::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
{
    LOG_FATAL("[%s] PowerModeHandler: %s", this->GetName().c_str(), c_str(mode));

M module-services/service-db/ServiceDB.hpp => module-services/service-db/ServiceDB.hpp +2 -0
@@ 89,6 89,8 @@ class ServiceDB : public sys::Service

    sys::ReturnCodes DeinitHandler() override;

    void ProcessCloseReason(sys::CloseReason closeReason) override;

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) final;

    bool StoreIntoBackup(const std::filesystem::path &backupPath);

M module-services/service-db/test/test-settings/test-service-db-settings-api.cpp => module-services/service-db/test/test-settings/test-service-db-settings-api.cpp +12 -12
@@ 52,38 52,38 @@ TEST_CASE("SettingsApi")
                testStart = std::make_shared<std::mutex>();
                testStart->lock();
                std::cout << "start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
                auto ret = sys::SystemManager::RunService(std::make_shared<EventManager>(service::name::evt_manager),
                                                          manager.get());
                ret &= sys::SystemManager::RunService(std::make_shared<ServiceDB>(), manager.get());
                auto ret = sys::SystemManager::RunSystemService(
                    std::make_shared<EventManager>(service::name::evt_manager), manager.get());
                ret &= sys::SystemManager::RunSystemService(std::make_shared<ServiceDB>(), manager.get());

                varWritter = std::make_shared<settings::MyService>("writterVar");
                varReader  = std::make_shared<settings::MyService>("readerVar");

                ret &= sys::SystemManager::RunService(varWritter, manager.get());
                ret &= sys::SystemManager::RunService(varReader, manager.get());
                ret &= sys::SystemManager::RunSystemService(varWritter, manager.get());
                ret &= sys::SystemManager::RunSystemService(varReader, manager.get());

                testVar = std::make_shared<settings::AppTest>("appTest", varWritter, varReader, testStart);
                ret &= sys::SystemManager::RunService(testVar, manager.get());
                ret &= sys::SystemManager::RunSystemService(testVar, manager.get());

                profWritter = std::make_shared<settings::ServiceProfile>("writterProf");
                profReader  = std::make_shared<settings::ServiceProfile>("readerProf");

                ret &= sys::SystemManager::RunService(profWritter, manager.get());
                ret &= sys::SystemManager::RunService(profReader, manager.get());
                ret &= sys::SystemManager::RunSystemService(profWritter, manager.get());
                ret &= sys::SystemManager::RunSystemService(profReader, manager.get());

                testProf = std::make_shared<settings::AppTestProfileMode>(
                    "appTestProfile", profWritter, profReader, testStart);
                ret &= sys::SystemManager::RunService(testProf, manager.get());
                ret &= sys::SystemManager::RunSystemService(testProf, manager.get());

                modeWritter = std::make_shared<settings::ServiceMode>("writterMode");
                modeReader  = std::make_shared<settings::ServiceMode>("readerMode");

                ret &= sys::SystemManager::RunService(modeWritter, manager.get());
                ret &= sys::SystemManager::RunService(modeReader, manager.get());
                ret &= sys::SystemManager::RunSystemService(modeWritter, manager.get());
                ret &= sys::SystemManager::RunSystemService(modeReader, manager.get());

                testMode =
                    std::make_shared<settings::AppTestProfileMode>("appTestMode", modeWritter, modeReader, testStart);
                ret &= sys::SystemManager::RunService(testMode, manager.get());
                ret &= sys::SystemManager::RunSystemService(testMode, manager.get());

                std::cout << "koniec start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
                testStart->unlock();

M module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp => module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp +16 -4
@@ 1,6 1,11 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

namespace app
{
    class UserPowerDownRequest : public sys::Message
    {};
} // namespace app
namespace settings
{
    class TestService : public sys::Service


@@ 84,7 89,7 @@ namespace settings
                testStart->lock();
                testStart->unlock();
                if (state != State::Unk) {
                    sys::SystemManager::CloseSystem(this);
                    closeSystem();
                }
                else {
                    state    = State::Start;


@@ 133,12 138,19 @@ namespace settings
            }
            else if (nullptr != dynamic_cast<settings::UTMsg::UTMsgStop *>(msg)) {
                if (state == State::Unregister) {
                    sys::SystemManager::CloseSystem(this);
                    closeSystem();
                }
            }

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

      protected:
        void closeSystem()
        {
            auto msg = std::make_shared<app::UserPowerDownRequest>();
            bus.sendUnicast(std::move(msg), service::name::system_manager);
        }
    };

    class AppTestProfileMode : public AppTest


@@ 157,7 169,7 @@ namespace settings
                testStart->lock();
                testStart->unlock();
                if (state != State::Unk) {
                    sys::SystemManager::CloseSystem(this);
                    closeSystem();
                }
                else {
                    state    = State::Start;


@@ 234,7 246,7 @@ namespace settings
            }
            else if (nullptr != dynamic_cast<settings::UTMsg::UTMsgStop *>(msg)) {
                if (state == State::RegisterAllAdd) {
                    sys::SystemManager::CloseSystem(this);
                    closeSystem();
                }
            }


M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +5 -0
@@ 236,6 236,11 @@ sys::ReturnCodes ServiceDesktop::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void ServiceDesktop::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::ReturnCodes ServiceDesktop::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
{
    return sys::ReturnCodes::Success;

M module-services/service-desktop/endpoints/backup/BackupRestore.cpp => module-services/service-desktop/endpoints/backup/BackupRestore.cpp +1 -1
@@ 137,7 137,7 @@ void BackupRestore::RestoreUserFiles(sys::Service *ownerService)
    /* close user files to be restored */
    LOG_INFO("RestoreUserFiles: closing ServiceDB...");
    std::string dbServiceName = service::name::db;
    sys::SystemManager::DestroyService(dbServiceName, ownerService);
    sys::SystemManager::DestroySystemService(dbServiceName, ownerService);

    BackupRestore::ReplaceUserFiles();


M module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp => module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp +1 -1
@@ 52,7 52,7 @@ namespace FactoryReset
        if (ownerService != nullptr) {
            LOG_INFO("FactoryReset: closing ServiceDB...");
            std::string dbServiceName = service::name::db;
            sys::SystemManager::DestroyService(dbServiceName, ownerService);
            sys::SystemManager::DestroySystemService(dbServiceName, ownerService);
        }

        if (DeleteDirContent(purefs::dir::getRootDiskPath()) != true) {

M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +1 -0
@@ 56,6 56,7 @@ class ServiceDesktop : public sys::Service

    sys::ReturnCodes InitHandler() override;
    sys::ReturnCodes DeinitHandler() override;
    void ProcessCloseReason(sys::CloseReason closeReason) override;
    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;
    sys::MessagePointer DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) override;


M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +5 -0
@@ 81,6 81,11 @@ namespace service::eink
        return sys::ReturnCodes::Success;
    }

    void ServiceEink::ProcessCloseReason(sys::CloseReason closeReason)
    {
        sendCloseReadyMessage(this);
    }

    sys::ReturnCodes ServiceEink::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
    {
        LOG_INFO("PowerModeHandler: %s", c_str(mode));

M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +1 -0
@@ 28,6 28,7 @@ namespace service::eink
        sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *response) override;
        sys::ReturnCodes InitHandler() override;
        sys::ReturnCodes DeinitHandler() override;
        void ProcessCloseReason(sys::CloseReason closeReason) override;
        sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;

      private:

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +5 -0
@@ 324,6 324,11 @@ sys::ReturnCodes EventManager::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void EventManager::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::ReturnCodes EventManager::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
{
    LOG_FATAL("[ServiceEvtMgr] PowerModeHandler: %s", c_str(mode));

M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +2 -0
@@ 63,6 63,8 @@ class EventManager : public sys::Service

    sys::ReturnCodes DeinitHandler() override;

    void ProcessCloseReason(sys::CloseReason closeReason) override;

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

    /**

M module-services/service-fota/ServiceFota.cpp => module-services/service-fota/ServiceFota.cpp +5 -0
@@ 71,6 71,11 @@ namespace FotaService
        return sys::ReturnCodes::Success;
    }

    void Service::ProcessCloseReason(sys::CloseReason closeReason)
    {
        sendCloseReadyMessage(this);
    }

    void Service::registerMessageHandlers()
    {
        LOG_DEBUG("Registring Handlers for Fota::Service:");

M module-services/service-fota/service-fota/ServiceFota.hpp => module-services/service-fota/service-fota/ServiceFota.hpp +2 -0
@@ 60,6 60,8 @@ namespace FotaService

        sys::ReturnCodes DeinitHandler() override;

        void ProcessCloseReason(sys::CloseReason closeReason) override;

        sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode /*mode*/) override final
        {
            return sys::ReturnCodes::Success;

M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +19 -8
@@ 39,7 39,7 @@ namespace service::gui
                                                                CommandsQueueCapacity)},
          contextReleaseTimer{
              std::make_unique<sys::Timer>(this, ContextReleaseTimeout.count(), sys::Timer::Type::SingleShot)},
          currentState{State::NotInitialised}
          currentState{State::NotInitialised}, lastRenderScheduled{false}, waitingForLastRender{false}
    {
        initAssetManagers();
        registerMessageHandlers();


@@ 94,6 94,11 @@ namespace service::gui
        return sys::ReturnCodes::Success;
    }

    void ServiceGUI::ProcessCloseReason(sys::CloseReason closeReason)
    {
        waitingForLastRender = true;
    }

    sys::ReturnCodes ServiceGUI::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
    {
        LOG_INFO("PowerModeHandler: %s", c_str(mode));


@@ 114,24 119,26 @@ namespace service::gui
    {
        if (isInState(State::NotInitialised)) {
            LOG_WARN("Service not yet initialised - ignoring draw commands");
            return sys::MessageNone{};
            return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
        }
        if (isInState(State::Suspended)) {
            LOG_WARN("Suspended - ignoring draw commands");
            return sys::MessageNone{};
        if (isInState(State::Suspended) || lastRenderScheduled) {
            LOG_WARN("Ignoring draw commands");
            return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
        }

        if (const auto drawMsg = static_cast<DrawMessage *>(message); !drawMsg->commands.empty()) {
            if (drawMsg->isType(DrawMessage::Type::SHUTDOWN) || drawMsg->isType(DrawMessage::Type::SUSPEND)) {
            if (drawMsg->isType(DrawMessage::Type::SUSPEND)) {
                setState(State::Suspended);
            }

            else if (drawMsg->isType(DrawMessage::Type::SHUTDOWN)) {
                lastRenderScheduled = true;
            }
            if (!isAnyFrameBeingRenderedOrDisplayed()) {
                prepareDisplayEarly(drawMsg->mode);
            }
            notifyRenderer(std::move(drawMsg->commands), drawMsg->mode);
        }
        return sys::MessageNone{};
        return std::make_shared<sys::ResponseMessage>();
    }

    sys::MessagePointer ServiceGUI::handleChangeColorScheme(sys::Message *message)


@@ 242,6 249,10 @@ namespace service::gui
        if (isNextFrameReady() and not isAnyFrameBeingRenderedOrDisplayed()) {
            trySendNextFrame();
        }
        else if (lastRenderScheduled && waitingForLastRender) {
            sendCloseReadyMessage(this);
        }

        return sys::MessageNone{};
    }


M module-services/service-gui/ServiceGUI.hpp => module-services/service-gui/ServiceGUI.hpp +3 -0
@@ 41,6 41,7 @@ namespace service::gui

        sys::ReturnCodes InitHandler() override;
        sys::ReturnCodes DeinitHandler() override;
        void ProcessCloseReason(sys::CloseReason closeReason) override;
        sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;



@@ 90,6 91,8 @@ namespace service::gui
        std::optional<CachedRender> cachedRender;
        std::unique_ptr<sys::Timer> contextReleaseTimer;
        State currentState;
        bool lastRenderScheduled;
        bool waitingForLastRender;
    };
} // namespace service::gui


M module-services/service-lwip/ServiceLwIP.cpp => module-services/service-lwip/ServiceLwIP.cpp +5 -0
@@ 72,6 72,11 @@ sys::ReturnCodes ServiceLwIP::DeinitHandler()
    return sys::ReturnCodes::Success;
}

void ServiceLwIP::ProcessCloseReason(sys::CloseReason closeReason)
{
    sendCloseReadyMessage(this);
}

sys::MessagePointer ServiceLwIP::DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp)
{
    LOG_ERROR("TRY START LWIP");

M module-services/service-lwip/service-lwip/ServiceLwIP.hpp => module-services/service-lwip/service-lwip/ServiceLwIP.hpp +1 -0
@@ 44,6 44,7 @@ class ServiceLwIP : public sys::Service
    virtual sys::MessagePointer DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) override;
    sys::ReturnCodes InitHandler() override;
    sys::ReturnCodes DeinitHandler() override;
    void ProcessCloseReason(sys::CloseReason closeReason) override;
    virtual sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;
};


M module-services/service-time/ServiceTime.cpp => module-services/service-time/ServiceTime.cpp +5 -0
@@ 40,6 40,11 @@ namespace stm
        return sys::ReturnCodes::Success;
    }

    void ServiceTime::ProcessCloseReason(sys::CloseReason closeReason)
    {
        sendCloseReadyMessage(this);
    }

    sys::ReturnCodes ServiceTime::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
    {
        LOG_FATAL("[ServiceTime] PowerModeHandler: %s", c_str(mode));

M module-services/service-time/ServiceTime.hpp => module-services/service-time/ServiceTime.hpp +1 -0
@@ 38,6 38,7 @@ namespace stm

        sys::ReturnCodes InitHandler() override;
        sys::ReturnCodes DeinitHandler() override;
        void ProcessCloseReason(sys::CloseReason closeReason) override;
        sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

        sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp = nullptr) override;

M module-sys/Service/Common.hpp => module-sys/Service/Common.hpp +8 -0
@@ 41,6 41,14 @@ namespace sys
        SuspendToRAM,
        SuspendToNVM
    };

    enum class CloseReason
    {
        RegularPowerDown,
        Reboot,
        SystemBrownout
    };

} // namespace sys

inline const char *c_str(sys::ReturnCodes code)

M module-sys/Service/Message.cpp => module-sys/Service/Message.cpp +14 -0
@@ 30,6 30,20 @@ namespace sys
        return Proxy::handleSystemMessage(service, this);
    }

    ServiceCloseReasonMessage::ServiceCloseReasonMessage(CloseReason closeReason) : closeReason(closeReason)
    {}

    MessagePointer ServiceCloseReasonMessage::Execute(Service *service)
    {
        Proxy::handleCloseReasonMessage(service, this);
        return MessageNone{};
    }

    CloseReason ServiceCloseReasonMessage::getCloseReason() const noexcept
    {
        return closeReason;
    }

    DataMessage::DataMessage(MessageType messageType) : messageType{messageType}
    {
        type = Type::Data;

M module-sys/Service/Message.hpp => module-sys/Service/Message.hpp +16 -0
@@ 71,6 71,22 @@ namespace sys
        ServicePowerMode powerMode;
    };

    class ServiceCloseReasonMessage : public Message
    {
      public:
        explicit ServiceCloseReasonMessage(CloseReason closeReason);

        MessagePointer Execute(Service *service) final;

        CloseReason getCloseReason() const noexcept;

      private:
        const CloseReason closeReason;
    };

    class ReadyToCloseMessage : public Message
    {};

    class DataMessage : public Message
    {
      public:

M module-sys/Service/Service.cpp => module-sys/Service/Service.cpp +15 -0
@@ 19,6 19,7 @@
#include <cstdint>             // for uint32_t, uint64_t, UINT32_MAX
#include <iosfwd>              // for std
#include <typeinfo>            // for type_info
#include <module-sys/SystemManager/Constants.hpp>

#if (DEBUG_SERVICE_MESSAGES > 0)
#include <cxxabi.h>


@@ 184,6 185,8 @@ namespace sys
        enableRunLoop = false;
    }

    auto Service::ProcessCloseReason(CloseReason closeReason) -> void{};

    auto Service::TimerHandle(SystemMessage &message) -> ReturnCodes
    {
        auto timer_message = dynamic_cast<sys::TimerMessage *>(&message);


@@ 209,6 212,12 @@ namespace sys
        }
    }

    void Service::sendCloseReadyMessage(Service *service)
    {
        auto msg = std::make_shared<sys::ReadyToCloseMessage>();
        service->bus.sendUnicast(std::move(msg), service::name::system_manager);
    }

    auto Proxy::handleMessage(Service *service, Message *message, ResponseMessage *response) -> MessagePointer
    {
        if (service->isReady) {


@@ 243,4 252,10 @@ namespace sys
        }
        return std::make_shared<ResponseMessage>(ret);
    }

    auto Proxy::handleCloseReasonMessage(Service *service, ServiceCloseReasonMessage *message) -> void
    {
        service->ProcessCloseReason(message->getCloseReason());
    }

} // namespace sys

M module-sys/Service/Service.hpp => module-sys/Service/Service.hpp +5 -0
@@ 66,6 66,8 @@ namespace sys
         */
        virtual ReturnCodes DeinitHandler() = 0;

        virtual auto ProcessCloseReason(CloseReason closeReason) -> void;

        virtual ReturnCodes SwitchPowerModeHandler(const ServicePowerMode mode) = 0;

        /**


@@ 92,6 94,8 @@ namespace sys
        bool connect(Message *msg, MessageHandler handler);
        bool connect(Message &&msg, MessageHandler handler);

        void sendCloseReadyMessage(Service *service);

      protected:
        bool enableRunLoop;



@@ 164,5 168,6 @@ namespace sys
        static auto handleMessage(Service *service, Message *message, ResponseMessage *response = nullptr)
            -> MessagePointer;
        static auto handleSystemMessage(Service *service, SystemMessage *message) -> MessagePointer;
        static auto handleCloseReasonMessage(Service *service, ServiceCloseReasonMessage *message) -> void;
    };
} // namespace sys

M module-sys/Service/Timer.cpp => module-sys/Service/Timer.cpp +6 -0
@@ 111,4 111,10 @@ namespace sys
        log_warn(
            "callback from %s non valid - %d, or not active - %d", name.c_str(), callback == nullptr, isActive != true);
    }

    bool Timer::isCurrentlyActive() const noexcept
    {
        return isActive;
    }

} // namespace sys

M module-sys/Service/Timer.hpp => module-sys/Service/Timer.hpp +1 -0
@@ 61,6 61,7 @@ namespace sys
        void reload(ms from_time = 0);
        void stop();
        void setInterval(ms new_interval);
        bool isCurrentlyActive() const noexcept;
        /// }

      protected:

M module-sys/SystemManager/SystemManager.cpp => module-sys/SystemManager/SystemManager.cpp +100 -27
@@ 15,6 15,7 @@
#include <service-evtmgr/BatteryMessages.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <service-appmgr/messages/UserPowerDownRequest.hpp>
#include <Service/Timer.hpp>
#include <service-desktop/service-desktop/Constants.hpp>
#include <service-cellular/CellularServiceAPI.hpp>


@@ 39,6 40,8 @@ namespace sys
            {bsp::KeyCodes::SSwitchUp, phone_modes::PhoneMode::Connected},
            {bsp::KeyCodes::SSwitchMid, phone_modes::PhoneMode::DoNotDisturb},
            {bsp::KeyCodes::SSwitchDown, phone_modes::PhoneMode::Offline}};

        constexpr auto preShutdownRoutineTimeout = 1500;
    } // namespace

    using namespace cpp_freertos;


@@ 93,7 96,7 @@ namespace sys
            }
        }

        DestroyService(service::name::evt_manager, this);
        DestroySystemService(service::name::evt_manager, this);

        CloseService();



@@ 144,7 147,7 @@ namespace sys
        }
        std::for_each(sortedServices.begin(), sortedServices.end(), [this](const auto &service) {
            const auto startTimeout = service.get().getStartTimeout().count();
            if (const auto success = RunService(service.get().create(), this, startTimeout); !success) {
            if (const auto success = RunSystemService(service.get().create(), this, startTimeout); !success) {
                LOG_FATAL("Unable to start service: %s", service.get().getName().c_str());
            }
        });


@@ 168,11 171,6 @@ namespace sys
        cpuStatisticsTimer->start();
    }

    bool SystemManager::CloseSystem(Service *s)
    {
        s->bus.sendUnicast(std::make_shared<SystemManagerCmd>(Code::CloseSystem), service::name::system_manager);
        return true;
    }
    bool SystemManager::Update(Service *s, const std::string &updateOSVer, std::string &currentOSVer)
    {
        // set update OS version (and also current os version) in Settings


@@ 230,10 228,6 @@ namespace sys

    bool SystemManager::RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout)
    {
        CriticalSection::Enter();
        servicesList.push_back(service);
        CriticalSection::Exit();

        service->StartService();

        auto msg  = std::make_shared<SystemMessage>(SystemMessageType::Start);


@@ 246,9 240,29 @@ namespace sys
        return false;
    }

    bool SystemManager::DestroyService(const std::string &name, Service *caller, TickType_t timeout)
    bool SystemManager::RunSystemService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout)
    {
        CriticalSection::Enter();
        servicesList.push_back(service);
        CriticalSection::Exit();

        return RunService(std::move(service), caller, timeout);
    }

    bool SystemManager::RunApplication(std::shared_ptr<Service> app, Service *caller, TickType_t timeout)
    {
        CriticalSection::Enter();
        applicationsList.push_back(app);
        CriticalSection::Exit();

        return RunService(std::move(app), caller, timeout);
    }

    bool SystemManager::DestroyService(std::vector<std::shared_ptr<Service>> &serviceContainer,
                                       const std::string &name,
                                       Service *caller,
                                       TickType_t timeout)
    {
        auto msg  = std::make_shared<SystemMessage>(SystemMessageType::Exit);
        auto ret  = caller->bus.sendUnicast(msg, name, timeout);
        auto resp = std::static_pointer_cast<ResponseMessage>(ret.second);


@@ 257,15 271,15 @@ namespace sys

            cpp_freertos::LockGuard lck(destroyMutex);

            auto serv = std::find_if(servicesList.begin(), servicesList.end(), [&](std::shared_ptr<Service> const &s) {
                return s->GetName() == name;
            });
            if (serv == servicesList.end()) {
            auto serv = std::find_if(serviceContainer.begin(),
                                     serviceContainer.end(),
                                     [&name](std::shared_ptr<Service> const &s) { return s->GetName() == name; });
            if (serv == serviceContainer.end()) {
                LOG_ERROR("No such service to destroy in services list: %s", name.c_str());
                return false;
            }

            servicesList.erase(serv);
            serviceContainer.erase(serv);

            return true;
        }


@@ 275,6 289,48 @@ namespace sys
        }
    }

    bool SystemManager::DestroySystemService(const std::string &name, Service *caller, TickType_t timeout)
    {
        return DestroyService(servicesList, name, caller, timeout);
    }

    bool SystemManager::DestroyApplication(const std::string &name, Service *caller, TickType_t timeout)
    {
        return DestroyService(applicationsList, name, caller, timeout);
    }

    void SystemManager::preCloseRoutine(CloseReason closeReason)
    {
        for (const auto &service : servicesList) {
            auto msg = std::make_shared<ServiceCloseReasonMessage>(closeReason);
            bus.sendUnicast(std::move(msg), service->GetName());
            readyForCloseRegister.push_back(service->GetName());
        }

        servicesPreShutdownRoutineTimeout =
            std::make_unique<sys::Timer>("servicesPreShutdownRoutine", this, preShutdownRoutineTimeout);
        servicesPreShutdownRoutineTimeout->connect([&](sys::Timer &) { CloseServices(); });
        servicesPreShutdownRoutineTimeout->start();
    }

    void SystemManager::readyToCloseHandler(Message *msg)
    {
        if (!readyForCloseRegister.empty() && servicesPreShutdownRoutineTimeout->isCurrentlyActive()) {
            auto message = static_cast<ReadyToCloseMessage *>(msg);
            LOG_INFO("ready to close %s", message->sender.c_str());
            readyForCloseRegister.erase(
                std::remove(readyForCloseRegister.begin(), readyForCloseRegister.end(), message->sender),
                readyForCloseRegister.end());

            // All services responded
            if (readyForCloseRegister.empty()) {
                LOG_INFO("All services ready to close.");
                servicesPreShutdownRoutineTimeout->stop();
                CloseServices();
            }
        }
    }

    void SystemManager::kill(std::shared_ptr<Service> const &toKill)
    {
        auto ret = toKill->DeinitHandler();


@@ 294,7 350,7 @@ namespace sys

                switch (data->type) {
                case Code::CloseSystem:
                    CloseSystemHandler();
                    CloseSystemHandler(data->closeReason);
                    break;
                case Code::Update:
                    UpdateSystemHandler();


@@ 325,11 381,8 @@ namespace sys
        });

        connect(sevm::BatteryBrownoutMessage(), [&](Message *) {
            LOG_INFO("Battery Brownout voltage level reached!");

            auto msg = std::make_shared<SystemBrownoutMesssage>();
            bus.sendUnicast(msg, app::manager::ApplicationManager::ServiceName);

            LOG_INFO("Battery Brownout voltage level reached! Closing system...");
            CloseSystemHandler(CloseReason::SystemBrownout);
            return MessageNone{};
        });



@@ 357,6 410,16 @@ namespace sys
            return MessageNone{};
        });

        connect(app::UserPowerDownRequest(), [&](Message *) {
            CloseSystemHandler(CloseReason::RegularPowerDown);
            return MessageNone{};
        });

        connect(ReadyToCloseMessage(), [&](Message *msg) {
            readyToCloseHandler(msg);
            return MessageNone{};
        });

        connect(typeid(sys::CpuFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::CpuFrequencyMessage *>(message);



@@ 413,7 476,7 @@ namespace sys
        return std::make_shared<ResponseMessage>();
    }

    void SystemManager::CloseSystemHandler()
    void SystemManager::CloseSystemHandler(CloseReason closeReason)
    {
        LOG_DEBUG("Invoking closing procedure...");



@@ 422,6 485,15 @@ namespace sys
        std::reverse(servicesList.begin(), servicesList.end());
        CriticalSection::Exit();

        preCloseRoutine(closeReason);
    }

    void SystemManager::CloseServices()
    {
        for (const auto &element : readyForCloseRegister) {
            LOG_INFO("Service: %s did not reported before timeout", element.c_str());
        }

        for (bool retry{};; retry = false) {
            for (auto &service : servicesList) {
                if (service->GetName() == service::name::evt_manager) {


@@ 429,7 501,7 @@ namespace sys
                    continue;
                }
                if (service->parent == "") {
                    const auto ret = DestroyService(service->GetName(), this);
                    const auto ret = DestroySystemService(service->GetName(), this);
                    if (!ret) {
                        // no response to exit message,
                        LOG_FATAL("%s", (service->GetName() + " failed to response to exit message").c_str());


@@ 486,7 558,7 @@ namespace sys
                    continue;
                }
                if (service->parent.empty()) {
                    const auto ret = DestroyService(service->GetName(), this);
                    const auto ret = DestroySystemService(service->GetName(), this);
                    if (!ret) {
                        // no response to exit message,
                        LOG_FATAL("%s failed to response to exit message", service->GetName().c_str());


@@ 504,7 576,7 @@ namespace sys

    void SystemManager::RebootHandler()
    {
        CloseSystemHandler();
        CloseSystemHandler(CloseReason::Reboot);
        set(State::Reboot);
    }



@@ 544,6 616,7 @@ namespace sys
    }

    std::vector<std::shared_ptr<Service>> SystemManager::servicesList;
    std::vector<std::shared_ptr<Service>> SystemManager::applicationsList;
    cpp_freertos::MutexStandard SystemManager::destroyMutex;
    std::unique_ptr<PowerManager> SystemManager::powerManager;
    std::unique_ptr<CpuStatistics> SystemManager::cpuStatistics;

M module-sys/SystemManager/SystemManager.hpp => module-sys/SystemManager/SystemManager.hpp +25 -7
@@ 50,10 50,12 @@ namespace sys
    class SystemManagerCmd : public DataMessage
    {
      public:
        SystemManagerCmd(Code type = Code::None) : DataMessage(BusChannel::SystemManagerRequests), type(type)
        explicit SystemManagerCmd(Code type = Code::None, CloseReason closeReason = CloseReason::RegularPowerDown)
            : DataMessage(BusChannel::SystemManagerRequests), type(type), closeReason(closeReason)
        {}

        Code type;
        CloseReason closeReason;
    };

    class SystemManager : public Service


@@ 79,9 81,6 @@ namespace sys

        void StartSystem(InitFunction sysInit, InitFunction appSpaceInit);

        // Invoke system close procedure
        static bool CloseSystem(Service *s);

        static bool Update(Service *s, const std::string &updateOSVer, std::string &currentOSVer);

        static bool Reboot(Service *s);


@@ 93,11 92,15 @@ namespace sys
        static bool ResumeService(const std::string &name, Service *caller);

        /// Runs a service
        static bool RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
        static bool RunSystemService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
        /// Runs an application
        static bool RunApplication(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);

        /// Destroy existing service
        /// @note there is no fallback
        static bool DestroyService(const std::string &name, Service *caller, TickType_t timeout = 5000);
        static bool DestroySystemService(const std::string &name, Service *caller, TickType_t timeout = 5000);
        /// Destroy existing application
        static bool DestroyApplication(const std::string &name, Service *caller, TickType_t timeout = 5000);

        /// Translates a slider state into a phone mode.
        /// \param key  Slider button state


@@ 133,12 136,24 @@ namespace sys

        void StartSystemServices();

        static bool RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
        static bool DestroyService(std::vector<std::shared_ptr<Service>> &serviceContainer,
                                   const std::string &name,
                                   Service *caller,
                                   TickType_t timeout = 5000);

        /// Sysmgr stores list of all active services but some of them are under control of parent services.
        /// Parent services ought to manage lifetime of child services hence we are sending DestroyRequests only to
        /// parents.
        /// It closes all workers except EventManager -as it needs information from Eventmanager that it's safe to
        /// shutdown
        void CloseSystemHandler();
        void CloseSystemHandler(CloseReason closeReason = CloseReason::RegularPowerDown);

        void CloseServices();

        void preCloseRoutine(CloseReason closeReason);

        void readyToCloseHandler(Message *msg);

        void UpdateSystemHandler();



@@ 162,11 177,14 @@ namespace sys

        std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
        std::unique_ptr<sys::Timer> cpuStatisticsTimer;
        std::unique_ptr<sys::Timer> servicesPreShutdownRoutineTimeout;
        std::unique_ptr<phone_modes::Subject> phoneModeSubject;
        InitFunction userInit;
        InitFunction systemInit;
        std::vector<std::string> readyForCloseRegister;

        static std::vector<std::shared_ptr<Service>> servicesList;
        static std::vector<std::shared_ptr<Service>> applicationsList;
        static cpp_freertos::MutexStandard destroyMutex;
        static std::unique_ptr<PowerManager> powerManager;
        static std::unique_ptr<CpuStatistics> cpuStatistics;

A module-sys/SystemManager/doc/SystemCloseSequence.md => module-sys/SystemManager/doc/SystemCloseSequence.md +10 -0
@@ 0,0 1,10 @@
# Sequence flow when closing the system

Regular power down via menu

![](./system_close_procedure_user.svg)


Close at Brownout event

![](./system_close_procedure_brownout.svg)
\ No newline at end of file

A module-sys/SystemManager/doc/system_close_procedure_brownout.puml => module-sys/SystemManager/doc/system_close_procedure_brownout.puml +27 -0
@@ 0,0 1,27 @@
@startuml

participant "System Manager" as sysmgr
participant "All services" as srv
participant "Application Manager" as appmgr
participant "Service GUI" as gui
participant "service EINK" as eink

-> sysmgr : battery brownout
sysmgr -> srv : preCloseRoutine

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(Dead Battery Window)
eink -> gui : last sreen show
gui -> srv : ready to close

srv -> sysmgr : readyToClose
alt timeout
sysmgr -> sysmgr : closeServices
end
sysmgr -> srv : SystemMessageType::Exit
srv -> sysmgr : MsgHandled
alt timeout
sysmgr -> sysmgr : kill service
end

@enduml

A module-sys/SystemManager/doc/system_close_procedure_brownout.svg => module-sys/SystemManager/doc/system_close_procedure_brownout.svg +37 -0
@@ 0,0 1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="525px" preserveAspectRatio="none" style="width:959px;height:525px;" version="1.1" viewBox="0 0 959 525" width="959px" zoomAndPan="magnify"><defs><filter height="300%" id="f14d4etav8v0b3" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f14d4etav8v0b3)" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="182.5" x="56.5" y="274.2266"/><rect fill="#FFFFFF" filter="url(#f14d4etav8v0b3)" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="160.5" x="56.5" y="405.7578"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="132.5" x2="132.5" y1="40.2969" y2="482.0234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="324" x2="324" y1="40.2969" y2="482.0234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="479.5" x2="479.5" y1="40.2969" y2="482.0234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="775" x2="775" y1="40.2969" y2="482.0234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="898" x2="898" y1="40.2969" y2="482.0234"/><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="66.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="73.5" y="24.9951">System Manager</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="66.5" y="481.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="73.5" y="501.0186">System Manager</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="90" x="277" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="284" y="24.9951">All services</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="90" x="277" y="481.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="284" y="501.0186">All services</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="153" x="401.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="139" x="408.5" y="24.9951">Application Manager</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="153" x="401.5" y="481.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="139" x="408.5" y="501.0186">Application Manager</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="92" x="727" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="78" x="734" y="24.9951">Service GUI</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="92" x="727" y="481.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="78" x="734" y="501.0186">Service GUI</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="98" x="847" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="854" y="24.9951">service EINK</text><rect fill="#FEFECE" filter="url(#f14d4etav8v0b3)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="98" x="847" y="481.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="854" y="501.0186">service EINK</text><polygon fill="#A80036" points="121,67.4297,131,71.4297,121,75.4297,125,71.4297" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="0" x2="127" y1="71.4297" y2="71.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="109" x="7" y="66.3638">battery brownout</text><polygon fill="#A80036" points="312,96.5625,322,100.5625,312,104.5625,316,100.5625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="133" x2="318" y1="100.5625" y2="100.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="104" x="140" y="95.4966">preCloseRoutine</text><polygon fill="#A80036" points="468,125.6953,478,129.6953,468,133.6953,472,129.6953" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="324" x2="474" y1="129.6953" y2="129.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="132" x="331" y="124.6294">processCloseReason</text><line style="stroke:#A80036;stroke-width:1.0;" x1="480" x2="522" y1="158.8281" y2="158.8281"/><line style="stroke:#A80036;stroke-width:1.0;" x1="522" x2="522" y1="158.8281" y2="171.8281"/><line style="stroke:#A80036;stroke-width:1.0;" x1="481" x2="522" y1="171.8281" y2="171.8281"/><polygon fill="#A80036" points="491,167.8281,481,171.8281,491,175.8281,487,171.8281" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="281" x="487" y="153.7622">switchWindowAtClose(Dead Battery Window)</text><polygon fill="#A80036" points="786,196.9609,776,200.9609,786,204.9609,782,200.9609" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="780" x2="897" y1="200.9609" y2="200.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="99" x="792" y="195.895">last sreen show</text><polygon fill="#A80036" points="335,226.0938,325,230.0938,335,234.0938,331,230.0938" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="329" x2="774" y1="230.0938" y2="230.0938"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="90" x="341" y="225.0278">ready to close</text><polygon fill="#A80036" points="144,255.2266,134,259.2266,144,263.2266,140,259.2266" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="138" x2="323" y1="259.2266" y2="259.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="86" x="150" y="254.1606">readyToClose</text><path d="M56.5,274.2266 L120.5,274.2266 L120.5,281.2266 L110.5,291.2266 L56.5,291.2266 L56.5,274.2266 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="182.5" x="56.5" y="274.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="19" x="71.5" y="287.2935">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="59" x="135.5" y="286.437">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="133" x2="175" y1="312.4922" y2="312.4922"/><line style="stroke:#A80036;stroke-width:1.0;" x1="175" x2="175" y1="312.4922" y2="325.4922"/><line style="stroke:#A80036;stroke-width:1.0;" x1="134" x2="175" y1="325.4922" y2="325.4922"/><polygon fill="#A80036" points="144,321.4922,134,325.4922,144,329.4922,140,325.4922" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="87" x="140" y="307.4263">closeServices</text><polygon fill="#A80036" points="312,357.625,322,361.625,312,365.625,316,361.625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="133" x2="318" y1="361.625" y2="361.625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="167" x="140" y="356.5591">SystemMessageType::Exit</text><polygon fill="#A80036" points="144,386.7578,134,390.7578,144,394.7578,140,390.7578" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="138" x2="323" y1="390.7578" y2="390.7578"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="79" x="150" y="385.6919">MsgHandled</text><path d="M56.5,405.7578 L120.5,405.7578 L120.5,412.7578 L110.5,422.7578 L56.5,422.7578 L56.5,405.7578 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="160.5" x="56.5" y="405.7578"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="19" x="71.5" y="418.8247">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="59" x="135.5" y="417.9683">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="133" x2="175" y1="444.0234" y2="444.0234"/><line style="stroke:#A80036;stroke-width:1.0;" x1="175" x2="175" y1="444.0234" y2="457.0234"/><line style="stroke:#A80036;stroke-width:1.0;" x1="134" x2="175" y1="457.0234" y2="457.0234"/><polygon fill="#A80036" points="144,453.0234,134,457.0234,144,461.0234,140,457.0234" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="65" x="140" y="438.9575">kill service</text><!--MD5=[d772a965bf366a1a13d1083fbf2ffa88]
@startuml

participant "System Manager" as sysmgr
participant "All services" as srv
participant "Application Manager" as appmgr
participant "Service GUI" as gui
participant "service EINK" as eink

-> sysmgr : battery brownout
sysmgr -> srv : preCloseRoutine

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(Dead Battery Window)
eink -> gui : last sreen show
gui -> srv : ready to close

srv -> sysmgr : readyToClose
alt timeout
sysmgr -> sysmgr : closeServices
end
sysmgr -> srv : SystemMessageType::Exit
srv -> sysmgr : MsgHandled
alt timeout
sysmgr -> sysmgr : kill service
end

@enduml

PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Default Encoding: UTF-8
Language: pl
Country: PL
--></g></svg>
\ No newline at end of file

A module-sys/SystemManager/doc/system_close_procedure_user.puml => module-sys/SystemManager/doc/system_close_procedure_user.puml +32 -0
@@ 0,0 1,32 @@
@startuml

actor User
participant "PowerOffWindow" as poff
participant "Application" as app
participant "System Manager" as sysmgr
participant "All services" as srv
participant "Application Manager" as appmgr
participant "Service GUI" as gui
participant "service EINK" as eink

User -> poff : confirm close
poff -> app : GUI off switch
app -> sysmgr : UserPowerDownRequest
sysmgr -> srv : preCloseRoutine

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(logo)
eink -> gui : last sreen show
gui -> srv : ready to close

srv -> sysmgr : readyToClose
alt timeout
sysmgr -> sysmgr : closeServices
end
sysmgr -> srv : SystemMessageType::Exit
srv -> sysmgr : MsgHandled
alt timeout
sysmgr -> sysmgr : kill service
end

@enduml

A module-sys/SystemManager/doc/system_close_procedure_user.svg => module-sys/SystemManager/doc/system_close_procedure_user.svg +42 -0
@@ 0,0 1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="672px" preserveAspectRatio="none" style="width:1152px;height:672px;" version="1.1" viewBox="0 0 1152 672" width="1152px" zoomAndPan="magnify"><defs><filter height="300%" id="f13kgozwf63std" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f13kgozwf63std)" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="182.5" x="359" y="380.4922"/><rect fill="#FFFFFF" filter="url(#f13kgozwf63std)" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="160.5" x="359" y="512.0234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="24" x2="24" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="133" x2="133" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="256" x2="256" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="435" x2="435" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="626.5" x2="626.5" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="782" x2="782" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="968.5" x2="968.5" y1="88.2969" y2="588.2891"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1091.5" x2="1091.5" y1="88.2969" y2="588.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="32" x="5" y="84.9951">User</text><ellipse cx="24" cy="15" fill="#FEFECE" filter="url(#f13kgozwf63std)" rx="8" ry="8" style="stroke:#A80036;stroke-width:2.0;"/><path d="M24,23 L24,50 M11,31 L37,31 M24,50 L11,65 M24,50 L37,65 " fill="none" filter="url(#f13kgozwf63std)" style="stroke:#A80036;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="32" x="5" y="600.2842">User</text><ellipse cx="24" cy="613.5859" fill="#FEFECE" filter="url(#f13kgozwf63std)" rx="8" ry="8" style="stroke:#A80036;stroke-width:2.0;"/><path d="M24,621.5859 L24,648.5859 M11,629.5859 L37,629.5859 M24,648.5859 L11,663.5859 M24,648.5859 L37,663.5859 " fill="none" filter="url(#f13kgozwf63std)" style="stroke:#A80036;stroke-width:2.0;"/><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="130" x="66" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="116" x="73" y="72.9951">PowerOffWindow</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="130" x="66" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="116" x="73" y="607.2842">PowerOffWindow</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="89" x="210" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="75" x="217" y="72.9951">Application</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="89" x="210" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="75" x="217" y="607.2842">Application</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="369" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="376" y="72.9951">System Manager</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="369" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="376" y="607.2842">System Manager</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="90" x="579.5" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="586.5" y="72.9951">All services</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="90" x="579.5" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="586.5" y="607.2842">All services</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="153" x="704" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="139" x="711" y="72.9951">Application Manager</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="153" x="704" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="139" x="711" y="607.2842">Application Manager</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="92" x="920.5" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="78" x="927.5" y="72.9951">Service GUI</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="92" x="920.5" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="78" x="927.5" y="607.2842">Service GUI</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="98" x="1040.5" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="1047.5" y="72.9951">service EINK</text><rect fill="#FEFECE" filter="url(#f13kgozwf63std)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="98" x="1040.5" y="587.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="1047.5" y="607.2842">service EINK</text><polygon fill="#A80036" points="121,115.4297,131,119.4297,121,123.4297,125,119.4297" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="24" x2="127" y1="119.4297" y2="119.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="85" x="31" y="114.3638">confirm close</text><polygon fill="#A80036" points="244.5,144.5625,254.5,148.5625,244.5,152.5625,248.5,148.5625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="133" x2="250.5" y1="148.5625" y2="148.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="86" x="140" y="143.4966">GUI off switch</text><polygon fill="#A80036" points="423.5,173.6953,433.5,177.6953,423.5,181.6953,427.5,177.6953" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="256.5" x2="429.5" y1="177.6953" y2="177.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="155" x="263.5" y="172.6294">UserPowerDownRequest</text><polygon fill="#A80036" points="614.5,202.8281,624.5,206.8281,614.5,210.8281,618.5,206.8281" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="435.5" x2="620.5" y1="206.8281" y2="206.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="104" x="442.5" y="201.7622">preCloseRoutine</text><polygon fill="#A80036" points="770.5,231.9609,780.5,235.9609,770.5,239.9609,774.5,235.9609" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="626.5" x2="776.5" y1="235.9609" y2="235.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="132" x="633.5" y="230.895">processCloseReason</text><line style="stroke:#A80036;stroke-width:1.0;" x1="782.5" x2="824.5" y1="265.0938" y2="265.0938"/><line style="stroke:#A80036;stroke-width:1.0;" x1="824.5" x2="824.5" y1="265.0938" y2="278.0938"/><line style="stroke:#A80036;stroke-width:1.0;" x1="783.5" x2="824.5" y1="278.0938" y2="278.0938"/><polygon fill="#A80036" points="793.5,274.0938,783.5,278.0938,793.5,282.0938,789.5,278.0938" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="172" x="789.5" y="260.0278">switchWindowAtClose(logo)</text><polygon fill="#A80036" points="979.5,303.2266,969.5,307.2266,979.5,311.2266,975.5,307.2266" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="973.5" x2="1090.5" y1="307.2266" y2="307.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="99" x="985.5" y="302.1606">last sreen show</text><polygon fill="#A80036" points="637.5,332.3594,627.5,336.3594,637.5,340.3594,633.5,336.3594" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="631.5" x2="967.5" y1="336.3594" y2="336.3594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="90" x="643.5" y="331.2935">ready to close</text><polygon fill="#A80036" points="446.5,361.4922,436.5,365.4922,446.5,369.4922,442.5,365.4922" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="440.5" x2="625.5" y1="365.4922" y2="365.4922"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="86" x="452.5" y="360.4263">readyToClose</text><path d="M359,380.4922 L423,380.4922 L423,387.4922 L413,397.4922 L359,397.4922 L359,380.4922 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="182.5" x="359" y="380.4922"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="19" x="374" y="393.5591">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="59" x="438" y="392.7026">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="435.5" x2="477.5" y1="418.7578" y2="418.7578"/><line style="stroke:#A80036;stroke-width:1.0;" x1="477.5" x2="477.5" y1="418.7578" y2="431.7578"/><line style="stroke:#A80036;stroke-width:1.0;" x1="436.5" x2="477.5" y1="431.7578" y2="431.7578"/><polygon fill="#A80036" points="446.5,427.7578,436.5,431.7578,446.5,435.7578,442.5,431.7578" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="87" x="442.5" y="413.6919">closeServices</text><polygon fill="#A80036" points="614.5,463.8906,624.5,467.8906,614.5,471.8906,618.5,467.8906" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="435.5" x2="620.5" y1="467.8906" y2="467.8906"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="167" x="442.5" y="462.8247">SystemMessageType::Exit</text><polygon fill="#A80036" points="446.5,493.0234,436.5,497.0234,446.5,501.0234,442.5,497.0234" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="440.5" x2="625.5" y1="497.0234" y2="497.0234"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="79" x="452.5" y="491.9575">MsgHandled</text><path d="M359,512.0234 L423,512.0234 L423,519.0234 L413,529.0234 L359,529.0234 L359,512.0234 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="59.2656" style="stroke:#000000;stroke-width:2.0;" width="160.5" x="359" y="512.0234"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="19" x="374" y="525.0903">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="59" x="438" y="524.2339">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="435.5" x2="477.5" y1="550.2891" y2="550.2891"/><line style="stroke:#A80036;stroke-width:1.0;" x1="477.5" x2="477.5" y1="550.2891" y2="563.2891"/><line style="stroke:#A80036;stroke-width:1.0;" x1="436.5" x2="477.5" y1="563.2891" y2="563.2891"/><polygon fill="#A80036" points="446.5,559.2891,436.5,563.2891,446.5,567.2891,442.5,563.2891" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="65" x="442.5" y="545.2231">kill service</text><!--MD5=[13bd41519717474e9d0f145e7a7409c3]
@startuml

actor User
participant "PowerOffWindow" as poff
participant "Application" as app
participant "System Manager" as sysmgr
participant "All services" as srv
participant "Application Manager" as appmgr
participant "Service GUI" as gui
participant "service EINK" as eink

User -> poff : confirm close
poff -> app : GUI off switch
app -> sysmgr : UserPowerDownRequest
sysmgr -> srv : preCloseRoutine

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(logo)
eink -> gui : last sreen show
gui -> srv : ready to close

srv -> sysmgr : readyToClose
alt timeout
sysmgr -> sysmgr : closeServices
end
sysmgr -> srv : SystemMessageType::Exit
srv -> sysmgr : MsgHandled
alt timeout
sysmgr -> sysmgr : kill service
end

@enduml

PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Default Encoding: UTF-8
Language: pl
Country: PL
--></g></svg>
\ No newline at end of file

M module-sys/SystemManager/messages/SystemManagerMessage.hpp => module-sys/SystemManager/messages/SystemManagerMessage.hpp +0 -10
@@ 37,14 37,4 @@ namespace sys
        bool isActive;
    };

    class SystemBrownoutMesssage : public sys::Message, public app::manager::actions::ConvertibleToAction
    {
      public:
        [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
        {
            return std::make_unique<app::manager::ActionRequest>(
                service::name::system_manager, app::manager::actions::SystemBrownout, nullptr);
        }
    };

} // namespace sys

M source/main.cpp => source/main.cpp +1 -1
@@ 174,7 174,7 @@ int main()
            applications.push_back(app::CreateLauncher<app::ApplicationOnBoarding>(app::name_onboarding));
#endif
            // start application manager
            return sysmgr->RunService(
            return sysmgr->RunSystemService(
                std::make_shared<app::manager::ApplicationManager>(
                    app::manager::ApplicationManager::ServiceName, std::move(applications), app::name_desktop),
                sysmgr.get());