~aleteoryx/muditaos

97e9d7b79fee667ebe70ff2f5142f021854cc45d — Mateusz Piesta 3 years ago 44cc7f0
[BH-1449] Fix gui/eink dependencies

* Dependencies between service-gui and service-eink
have been correctly defined.
* System close routine was replaced with the sequential one
which should solve many bell issues.
* It also fixes BH-1406 and BH-1442.
* Fixed some weird CMake issues in module-audio and
several other modules.
* Fixed service-gui closing routine
* Removed unneeded messages/states from service-gui/eink.
* Enhanced app-mgr closing routine. Fixed closing action handling.
39 files changed, 209 insertions(+), 365 deletions(-)

M Target_Linux.cmake
M module-apps/apps-common/ApplicationCommon.cpp
M module-apps/apps-common/ApplicationCommon.hpp
M module-apps/apps-common/messages/AppMessage.hpp
M module-audio/Audio/AudioDevice.hpp
M module-audio/Audio/Operation/Operation.hpp
M module-audio/Audio/Profiles/Profile.hpp
M module-audio/CMakeLists.txt
M module-services/CMakeLists.txt
M module-services/service-appmgr/include/service-appmgr/StartupType.hpp
M module-services/service-appmgr/model/ApplicationManagerCommon.cpp
M module-services/service-eink/CMakeLists.txt
M module-services/service-eink/EinkDisplay.hpp
M module-services/service-eink/ServiceEink.cpp
M module-services/service-eink/ServiceEink.hpp
M module-services/service-gui/CMakeLists.txt
M module-services/service-gui/ServiceGUI.cpp
M module-services/service-gui/WorkerGUI.cpp
M module-services/service-gui/service-gui/ServiceGUI.hpp
M module-services/service-gui/service-gui/messages/DrawMessage.hpp
D module-services/service-gui/service-gui/messages/EinkInitialized.hpp
M module-sys/SystemManager/SystemManagerCommon.cpp
M module-sys/SystemManager/doc/SystemCloseSequence.md
M module-sys/SystemManager/doc/system_close_procedure_brownout.puml
M module-sys/SystemManager/doc/system_close_procedure_brownout.svg
M module-sys/SystemManager/doc/system_close_procedure_user.puml
M module-sys/SystemManager/doc/system_close_procedure_user.svg
M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp
M products/BellHybrid/BellHybridMain.cpp
M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp
M products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp
M products/BellHybrid/services/appmgr/ApplicationManager.cpp
M products/BellHybrid/services/appmgr/CMakeLists.txt
M products/BellHybrid/services/appmgr/include/appmgr/ApplicationManager.hpp
D products/BellHybrid/services/appmgr/include/appmgr/messages/BatteryShutdown.hpp
M products/BellHybrid/sys/SystemManager.cpp
M products/BellHybrid/sys/include/sys/SystemManager.hpp
M products/PurePhone/PurePhoneMain.cpp
M products/PurePhone/services/appmgr/ApplicationManager.cpp
M Target_Linux.cmake => Target_Linux.cmake +0 -1
@@ 5,7 5,6 @@ add_compile_options(-funsigned-char)
set(TARGET_LIBRARIES
    rt
    pthread
    portaudio
    CACHE INTERNAL "" )

link_libraries(pthread rt)

M module-apps/apps-common/ApplicationCommon.cpp => module-apps/apps-common/ApplicationCommon.cpp +19 -31
@@ 127,8 127,6 @@ namespace app

        connect(typeid(AppRefreshMessage),
                [this](sys::Message *msg) -> sys::MessagePointer { return handleAppRefresh(msg); });
        connect(typeid(AppShutdownRefreshMessage),
                [this](sys::Message *msg) -> sys::MessagePointer { return handleAppShutdownRefresh(msg); });
        connect(sevm::BatteryStatusChangeMessage(), [&](sys::Message *) { return handleBatteryStatusChange(); });
        connect(typeid(app::manager::DOMRequest),
                [&](sys::Message *msg) -> sys::MessagePointer { return handleGetDOM(msg); });


@@ 713,33 711,6 @@ namespace app
        return sys::msgHandled();
    }

    sys::MessagePointer ApplicationCommon::handleAppShutdownRefresh(sys::Message *msgl)
    {
        auto *msg = static_cast<AppShutdownRefreshMessage *>(msgl);
        assert(msg);

        if (not windowsFactory.isRegistered(msg->getWindowName())) {
            LOG_ERROR("Cannot find window %s windowsFactory in application: %s",
                      msg->getWindowName().c_str(),
                      GetName().c_str());
            return sys::msgHandled();
        }

        pushWindow(msg->getWindowName());
        auto window = getWindow(msg->getWindowName());

        if (not window) {
            LOG_ERROR("Cannot find window %s in application %s", msg->getWindowName().c_str(), GetName().c_str());
            return sys::msgHandled();
        }

        auto message = std::make_shared<service::gui::DrawMessage>(window->buildDrawList(), msg->getMode());
        message->setCommandType(service::gui::DrawMessage::Type::SHUTDOWN);
        bus.sendUnicast(std::move(message), service::name::gui);

        return sys::msgHandled();
    }

    sys::MessagePointer ApplicationCommon::handleGetDOM(sys::Message *msgl)
    {
        if (windowsStack().isEmpty()) {


@@ 936,8 907,25 @@ namespace app
                 GetName().c_str(),
                 windowName.length() ? windowName.c_str() : default_window.c_str());
#endif
        auto msg = std::make_shared<AppShutdownRefreshMessage>(windowName);
        bus.sendUnicast(msg, this->GetName());
        if (not windowsFactory.isRegistered(windowName)) {
            LOG_ERROR("Cannot find window %s windowsFactory in application: %s", windowName.c_str(), GetName().c_str());
            return;
        }

        pushWindow(windowName);
        const auto window = getWindow(windowName);
        if (not window) {
            LOG_ERROR("Cannot find window %s in application %s", windowName.c_str(), GetName().c_str());
            return;
        }

        const auto response = bus.sendUnicastSync(
            std::make_shared<service::gui::DrawMessage>(window->buildDrawList(), gui::RefreshModes::GUI_REFRESH_DEEP),
            service::name::gui,
            100);
        if (response.first != sys::ReturnCodes::Success) {
            LOG_FATAL("Failed to send the shutdown window frame");
        }
    }

    bool ApplicationCommon::userInterfaceDBNotification([[maybe_unused]] sys::Message *msg,

M module-apps/apps-common/ApplicationCommon.hpp => module-apps/apps-common/ApplicationCommon.hpp +0 -1
@@ 206,7 206,6 @@ namespace app
        bool handleUpdateTextRefresh(gui::SwitchData *data);
        sys::MessagePointer handleAppRebuild(sys::Message *msgl);
        sys::MessagePointer handleAppRefresh(sys::Message *msgl);
        sys::MessagePointer handleAppShutdownRefresh(sys::Message *msgl);
        sys::MessagePointer handleGetDOM(sys::Message *msgl);

        std::list<std::unique_ptr<app::GuiTimer>> gui_timers;

M module-apps/apps-common/messages/AppMessage.hpp => module-apps/apps-common/messages/AppMessage.hpp +0 -7
@@ 114,13 114,6 @@ namespace app
        }
    };

    class AppShutdownRefreshMessage : public AppRefreshMessage
    {
      public:
        AppShutdownRefreshMessage(std::string window_name)
            : AppRefreshMessage(gui::RefreshModes::GUI_REFRESH_DEEP, window_name){};
    };

    class AppSwitchWindowMessage : public AppMessage
    {
      protected:

M module-audio/Audio/AudioDevice.hpp => module-audio/Audio/AudioDevice.hpp +1 -1
@@ 3,7 3,7 @@

#pragma once

#include <Audio/Endpoint.hpp>
#include "Endpoint.hpp"

#include <optional>
#include <memory>

M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +6 -6
@@ 7,12 7,12 @@
#include <functional>
#include <optional>

#include <Audio/AudioCommon.hpp>
#include <Audio/AudioDeviceFactory.hpp>
#include <Audio/AudioPlatform.hpp>
#include <Audio/ServiceObserver.hpp>
#include <Audio/encoder/Encoder.hpp>
#include <Audio/Profiles/Profile.hpp>
#include "Audio/AudioCommon.hpp"
#include "Audio/AudioDeviceFactory.hpp"
#include "Audio/AudioPlatform.hpp"
#include "Audio/ServiceObserver.hpp"
#include "Audio/encoder/Encoder.hpp"
#include "Audio/Profiles/Profile.hpp"

#include <service-bluetooth/ServiceBluetoothCommon.hpp>


M module-audio/Audio/Profiles/Profile.hpp => module-audio/Audio/Profiles/Profile.hpp +2 -2
@@ 3,8 3,8 @@

#pragma once

#include <Audio/AudioDevice.hpp>
#include <Audio/codec.hpp>
#include "Audio/AudioDevice.hpp"
#include "Audio/codec.hpp"

#include <memory>
#include <functional>

M module-audio/CMakeLists.txt => module-audio/CMakeLists.txt +2 -1
@@ 53,7 53,7 @@ target_sources(
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_TARGET})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDES})
target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# supress warning for flac decoder
set_source_files_properties(


@@ 75,6 75,7 @@ target_link_libraries(${PROJECT_NAME}
                utils-math
                tagsfetcher
                dr_libs::dr_libs
                service-bluetooth
)

add_subdirectory(tags_fetcher)

M module-services/CMakeLists.txt => module-services/CMakeLists.txt +9 -10
@@ 3,7 3,7 @@

module_is_test_entity()

add_library(${PROJECT_NAME} STATIC ${SOURCES})
add_library(${PROJECT_NAME} INTERFACE)

option(ENABLE_SERVICE_TEST "Enable service test" OFF) 



@@ 30,8 30,8 @@ add_module_options( OPTION_PREFIX "SERVICE"

set(ENABLED_SERVICES_DEFINES ${ENABLED_SERVICES_DEFINES} PARENT_SCOPE)

target_link_libraries(${PROJECT_NAME} 
    PUBLIC
target_link_libraries(${PROJECT_NAME}
    INTERFACE
        service-gui
        service-eink
        service-appmgr


@@ 45,25 45,24 @@ target_link_libraries(${PROJECT_NAME}
        module-audio
        service-antenna
        ${TARGET_LIBRARIES}
    PRIVATE
        utils-time
)

# Board specific compilation definitions,options,include directories and features
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_TARGET})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDES})
target_include_directories(${PROJECT_NAME} PUBLIC ${LWIP_INCLUDE_DIRS})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${PROJECT_TARGET})
target_include_directories(${PROJECT_NAME} INTERFACE ${PROJECT_INCLUDES})
target_include_directories(${PROJECT_NAME} INTERFACE ${LWIP_INCLUDE_DIRS})

target_include_directories(${PROJECT_NAME}
        PUBLIC
        INTERFACE
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/../source
        ${CMAKE_SOURCE_DIR}/module-bluetooth
)

target_compile_options(${PROJECT_NAME}
        PUBLIC
        INTERFACE
        -Wall
        $<$<COMPILE_LANGUAGE:C>:-std=gnu11>
        $<$<COMPILE_LANGUAGE:C>:-Wno-discarded-qualifiers>

M module-services/service-appmgr/include/service-appmgr/StartupType.hpp => module-services/service-appmgr/include/service-appmgr/StartupType.hpp +2 -1
@@ 9,6 9,7 @@ namespace app::manager
    {
        Regular,
        LowBattery,
        LowBatteryCharging
        LowBatteryCharging,
        CriticalBattery
    };
} // namespace app::manager

M module-services/service-appmgr/model/ApplicationManagerCommon.cpp => module-services/service-appmgr/model/ApplicationManagerCommon.cpp +21 -16
@@ 35,6 35,23 @@ namespace app::manager
    namespace
    {
        constexpr auto ApplicationManagerStackDepth = 3072;

        bool checkIfCloseableAction(const actions::Action action)
        {
            return action == app::manager::actions::DisplayLogoAtExit or
                   action == app::manager::actions::SystemBrownout;
        }

        ActionRequest getCloseableAction(const app::ApplicationName &senderName, const sys::CloseReason closeReason)
        {
            switch (closeReason) {
            case sys::CloseReason::SystemBrownout:
            case sys::CloseReason::LowBattery:
                return ActionRequest{senderName, app::manager::actions::SystemBrownout, nullptr};
            default:
                return ActionRequest{senderName, app::manager::actions::DisplayLogoAtExit, nullptr};
            }
        }
    } // namespace

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


@@ 148,26 165,14 @@ namespace app::manager

    sys::ReturnCodes ApplicationManagerCommon::DeinitHandler()
    {
        settings->deinit();
        closeApplications();
        settings->deinit();
        return sys::ReturnCodes::Success;
    }

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



@@ 260,7 265,7 @@ namespace app::manager
            return sys::msgHandled();
        });
        connect(typeid(ActionHandledResponse), [this](sys::Message *response) {
            if (actionsRegistry.getPendingAction()->actionId == app::manager::actions::DisplayLogoAtExit) {
            if (checkIfCloseableAction(actionsRegistry.getPendingAction()->actionId)) {
                isReady = false;
                sendCloseReadyMessage(this);
            }


@@ 846,5 851,5 @@ namespace app::manager
    auto ApplicationManagerCommon::handleDeveloperModeRequest(sys::Message *request) -> sys::MessagePointer
    {
        return sys::msgNotHandled();
    };
    }
} // namespace app::manager

M module-services/service-eink/CMakeLists.txt => module-services/service-eink/CMakeLists.txt +5 -3
@@ 14,9 14,11 @@ add_library(${PROJECT_NAME} STATIC ${SOURCES})
add_board_subdirectory(board)

target_link_libraries( ${PROJECT_NAME}
    module-utils
    service-gui
    Microsoft.GSL::GSL
        module-utils
        module-bsp
        Microsoft.GSL::GSL
        messagetype
        module-sys
)

target_include_directories(${PROJECT_NAME}

M module-services/service-eink/EinkDisplay.hpp => module-services/service-eink/EinkDisplay.hpp +1 -2
@@ 3,9 3,8 @@

#pragma once

#include <gui/Common.hpp>

#include <EinkIncludes.hpp>
#include <gui/Common.hpp>
#include "Common.hpp"

#include <cstdint>

M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +1 -21
@@ 6,7 6,6 @@
#include "internal/StaticData.hpp"
#include "messages/EinkModeMessage.hpp"
#include "messages/PrepareDisplayEarlyRequest.hpp"
#include <service-gui/messages/EinkInitialized.hpp>
#include <time/ScopedTime.hpp>
#include <Timers/TimerFactory.hpp>



@@ 42,7 41,7 @@ namespace service::eink
    ServiceEink::ServiceEink(ExitAction exitAction, const std::string &name, std::string parent)
        : sys::Service(name, std::move(parent), ServceEinkStackDepth),
          exitAction{exitAction}, display{{BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y}},
          currentState{State::Running}, waitingForLastRender{false}, settings{std::make_unique<settings::Settings>()}
          currentState{State::Running}, settings{std::make_unique<settings::Settings>()}
    {
        displayPowerOffTimer = sys::TimerFactory::createSingleShotTimer(
            this, "einkDisplayPowerOff", displayPowerOffTimeout, [this](sys::Timer &) { display.powerOff(); });


@@ 52,9 51,6 @@ namespace service::eink
        connect(typeid(ImageMessage),
                [this](sys::Message *request) -> sys::MessagePointer { return handleImageMessage(request); });

        connect(typeid(ShutdownImageMessage),
                [this](sys::Message *request) -> sys::MessagePointer { return handleShutdownImageMessage(request); });

        connect(typeid(PrepareDisplayEarlyRequest),
                [this](sys::Message *request) -> sys::MessagePointer { return handlePrepareEarlyRequest(request); });



@@ 86,8 82,6 @@ namespace service::eink

        display.powerOn();

        auto msg = std::make_shared<service::gui::EinkInitialized>(display.getSize());
        bus.sendUnicast(msg, service::name::gui);
        return sys::ReturnCodes::Success;
    }



@@ 176,15 170,6 @@ namespace service::eink
        return std::make_shared<service::eink::ImageDisplayedNotification>(message->getContextId());
    }

    sys::MessagePointer ServiceEink::handleShutdownImageMessage(sys::Message *request)
    {
        if (waitingForLastRender) {
            isReady = false;
            sendCloseReadyMessage(this);
        };
        return handleImageMessage(request);
    }

    void ServiceEink::showImage(std::uint8_t *frameBuffer, ::gui::RefreshModes refreshMode)
    {
        displayPowerOffTimer.stop();


@@ 258,9 243,4 @@ namespace service::eink
        return currentState == state;
    }

    void ServiceEink::ProcessCloseReasonHandler(sys::CloseReason closeReason)
    {
        waitingForLastRender = true;
    }

} // namespace service::eink

M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +1 -6
@@ 13,7 13,6 @@

#include <service-db/DBServiceName.hpp>
#include <service-db/Settings.hpp>
#include <service-gui/Common.hpp>

#include <chrono>
#include <cstdint>


@@ 68,17 67,13 @@ namespace service::eink

        sys::MessagePointer handleEinkModeChangedMessage(sys::Message *message);
        sys::MessagePointer handleImageMessage(sys::Message *message);
        sys::MessagePointer handleShutdownImageMessage(sys::Message *message);
        sys::MessagePointer handlePrepareEarlyRequest(sys::Message *message);

        auto ProcessCloseReasonHandler(sys::CloseReason closeReason) -> void override;

        void initStaticData();

        ExitAction exitAction;
        EinkDisplay display;
        State currentState;
        bool waitingForLastRender;
        sys::TimerHandle displayPowerOffTimer;
        std::shared_ptr<EinkSentinel> eInkSentinel;
        std::unique_ptr<settings::Settings> settings;


@@ 93,7 88,7 @@ namespace sys
        {
            ServiceManifest manifest;
            manifest.name         = service::name::eink;
            manifest.dependencies = {service::name::db, service::name::gui};
            manifest.dependencies = {service::name::db};
            return manifest;
        }
    };

M module-services/service-gui/CMakeLists.txt => module-services/service-gui/CMakeLists.txt +0 -1
@@ 14,7 14,6 @@ target_sources(service-gui
        service-gui/ServiceGUI.hpp
        service-gui/messages/ChangeColorScheme.hpp
        service-gui/messages/DrawMessage.hpp
        service-gui/messages/EinkInitialized.hpp
        service-gui/messages/GUIMessage.hpp
        service-gui/messages/RenderingFinished.hpp
    PRIVATE

M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +27 -70
@@ 5,8 5,6 @@
#include "WorkerGUI.hpp"

#include "messages/DrawMessage.hpp"

#include "messages/EinkInitialized.hpp"
#include "messages/ChangeColorScheme.hpp"

#include <DrawCommand.hpp>


@@ 43,10 41,9 @@ namespace service::gui
        }
    } // namespace

    ServiceGUI::ServiceGUI(const std::string &name, std::string parent)
        : sys::Service(name, parent, ServiceGuiStackDepth), commandsQueue{std::make_unique<DrawCommandsQueue>(
                                                                CommandsQueueCapacity)},
          currentState{State::NotInitialised}, lastRenderScheduled{false}, waitingForLastRender{false}
    ServiceGUI::ServiceGUI(::gui::Size displaySize, const std::string &name, std::string parent)
        : sys::Service(name, parent, ServiceGuiStackDepth), displaySize{displaySize},
          commandsQueue{std::make_unique<DrawCommandsQueue>(CommandsQueueCapacity)}
    {
        initAssetManagers();
        registerMessageHandlers();


@@ 63,9 60,6 @@ namespace service::gui

    void ServiceGUI::registerMessageHandlers()
    {
        connect(typeid(EinkInitialized),
                [this](sys::Message *request) -> sys::MessagePointer { return handleEinkInitialized(request); });

        connect(typeid(DrawMessage),
                [this](sys::Message *request) -> sys::MessagePointer { return handleDrawMessage(request); });



@@ 87,6 81,8 @@ namespace service::gui

    sys::ReturnCodes ServiceGUI::InitHandler()
    {
        contextPool = std::make_unique<ContextPool>(displaySize, ContextsCount);

        std::list<sys::WorkerQueueInfo> queueInfo{
            {WorkerGUI::SignallingQueueName, WorkerGUI::SignalSize, WorkerGUI::SignallingQueueCapacity}};
        worker = std::make_unique<WorkerGUI>(this);


@@ 103,7 99,13 @@ namespace service::gui

    void ServiceGUI::ProcessCloseReason(sys::CloseReason closeReason)
    {
        waitingForLastRender = true;
        if (not isDisplaying and not isRendering) {
            sendCloseReadyMessage(this);
            return;
        }
        else {
            isClosing = true;
        }
    }

    void ServiceGUI::ProcessCloseReasonHandler(sys::CloseReason closeReason)


@@ 114,37 116,12 @@ namespace service::gui
    sys::ReturnCodes ServiceGUI::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
    {
        LOG_INFO("PowerModeHandler: %s", c_str(mode));
        switch (mode) {
        case sys::ServicePowerMode::Active:
            setState(contextPool != nullptr ? State::Idle : State::NotInitialised);
            break;
        case sys::ServicePowerMode::SuspendToRAM:
            [[fallthrough]];
        case sys::ServicePowerMode::SuspendToNVM:
            setState(State::Suspended);
            break;
        }
        return sys::ReturnCodes::Success;
    }

    sys::MessagePointer ServiceGUI::handleDrawMessage(sys::Message *message)
    {
        if (isInState(State::NotInitialised)) {
            LOG_WARN("Service not yet initialised - ignoring draw commands");
            return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
        }
        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::SUSPEND)) {
                setState(State::Suspended);
            }
            else if (drawMsg->isType(DrawMessage::Type::SHUTDOWN)) {
                lastRenderScheduled = true;
            }
            if (!isAnyFrameBeingRenderedOrDisplayed()) {
                prepareDisplayEarly(drawMsg->mode);
            }


@@ 169,6 146,7 @@ namespace service::gui
    void ServiceGUI::notifyRenderer(std::list<std::unique_ptr<::gui::DrawCommand>> &&commands,
                                    ::gui::RefreshModes refreshMode)
    {
        isRendering = true;
        enqueueDrawCommands(DrawCommandsQueue::QueueItem{std::move(commands), refreshMode});
        worker->notify(WorkerGUI::Signal::Render);
    }


@@ 195,10 173,12 @@ namespace service::gui

    sys::MessagePointer ServiceGUI::handleGUIRenderingFinished(sys::Message *message)
    {
        isRendering          = false;
        auto finishedMsg     = static_cast<service::gui::RenderingFinished *>(message);
        const auto contextId = finishedMsg->getContextId();
        auto refreshMode     = finishedMsg->getRefreshMode();
        if (isInState(State::Idle)) {

        if (not isDisplaying) {
            if (cache.isRenderCached()) {
                refreshMode = getMaxRefreshMode(cache.getCachedRender()->refreshMode, refreshMode);
                cache.invalidate();


@@ 215,14 195,9 @@ namespace service::gui

    void ServiceGUI::sendOnDisplay(::gui::Context *context, int contextId, ::gui::RefreshModes refreshMode)
    {
        setState(State::Busy);
        isDisplaying = true;
        std::shared_ptr<service::eink::ImageMessage> imageMsg;
        if (waitingForLastRender) {
            imageMsg = std::make_shared<service::eink::ShutdownImageMessage>(contextId, context, refreshMode);
        }
        else {
            imageMsg = std::make_shared<service::eink::ImageMessage>(contextId, context, refreshMode);
        }
        imageMsg = std::make_shared<service::eink::ImageMessage>(contextId, context, refreshMode);
        bus.sendUnicast(imageMsg, service::name::eink);
        scheduleContextRelease(contextId);
    }


@@ 240,32 215,24 @@ namespace service::gui
        contextReleaseTimer.start();
    }

    sys::MessagePointer ServiceGUI::handleEinkInitialized(sys::Message *message)
    {
        const auto msg = static_cast<service::gui::EinkInitialized *>(message);
        contextPool    = std::make_unique<ContextPool>(msg->getDisplaySize(), ContextsCount);
        setState(State::Idle);
        return sys::MessageNone{};
    }

    sys::MessagePointer ServiceGUI::handleImageDisplayedNotification(sys::Message *message)
    {
        isDisplaying         = false;
        const auto msg       = static_cast<eink::ImageDisplayedNotification *>(message);
        const auto contextId = msg->getContextId();
        contextPool->returnContext(contextId);
        contextReleaseTimer.stop();
        setState(State::Idle);

        // Even if the next render is already cached, if any context in the pool is currently being processed, then
        // we better wait for it.
        if (isNextFrameReady() and not isAnyFrameBeingRenderedOrDisplayed()) {
            trySendNextFrame();
        }
        else if (lastRenderScheduled && waitingForLastRender) {
            isReady = false;
        if (isClosing) {
            sendCloseReadyMessage(this);
        }

        else {
            // Even if the next render is already cached, if any context in the pool is currently being processed, then
            // we better wait for it.
            if (isNextFrameReady() and not isAnyFrameBeingRenderedOrDisplayed()) {
                trySendNextFrame();
            }
        }
        return sys::MessageNone{};
    }



@@ 287,14 254,4 @@ namespace service::gui
        }
        cache.invalidate();
    }

    void ServiceGUI::setState(State state) noexcept
    {
        currentState = state;
    }

    bool ServiceGUI::isInState(State state) const noexcept
    {
        return currentState == state;
    }
} // namespace service::gui

M module-services/service-gui/WorkerGUI.cpp => module-services/service-gui/WorkerGUI.cpp +0 -1
@@ 5,7 5,6 @@

#include <DrawCommand.hpp>
#include <log/log.hpp>
#include <Renderer.hpp>
#include <Service/Worker.hpp>
#include <service-gui/ServiceGUI.hpp>


M module-services/service-gui/service-gui/ServiceGUI.hpp => module-services/service-gui/service-gui/ServiceGUI.hpp +9 -18
@@ 13,8 13,7 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Timers/TimerHandle.hpp>

#include <service-db/DBServiceName.hpp>
#include <service-eink/Common.hpp>

#include <cstdint>
#include <memory>


@@ 35,7 34,9 @@ namespace service::gui
        friend WorkerGUI;

      public:
        explicit ServiceGUI(const std::string &name = service::name::gui, std::string parent = {});
        explicit ServiceGUI(::gui::Size displaySize,
                            const std::string &name = service::name::gui,
                            std::string parent      = {});
        ~ServiceGUI() noexcept override;

        sys::ReturnCodes InitHandler() override;


@@ 46,13 47,9 @@ namespace service::gui
        sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;

      private:
        enum class State
        {
            NotInitialised,
            Idle,
            Busy,
            Suspended
        };
        bool isRendering{};
        bool isDisplaying{};
        bool isClosing{};

        static void initAssetManagers();
        void registerMessageHandlers();


@@ 67,24 64,18 @@ namespace service::gui
        bool isAnyFrameBeingRenderedOrDisplayed() const noexcept;
        void trySendNextFrame();

        void setState(State state) noexcept;
        bool isInState(State state) const noexcept;

        sys::MessagePointer handleDrawMessage(sys::Message *message);
        sys::MessagePointer handleGUIRenderingFinished(sys::Message *message);
        sys::MessagePointer handleEinkInitialized(sys::Message *message);
        sys::MessagePointer handleImageDisplayedNotification(sys::Message *message);
        sys::MessagePointer handleChangeColorScheme(sys::Message *message);

        ::gui::Size displaySize;
        std::unique_ptr<ContextPool> contextPool;
        std::unique_ptr<WorkerGUI> worker;
        std::unique_ptr<DrawCommandsQueue> commandsQueue;
        std::unique_ptr<::gui::ColorScheme> colorSchemeUpdate;
        RenderCache cache;
        sys::TimerHandle contextReleaseTimer;
        State currentState;
        bool lastRenderScheduled;
        bool waitingForLastRender;
    };
} // namespace service::gui



@@ 96,7 87,7 @@ namespace sys
        {
            ServiceManifest manifest;
            manifest.name         = service::name::gui;
            manifest.dependencies = {service::name::db};
            manifest.dependencies = {service::name::eink};
            return manifest;
        }
    };

M module-services/service-gui/service-gui/messages/DrawMessage.hpp => module-services/service-gui/service-gui/messages/DrawMessage.hpp +1 -2
@@ 24,8 24,7 @@ namespace service::gui
        enum class Type
        {
            NORMAL,
            SUSPEND,
            SHUTDOWN
            SUSPEND
        } type = Type::NORMAL;

      public:

D module-services/service-gui/service-gui/messages/EinkInitialized.hpp => module-services/service-gui/service-gui/messages/EinkInitialized.hpp +0 -26
@@ 1,26 0,0 @@
// 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 "GUIMessage.hpp"

#include <gui/Common.hpp>

namespace service::gui
{
    class EinkInitialized : public GUIMessage
    {
      public:
        explicit EinkInitialized(::gui::Size displaySize) : einkDisplaySize{displaySize}
        {}

        [[nodiscard]] auto getDisplaySize() const noexcept -> ::gui::Size
        {
            return einkDisplaySize;
        }

      private:
        ::gui::Size einkDisplaySize;
    };
} // namespace service::gui

M module-sys/SystemManager/SystemManagerCommon.cpp => module-sys/SystemManager/SystemManagerCommon.cpp +60 -54
@@ 40,8 40,27 @@ namespace sys
{
    namespace
    {
        constexpr std::chrono::milliseconds preShutdownRoutineTimeout{1500};
        constexpr std::chrono::milliseconds serviceCloseResponseTimeout{1500};
        constexpr std::chrono::milliseconds lowBatteryShutdownDelayTime{5000};

        app::manager::StartupType toStartupType(Store::Battery::LevelState state)
        {
            using bState = Store::Battery::LevelState;
            using sState = app::manager::StartupType;

            switch (state) {
            case bState::Normal:
                return sState::Regular;
            case bState::Shutdown:
                return sState::CriticalBattery;
            case bState::CriticalNotCharging:
                return sState::LowBattery;
            case bState::CriticalCharging:
                return sState::LowBatteryCharging;
            }
            return sState::Regular;
        }

    } // namespace

    namespace state


@@ 444,20 463,41 @@ namespace sys
        return "none";
    }

    void SystemManagerCommon::preCloseRoutine(CloseReason closeReason)
    void SystemManagerCommon::InitiateSystemCloseSequence(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());
            servicesToClose.push_back(service->GetName());
        }

        // stored to be used later in CloseServices
        this->closeReason = closeReason;

        servicesPreShutdownRoutineTimeout = sys::TimerFactory::createPeriodicTimer(
            this, "servicesPreShutdownRoutine", preShutdownRoutineTimeout, [this](sys::Timer &) { CloseServices(); });
        servicesPreShutdownRoutineTimeout.start();
        serviceCloseTimer = sys::TimerFactory::createSingleShotTimer(
            this, "serviceCloseTimer", serviceCloseResponseTimeout, [this](sys::Timer &) { CloseServices(); });
        serviceCloseTimer.start();

        /// Start the sequence by sending close request to the first service on the list
        bus.sendUnicast(std::make_shared<ServiceCloseReasonMessage>(closeReason), servicesToClose.front());
    }

    void SystemManagerCommon::ServiceReadyToCloseHandler(Message *msg)
    {
        if (!servicesToClose.empty() && serviceCloseTimer.isActive()) {
            serviceCloseTimer.stop();

            const auto message = static_cast<ReadyToCloseMessage *>(msg);
            LOG_INFO("ready to close %s", message->sender.c_str());
            servicesToClose.erase(std::remove(servicesToClose.begin(), servicesToClose.end(), message->sender),
                                  servicesToClose.end());

            // All services responded
            if (servicesToClose.empty()) {
                LOG_INFO("All services ready to close.");
                CloseServices();
            }
            else {
                bus.sendUnicast(std::make_shared<ServiceCloseReasonMessage>(closeReason), servicesToClose.front());
                serviceCloseTimer.start();
            }
        }
    }

    void SystemManagerCommon::postStartRoutine()


@@ 489,7 529,9 @@ namespace sys
    void SystemManagerCommon::batteryShutdownLevelAction()
    {
        LOG_INFO("Battery level too low - shutting down the system...");
        CloseSystemHandler(CloseReason::LowBattery);
        if (!lowBatteryShutdownDelay.isActive()) {
            lowBatteryShutdownDelay.start();
        }
    }

    void SystemManagerCommon::batteryNormalLevelAction()


@@ 497,24 539,6 @@ namespace sys
        LOG_INFO("Battery level normal.");
    }

    void SystemManagerCommon::readyToCloseHandler(Message *msg)
    {
        if (!readyForCloseRegister.empty() && servicesPreShutdownRoutineTimeout.isActive()) {
            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 SystemManagerCommon::kill(std::shared_ptr<Service> const &toKill)
    {
        auto ret = toKill->DeinitHandler();


@@ 586,7 610,7 @@ namespace sys
        });

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



@@ 643,27 667,9 @@ namespace sys
        });

        connect(typeid(app::manager::CheckIfStartAllowedMessage), [this](sys::Message *) -> sys::MessagePointer {
            switch (Store::Battery::get().levelState) {
            case Store::Battery::LevelState::Normal:
                bus.sendUnicast(std::make_unique<app::manager::StartAllowedMessage>(app::manager::StartupType::Regular),
                                service::name::appmgr);
                break;
            case Store::Battery::LevelState::Shutdown:
                if (!lowBatteryShutdownDelay.isActive()) {
                    lowBatteryShutdownDelay.start();
                }
                [[fallthrough]];
            case Store::Battery::LevelState::CriticalNotCharging:
                bus.sendUnicast(
                    std::make_unique<app::manager::StartAllowedMessage>(app::manager::StartupType::LowBattery),
                    service::name::appmgr);
                break;
            case Store::Battery::LevelState::CriticalCharging:
                bus.sendUnicast(
                    std::make_unique<app::manager::StartAllowedMessage>(app::manager::StartupType::LowBatteryCharging),
                    service::name::appmgr);
                break;
            }
            bus.sendUnicast(
                std::make_unique<app::manager::StartAllowedMessage>(toStartupType(Store::Battery::get().levelState)),
                service::name::appmgr);
            return sys::MessageNone{};
        });



@@ 697,16 703,16 @@ namespace sys
        std::reverse(servicesList.begin(), servicesList.end());
        CriticalSection::Exit();

        preCloseRoutine(closeReason);
        InitiateSystemCloseSequence(closeReason);
    }

    void SystemManagerCommon::CloseServices()
    {
        for (const auto &element : readyForCloseRegister) {
        for (const auto &element : servicesToClose) {
            LOG_INFO("Service: %s did not reported before timeout", element.c_str());
        }
        // All delayed messages will be ignored
        readyForCloseRegister.clear();
        servicesToClose.clear();

        switch (closeReason) {
        case CloseReason::RegularPowerDown:

M module-sys/SystemManager/doc/SystemCloseSequence.md => module-sys/SystemManager/doc/SystemCloseSequence.md +2 -3
@@ 2,9 2,8 @@

Regular power down via menu

![](./system_close_procedure_user.svg)

![](system_close_procedure_user.svg)

Close at Brownout event

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

M module-sys/SystemManager/doc/system_close_procedure_brownout.puml => module-sys/SystemManager/doc/system_close_procedure_brownout.puml +1 -1
@@ 8,7 8,7 @@ participant "Service GUI" as gui
participant "service EINK" as eink

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

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(Dead Battery Window)

M module-sys/SystemManager/doc/system_close_procedure_brownout.svg => module-sys/SystemManager/doc/system_close_procedure_brownout.svg +3 -5
@@ 1,4 1,4 @@
<?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="520px" preserveAspectRatio="none" style="width:959px;height:520px;background:#F0F0F0;" version="1.1" viewBox="0 0 959 520" width="959px" zoomAndPan="magnify"><defs><filter height="300%" id="fhknj5rncvr09" 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="#F0F0F0" filter="url(#fhknj5rncvr09)" height="59.2656" style="stroke: #000000; stroke-width: 2.0;" width="182.5" x="59.5" y="272.2266"/><rect fill="#F0F0F0" filter="url(#fhknj5rncvr09)" height="59.2656" style="stroke: #000000; stroke-width: 2.0;" width="160.5" x="59.5" y="403.7578"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="135.5" x2="135.5" y1="38.2969" y2="480.0234"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="327" x2="327" y1="38.2969" y2="480.0234"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="482.5" x2="482.5" y1="38.2969" y2="480.0234"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="778" x2="778" y1="38.2969" y2="480.0234"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="901" x2="901" y1="38.2969" y2="480.0234"/><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="129" x="69.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="115" x="76.5" y="22.9951">System Manager</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="129" x="69.5" y="479.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="115" x="76.5" y="499.0186">System Manager</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="280" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="76" x="287" y="22.9951">All services</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="280" y="479.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="76" x="287" y="499.0186">All services</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="153" x="404.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="139" x="411.5" y="22.9951">Application Manager</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="153" x="404.5" y="479.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="139" x="411.5" y="499.0186">Application Manager</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="730" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="78" x="737" y="22.9951">Service GUI</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="730" y="479.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="78" x="737" y="499.0186">Service GUI</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="98" x="850" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="84" x="857" y="22.9951">service EINK</text><rect fill="#FEFECE" filter="url(#fhknj5rncvr09)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="98" x="850" y="479.0234"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="84" x="857" y="499.0186">service EINK</text><polygon fill="#A80036" points="124,65.4297,134,69.4297,124,73.4297,128,69.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="3" x2="130" y1="69.4297" y2="69.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="109" x="10" y="64.3638">battery brownout</text><polygon fill="#A80036" points="315,94.5625,325,98.5625,315,102.5625,319,98.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="136" x2="321" y1="98.5625" y2="98.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="104" x="143" y="93.4966">preCloseRoutine</text><polygon fill="#A80036" points="471,123.6953,481,127.6953,471,131.6953,475,127.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="327" x2="477" y1="127.6953" y2="127.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="132" x="334" y="122.6294">processCloseReason</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="483" x2="525" y1="156.8281" y2="156.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="525" x2="525" y1="156.8281" y2="169.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="484" x2="525" y1="169.8281" y2="169.8281"/><polygon fill="#A80036" points="494,165.8281,484,169.8281,494,173.8281,490,169.8281" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="281" x="490" y="151.7622">switchWindowAtClose(Dead Battery Window)</text><polygon fill="#A80036" points="789,194.9609,779,198.9609,789,202.9609,785,198.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="783" x2="900" y1="198.9609" y2="198.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="99" x="795" y="193.895">last sreen show</text><polygon fill="#A80036" points="338,224.0938,328,228.0938,338,232.0938,334,228.0938" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="332" x2="777" y1="228.0938" y2="228.0938"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="90" x="344" y="223.0278">ready to close</text><polygon fill="#A80036" points="147,253.2266,137,257.2266,147,261.2266,143,257.2266" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="141" x2="326" y1="257.2266" y2="257.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="86" x="153" y="252.1606">readyToClose</text><path d="M59.5,272.2266 L123.5,272.2266 L123.5,279.2266 L113.5,289.2266 L59.5,289.2266 L59.5,272.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="59.5" y="272.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="19" x="74.5" y="285.2935">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="59" x="138.5" y="284.437">[timeout]</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="136" x2="178" y1="310.4922" y2="310.4922"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="178" x2="178" y1="310.4922" y2="323.4922"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="137" x2="178" y1="323.4922" y2="323.4922"/><polygon fill="#A80036" points="147,319.4922,137,323.4922,147,327.4922,143,323.4922" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="87" x="143" y="305.4263">closeServices</text><polygon fill="#A80036" points="315,355.625,325,359.625,315,363.625,319,359.625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="136" x2="321" y1="359.625" y2="359.625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="167" x="143" y="354.5591">SystemMessageType::Exit</text><polygon fill="#A80036" points="147,384.7578,137,388.7578,147,392.7578,143,388.7578" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="141" x2="326" y1="388.7578" y2="388.7578"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="79" x="153" y="383.6919">MsgHandled</text><path d="M59.5,403.7578 L123.5,403.7578 L123.5,410.7578 L113.5,420.7578 L59.5,420.7578 L59.5,403.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="59.5" y="403.7578"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="19" x="74.5" y="416.8247">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="59" x="138.5" y="415.9683">[timeout]</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="136" x2="178" y1="442.0234" y2="442.0234"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="178" x2="178" y1="442.0234" y2="455.0234"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="137" x2="178" y1="455.0234" y2="455.0234"/><polygon fill="#A80036" points="147,451.0234,137,455.0234,147,459.0234,143,455.0234" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="65" x="143" y="436.9575">kill service</text><!--MD5=[210197d7022123c369a910652d598c70]
<?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="564px" preserveAspectRatio="none" style="width:938px;height:564px;background:#F0F0F0;" version="1.1" viewBox="0 0 938 564" width="938px" zoomAndPan="magnify"><defs><filter height="300%" id="f1pw8gm80p6qkb" 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="#F0F0F0" filter="url(#f1pw8gm80p6qkb)" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="172.5" x="55.5" y="295.01"/><rect fill="#F0F0F0" filter="url(#f1pw8gm80p6qkb)" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="154.5" x="55.5" y="436.8341"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="130.5" x2="130.5" y1="43.0679" y2="518.2461"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="330.5" x2="330.5" y1="43.0679" y2="518.2461"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="476.5" x2="476.5" y1="43.0679" y2="518.2461"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="760.5" x2="760.5" y1="43.0679" y2="518.2461"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="877" x2="877" y1="43.0679" y2="518.2461"/><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="127" x="65.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="113" x="72.5" y="26.9659">System Manager</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="127" x="65.5" y="517.2461"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="113" x="72.5" y="539.2121">System Manager</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="89" x="284.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="75" x="291.5" y="26.9659">All services</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="89" x="284.5" y="517.2461"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="75" x="291.5" y="539.2121">All services</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="155" x="397.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="141" x="404.5" y="26.9659">Application Manager</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="155" x="397.5" y="517.2461"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="141" x="404.5" y="539.2121">Application Manager</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="91" x="713.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="720.5" y="26.9659">Service GUI</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="91" x="713.5" y="517.2461"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="720.5" y="539.2121">Service GUI</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="98" x="826" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="833" y="26.9659">service EINK</text><rect fill="#FEFECE" filter="url(#f1pw8gm80p6qkb)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="98" x="826" y="517.2461"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="833" y="539.2121">service EINK</text><polygon fill="#A80036" points="119,72.7739,129,76.7739,119,80.7739,123,76.7739" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="0" x2="125" y1="76.7739" y2="76.7739"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="107" x="7" y="70.9649">battery brownout</text><polygon fill="#A80036" points="319,104.4799,329,108.4799,319,112.4799,323,108.4799" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="131" x2="325" y1="108.4799" y2="108.4799"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="176" x="138" y="102.6709">InitiateSystemCloseSequence</text><polygon fill="#A80036" points="465,136.186,475,140.186,465,144.186,469,140.186" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="331" x2="471" y1="140.186" y2="140.186"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="122" x="338" y="134.377">processCloseReason</text><line style="stroke:#A80036;stroke-width:1.0;" x1="477" x2="519" y1="171.892" y2="171.892"/><line style="stroke:#A80036;stroke-width:1.0;" x1="519" x2="519" y1="171.892" y2="184.892"/><line style="stroke:#A80036;stroke-width:1.0;" x1="478" x2="519" y1="184.892" y2="184.892"/><polygon fill="#A80036" points="488,180.892,478,184.892,488,188.892,484,184.892" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="270" x="484" y="166.083">switchWindowAtClose(Dead Battery Window)</text><polygon fill="#A80036" points="772,212.598,762,216.598,772,220.598,768,216.598" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="766" x2="876" y1="216.598" y2="216.598"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="92" x="778" y="210.789">last sreen show</text><polygon fill="#A80036" points="342,244.304,332,248.304,342,252.304,338,248.304" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="336" x2="760" y1="248.304" y2="248.304"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="83" x="348" y="242.495">ready to close</text><polygon fill="#A80036" points="142,276.01,132,280.01,142,284.01,138,280.01" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="136" x2="330" y1="280.01" y2="280.01"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="81" x="148" y="274.201">readyToClose</text><path d="M55.5,295.01 L118.5,295.01 L118.5,304.01 L108.5,314.01 L55.5,314.01 L55.5,295.01 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="172.5" x="55.5" y="295.01"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="18" x="70.5" y="309.907">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="53" x="133.5" y="308.7689">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="131" x2="173" y1="338.4221" y2="338.4221"/><line style="stroke:#A80036;stroke-width:1.0;" x1="173" x2="173" y1="338.4221" y2="351.4221"/><line style="stroke:#A80036;stroke-width:1.0;" x1="132" x2="173" y1="351.4221" y2="351.4221"/><polygon fill="#A80036" points="142,347.4221,132,351.4221,142,355.4221,138,351.4221" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="78" x="138" y="332.6131">closeServices</text><polygon fill="#A80036" points="319,386.1281,329,390.1281,319,394.1281,323,390.1281" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="131" x2="325" y1="390.1281" y2="390.1281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="154" x="138" y="384.3191">SystemMessageType::Exit</text><polygon fill="#A80036" points="142,417.8341,132,421.8341,142,425.8341,138,421.8341" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="136" x2="330" y1="421.8341" y2="421.8341"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="77" x="148" y="416.0251">MsgHandled</text><path d="M55.5,436.8341 L118.5,436.8341 L118.5,445.8341 L108.5,455.8341 L55.5,455.8341 L55.5,436.8341 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="154.5" x="55.5" y="436.8341"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="18" x="70.5" y="451.7311">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="53" x="133.5" y="450.593">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="131" x2="173" y1="480.2461" y2="480.2461"/><line style="stroke:#A80036;stroke-width:1.0;" x1="173" x2="173" y1="480.2461" y2="493.2461"/><line style="stroke:#A80036;stroke-width:1.0;" x1="132" x2="173" y1="493.2461" y2="493.2461"/><polygon fill="#A80036" points="142,489.2461,132,493.2461,142,497.2461,138,493.2461" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="60" x="138" y="474.4371">kill service</text><!--MD5=[dc32efee2c8c59b6247c204766715b97]
@startuml
skinparam BackgroundColor F0F0F0



@@ 9,7 9,7 @@ participant "Service GUI" as gui
participant "service EINK" as eink

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

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(Dead Battery Window)


@@ 28,12 28,10 @@ end

@enduml

PlantUML version 1.2020.02(Sun Mar 01 05:22:07 EST 2020)
PlantUML version 1.2021.7(Sun May 23 14:40:07 CEST 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 11.0.12+7-post-Debian-2
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: US

M module-sys/SystemManager/doc/system_close_procedure_user.puml => module-sys/SystemManager/doc/system_close_procedure_user.puml +1 -1
@@ 13,7 13,7 @@ participant "service EINK" as eink
User -> poff : confirm close
poff -> app : GUI off switch
app -> sysmgr : UserPowerDownRequest
sysmgr -> srv : preCloseRoutine
sysmgr -> srv : InitiateSystemCloseSequence

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(logo)

M module-sys/SystemManager/doc/system_close_procedure_user.svg => module-sys/SystemManager/doc/system_close_procedure_user.svg +3 -5
@@ 1,4 1,4 @@
<?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="673px" preserveAspectRatio="none" style="width:1152px;height:673px;background:#F0F0F0;" version="1.1" viewBox="0 0 1152 673" width="1152px" zoomAndPan="magnify"><defs><filter height="300%" id="fdnpftd7rchiv" 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="#F0F0F0" filter="url(#fdnpftd7rchiv)" height="59.2656" style="stroke: #000000; stroke-width: 2.0;" width="182.5" x="362" y="378.4922"/><rect fill="#F0F0F0" filter="url(#fdnpftd7rchiv)" height="59.2656" style="stroke: #000000; stroke-width: 2.0;" width="160.5" x="362" y="510.0234"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="27" x2="27" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="136" x2="136" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="259" x2="259" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="438" x2="438" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="629.5" x2="629.5" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="785" x2="785" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="971.5" x2="971.5" y1="86.2969" y2="586.2891"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="1094.5" x2="1094.5" y1="86.2969" y2="586.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="32" x="8" y="82.9951">User</text><ellipse cx="27" cy="13" fill="#FEFECE" filter="url(#fdnpftd7rchiv)" rx="8" ry="8" style="stroke: #A80036; stroke-width: 2.0;"/><path d="M27,21 L27,48 M14,29 L40,29 M27,48 L14,63 M27,48 L40,63 " fill="none" filter="url(#fdnpftd7rchiv)" style="stroke: #A80036; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="32" x="8" y="598.2842">User</text><ellipse cx="27" cy="611.5859" fill="#FEFECE" filter="url(#fdnpftd7rchiv)" rx="8" ry="8" style="stroke: #A80036; stroke-width: 2.0;"/><path d="M27,619.5859 L27,646.5859 M14,627.5859 L40,627.5859 M27,646.5859 L14,661.5859 M27,646.5859 L40,661.5859 " fill="none" filter="url(#fdnpftd7rchiv)" style="stroke: #A80036; stroke-width: 2.0;"/><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="130" x="69" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="116" x="76" y="70.9951">PowerOffWindow</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="130" x="69" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="116" x="76" y="605.2842">PowerOffWindow</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="89" x="213" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="75" x="220" y="70.9951">Application</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="89" x="213" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="75" x="220" y="605.2842">Application</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="129" x="372" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="115" x="379" y="70.9951">System Manager</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="129" x="372" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="115" x="379" y="605.2842">System Manager</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="582.5" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="76" x="589.5" y="70.9951">All services</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="582.5" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="76" x="589.5" y="605.2842">All services</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="153" x="707" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="139" x="714" y="70.9951">Application Manager</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="153" x="707" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="139" x="714" y="605.2842">Application Manager</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="923.5" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="78" x="930.5" y="70.9951">Service GUI</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="923.5" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="78" x="930.5" y="605.2842">Service GUI</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="98" x="1043.5" y="51"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="84" x="1050.5" y="70.9951">service EINK</text><rect fill="#FEFECE" filter="url(#fdnpftd7rchiv)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="98" x="1043.5" y="585.2891"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="84" x="1050.5" y="605.2842">service EINK</text><polygon fill="#A80036" points="124,113.4297,134,117.4297,124,121.4297,128,117.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="27" x2="130" y1="117.4297" y2="117.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="85" x="34" y="112.3638">confirm close</text><polygon fill="#A80036" points="247.5,142.5625,257.5,146.5625,247.5,150.5625,251.5,146.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="136" x2="253.5" y1="146.5625" y2="146.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="86" x="143" y="141.4966">GUI off switch</text><polygon fill="#A80036" points="426.5,171.6953,436.5,175.6953,426.5,179.6953,430.5,175.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="259.5" x2="432.5" y1="175.6953" y2="175.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="155" x="266.5" y="170.6294">UserPowerDownRequest</text><polygon fill="#A80036" points="617.5,200.8281,627.5,204.8281,617.5,208.8281,621.5,204.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="438.5" x2="623.5" y1="204.8281" y2="204.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="104" x="445.5" y="199.7622">preCloseRoutine</text><polygon fill="#A80036" points="773.5,229.9609,783.5,233.9609,773.5,237.9609,777.5,233.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="629.5" x2="779.5" y1="233.9609" y2="233.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="132" x="636.5" y="228.895">processCloseReason</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="785.5" x2="827.5" y1="263.0938" y2="263.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="827.5" x2="827.5" y1="263.0938" y2="276.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="786.5" x2="827.5" y1="276.0938" y2="276.0938"/><polygon fill="#A80036" points="796.5,272.0938,786.5,276.0938,796.5,280.0938,792.5,276.0938" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="172" x="792.5" y="258.0278">switchWindowAtClose(logo)</text><polygon fill="#A80036" points="982.5,301.2266,972.5,305.2266,982.5,309.2266,978.5,305.2266" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="976.5" x2="1093.5" y1="305.2266" y2="305.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="99" x="988.5" y="300.1606">last sreen show</text><polygon fill="#A80036" points="640.5,330.3594,630.5,334.3594,640.5,338.3594,636.5,334.3594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="634.5" x2="970.5" y1="334.3594" y2="334.3594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="90" x="646.5" y="329.2935">ready to close</text><polygon fill="#A80036" points="449.5,359.4922,439.5,363.4922,449.5,367.4922,445.5,363.4922" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="443.5" x2="628.5" y1="363.4922" y2="363.4922"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="86" x="455.5" y="358.4263">readyToClose</text><path d="M362,378.4922 L426,378.4922 L426,385.4922 L416,395.4922 L362,395.4922 L362,378.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="362" y="378.4922"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="19" x="377" y="391.5591">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="59" x="441" y="390.7026">[timeout]</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="438.5" x2="480.5" y1="416.7578" y2="416.7578"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="480.5" x2="480.5" y1="416.7578" y2="429.7578"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="439.5" x2="480.5" y1="429.7578" y2="429.7578"/><polygon fill="#A80036" points="449.5,425.7578,439.5,429.7578,449.5,433.7578,445.5,429.7578" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="87" x="445.5" y="411.6919">closeServices</text><polygon fill="#A80036" points="617.5,461.8906,627.5,465.8906,617.5,469.8906,621.5,465.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="438.5" x2="623.5" y1="465.8906" y2="465.8906"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="167" x="445.5" y="460.8247">SystemMessageType::Exit</text><polygon fill="#A80036" points="449.5,491.0234,439.5,495.0234,449.5,499.0234,445.5,495.0234" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="443.5" x2="628.5" y1="495.0234" y2="495.0234"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="79" x="455.5" y="489.9575">MsgHandled</text><path d="M362,510.0234 L426,510.0234 L426,517.0234 L416,527.0234 L362,527.0234 L362,510.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="362" y="510.0234"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="19" x="377" y="523.0903">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="59" x="441" y="522.2339">[timeout]</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="438.5" x2="480.5" y1="548.2891" y2="548.2891"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="480.5" x2="480.5" y1="548.2891" y2="561.2891"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="439.5" x2="480.5" y1="561.2891" y2="561.2891"/><polygon fill="#A80036" points="449.5,557.2891,439.5,561.2891,449.5,565.2891,445.5,561.2891" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="65" x="445.5" y="543.2231">kill service</text><!--MD5=[c7d7d97be0d6be1e0cc194251024e491]
<?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="716px" preserveAspectRatio="none" style="width:1128px;height:716px;background:#F0F0F0;" version="1.1" viewBox="0 0 1128 716" width="1128px" zoomAndPan="magnify"><defs><filter height="300%" id="fcxj0o41qrtzf" 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="#F0F0F0" filter="url(#fcxj0o41qrtzf)" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="172.5" x="349" y="406.4221"/><rect fill="#F0F0F0" filter="url(#fcxj0o41qrtzf)" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="154.5" x="349" y="548.2461"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="23" x2="23" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="126.5" x2="126.5" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="250.5" x2="250.5" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="424" x2="424" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="624" x2="624" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="770" x2="770" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="951" x2="951" y1="91.0679" y2="629.6582"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1067.5" x2="1067.5" y1="91.0679" y2="629.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="31" x="5" y="86.9659">User</text><ellipse cx="23.5" cy="15" fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" rx="8" ry="8" style="stroke:#A80036;stroke-width:2.0;"/><path d="M23.5,23 L23.5,50 M10.5,31 L36.5,31 M23.5,50 L10.5,65 M23.5,50 L36.5,65 " fill="none" filter="url(#fcxj0o41qrtzf)" style="stroke:#A80036;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="31" x="5" y="643.6241">User</text><ellipse cx="23.5" cy="657.7261" fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" rx="8" ry="8" style="stroke:#A80036;stroke-width:2.0;"/><path d="M23.5,665.7261 L23.5,692.7261 M10.5,673.7261 L36.5,673.7261 M23.5,692.7261 L10.5,707.7261 M23.5,692.7261 L36.5,707.7261 " fill="none" filter="url(#fcxj0o41qrtzf)" style="stroke:#A80036;stroke-width:2.0;"/><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="130" x="59.5" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="116" x="66.5" y="74.9659">PowerOffWindow</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="130" x="59.5" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="116" x="66.5" y="650.6241">PowerOffWindow</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="90" x="203.5" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="210.5" y="74.9659">Application</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="90" x="203.5" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="210.5" y="650.6241">Application</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="127" x="359" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="113" x="366" y="74.9659">System Manager</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="127" x="359" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="113" x="366" y="650.6241">System Manager</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="89" x="578" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="75" x="585" y="74.9659">All services</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="89" x="578" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="75" x="585" y="650.6241">All services</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="155" x="691" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="141" x="698" y="74.9659">Application Manager</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="155" x="691" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="141" x="698" y="650.6241">Application Manager</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="91" x="904" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="911" y="74.9659">Service GUI</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="91" x="904" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="911" y="650.6241">Service GUI</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="98" x="1016.5" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="1023.5" y="74.9659">service EINK</text><rect fill="#FEFECE" filter="url(#fcxj0o41qrtzf)" height="33.0679" style="stroke:#A80036;stroke-width:1.5;" width="98" x="1016.5" y="628.6582"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="1023.5" y="650.6241">service EINK</text><polygon fill="#A80036" points="114.5,120.7739,124.5,124.7739,114.5,128.7739,118.5,124.7739" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="23.5" x2="120.5" y1="124.7739" y2="124.7739"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="79" x="30.5" y="118.9649">confirm close</text><polygon fill="#A80036" points="238.5,152.4799,248.5,156.4799,238.5,160.4799,242.5,156.4799" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="126.5" x2="244.5" y1="156.4799" y2="156.4799"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="83" x="133.5" y="150.6709">GUI off switch</text><polygon fill="#A80036" points="412.5,184.186,422.5,188.186,412.5,192.186,416.5,188.186" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="250.5" x2="418.5" y1="188.186" y2="188.186"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="150" x="257.5" y="182.377">UserPowerDownRequest</text><polygon fill="#A80036" points="612.5,215.892,622.5,219.892,612.5,223.892,616.5,219.892" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="424.5" x2="618.5" y1="219.892" y2="219.892"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="176" x="431.5" y="214.083">InitiateSystemCloseSequence</text><polygon fill="#A80036" points="758.5,247.598,768.5,251.598,758.5,255.598,762.5,251.598" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="624.5" x2="764.5" y1="251.598" y2="251.598"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="122" x="631.5" y="245.789">processCloseReason</text><line style="stroke:#A80036;stroke-width:1.0;" x1="770.5" x2="812.5" y1="283.304" y2="283.304"/><line style="stroke:#A80036;stroke-width:1.0;" x1="812.5" x2="812.5" y1="283.304" y2="296.304"/><line style="stroke:#A80036;stroke-width:1.0;" x1="771.5" x2="812.5" y1="296.304" y2="296.304"/><polygon fill="#A80036" points="781.5,292.304,771.5,296.304,781.5,300.304,777.5,296.304" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="167" x="777.5" y="277.495">switchWindowAtClose(logo)</text><polygon fill="#A80036" points="962.5,324.01,952.5,328.01,962.5,332.01,958.5,328.01" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="956.5" x2="1066.5" y1="328.01" y2="328.01"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="92" x="968.5" y="322.201">last sreen show</text><polygon fill="#A80036" points="635.5,355.716,625.5,359.716,635.5,363.716,631.5,359.716" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="629.5" x2="950.5" y1="359.716" y2="359.716"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="83" x="641.5" y="353.907">ready to close</text><polygon fill="#A80036" points="435.5,387.4221,425.5,391.4221,435.5,395.4221,431.5,391.4221" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="429.5" x2="623.5" y1="391.4221" y2="391.4221"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="81" x="441.5" y="385.6131">readyToClose</text><path d="M349,406.4221 L412,406.4221 L412,415.4221 L402,425.4221 L349,425.4221 L349,406.4221 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="172.5" x="349" y="406.4221"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="18" x="364" y="421.3191">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="53" x="427" y="420.181">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="424.5" x2="466.5" y1="449.8341" y2="449.8341"/><line style="stroke:#A80036;stroke-width:1.0;" x1="466.5" x2="466.5" y1="449.8341" y2="462.8341"/><line style="stroke:#A80036;stroke-width:1.0;" x1="425.5" x2="466.5" y1="462.8341" y2="462.8341"/><polygon fill="#A80036" points="435.5,458.8341,425.5,462.8341,435.5,466.8341,431.5,462.8341" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="78" x="431.5" y="444.0251">closeServices</text><polygon fill="#A80036" points="612.5,497.5401,622.5,501.5401,612.5,505.5401,616.5,501.5401" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="424.5" x2="618.5" y1="501.5401" y2="501.5401"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="154" x="431.5" y="495.7311">SystemMessageType::Exit</text><polygon fill="#A80036" points="435.5,529.2461,425.5,533.2461,435.5,537.2461,431.5,533.2461" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="429.5" x2="623.5" y1="533.2461" y2="533.2461"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="77" x="441.5" y="527.4371">MsgHandled</text><path d="M349,548.2461 L412,548.2461 L412,557.2461 L402,567.2461 L349,567.2461 L349,548.2461 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="64.412" style="stroke:#000000;stroke-width:2.0;" width="154.5" x="349" y="548.2461"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="18" x="364" y="563.1431">alt</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="53" x="427" y="562.005">[timeout]</text><line style="stroke:#A80036;stroke-width:1.0;" x1="424.5" x2="466.5" y1="591.6582" y2="591.6582"/><line style="stroke:#A80036;stroke-width:1.0;" x1="466.5" x2="466.5" y1="591.6582" y2="604.6582"/><line style="stroke:#A80036;stroke-width:1.0;" x1="425.5" x2="466.5" y1="604.6582" y2="604.6582"/><polygon fill="#A80036" points="435.5,600.6582,425.5,604.6582,435.5,608.6582,431.5,604.6582" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="60" x="431.5" y="585.8492">kill service</text><!--MD5=[a331d730c9d76b9349085f79d38295fd]
@startuml
skinparam BackgroundColor F0F0F0



@@ 14,7 14,7 @@ participant "service EINK" as eink
User -> poff : confirm close
poff -> app : GUI off switch
app -> sysmgr : UserPowerDownRequest
sysmgr -> srv : preCloseRoutine
sysmgr -> srv : InitiateSystemCloseSequence

srv -> appmgr : processCloseReason
appmgr -> appmgr : switchWindowAtClose(logo)


@@ 33,12 33,10 @@ end

@enduml

PlantUML version 1.2020.02(Sun Mar 01 05:22:07 EST 2020)
PlantUML version 1.2021.7(Sun May 23 14:40:07 CEST 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 11.0.12+7-post-Debian-2
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: US

M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp => module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp +4 -5
@@ 173,11 173,10 @@ namespace sys

        void CloseServices();

        void preCloseRoutine(CloseReason closeReason);

        void InitiateSystemCloseSequence(CloseReason closeReason);
        void postStartRoutine();

        void readyToCloseHandler(Message *msg);
        void ServiceReadyToCloseHandler(Message *msg);

        void RestoreSystemHandler();



@@ 198,13 197,13 @@ namespace sys
        UpdateReason updateReason{UpdateReason::Update};
        std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
        sys::TimerHandle freqTimer;
        sys::TimerHandle servicesPreShutdownRoutineTimeout;
        sys::TimerHandle serviceCloseTimer;
        sys::TimerHandle lowBatteryShutdownDelay;
        sys::TimerHandle powerManagerEfficiencyTimer;
        InitFunction userInit;
        InitFunction systemInit;
        DeinitFunction systemDeinit;
        std::vector<std::string> readyForCloseRegister;
        std::vector<std::string> servicesToClose;

        std::shared_ptr<sys::CpuSentinel> cpuSentinel;


M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +2 -1
@@ 86,7 86,8 @@ int main()
    systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());
    systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>(std::make_shared<alarms::AlarmOperationsFactory>()));
    systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>(service::eink::ExitAction::None));
    systemServices.emplace_back(sys::CreatorFor<service::gui::ServiceGUI>());
    systemServices.emplace_back(
        sys::CreatorFor<service::gui::ServiceGUI>(gui::Size{BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y}));

    auto sysmgr = std::make_shared<sys::SystemManager>(std::move(systemServices));
    sysmgr->StartSystem(

M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp => products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp +6 -21
@@ 50,6 50,12 @@ namespace app
            return actionHandled();
        });

        addActionReceiver(manager::actions::ChangeHomescreenLayout, [this](auto &&data) {
            auto msgLayout = dynamic_cast<gui::ChangeHomescreenLayoutParams *>(data.get());
            setHomeScreenLayout(msgLayout->getNewHomescreenLayoutName());
            return actionHandled();
        });

        addActionReceiver(app::manager::actions::DisplayLogoAtExit, [this](auto &&data) {
            requestShutdownWindow(gui::BellWelcomeWindow::defaultName);
            return actionHandled();


@@ 59,22 65,6 @@ namespace app
            requestShutdownWindow(gui::window::name::bell_battery_shutdown);
            return actionHandled();
        });

        addActionReceiver(manager::actions::ChangeHomescreenLayout, [this](auto &&data) {
            auto msgLayout = dynamic_cast<gui::ChangeHomescreenLayoutParams *>(data.get());
            setHomeScreenLayout(msgLayout->getNewHomescreenLayoutName());
            return actionHandled();
        });

        addActionReceiver(app::manager::actions::DisplayLowBatteryScreen, [this](auto &&data) {
            /**
             * Due to the way of handling shutdown sequence by GUI renderer and applications it is required to leave
             * this handler defined but not implemented even if it's not used at all.
             * Without it, the renderer won't render the last frame properly.
             * This issue will be addressed in future PRs.
             */
            return actionHandled();
        });
    }

    sys::ReturnCodes ApplicationBellMain::InitHandler()


@@ 149,11 139,6 @@ namespace app
        return handleAsyncResponse(resp);
    }

    auto ApplicationBellMain::isHomeScreenFocused() -> bool
    {
        return GetName() == app::applicationBellName && getCurrentWindow()->getName() == gui::name::window::main_window;
    }

    // Empty: do not start idleTimer on application run
    void ApplicationBellMain::onStart()
    {}

M products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp => products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp +0 -2
@@ 42,7 42,6 @@ namespace app
        }

      private:
        auto isHomeScreenFocused() -> bool;
        void onStart() override;
        sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;
        void setHomeScreenLayout(std::string layoutName);


@@ 57,7 56,6 @@ namespace app
            return {{manager::actions::Launch,
                     manager::actions::ShowAlarm,
                     manager::actions::DisplayLogoAtExit,
                     manager::actions::DisplayLowBatteryScreen,
                     manager::actions::SystemBrownout,
                     manager::actions::ChangeHomescreenLayout}};
        }

M products/BellHybrid/services/appmgr/ApplicationManager.cpp => products/BellHybrid/services/appmgr/ApplicationManager.cpp +16 -3
@@ 3,13 3,12 @@

#include <appmgr/ApplicationManager.hpp>
#include <appmgr/messages/AlarmMessage.hpp>
#include <appmgr/messages/BatteryShutdown.hpp>
#include <appmgr/messages/IdleTimerMessage.hpp>
#include <appmgr/messages/ChangeHomescreenLayoutMessage.hpp>
#include <application-bell-main/ApplicationBellMain.hpp>
#include <application-bell-onboarding/BellOnBoardingNames.hpp>
#include <service-appmgr/Constants.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <common/windows/BellWelcomeWindow.hpp>

namespace app::manager
{


@@ 46,6 45,21 @@ namespace app::manager
        }
    }

    void ApplicationManager::handleStart(StartAllowedMessage *msg)
    {
        switch (msg->getStartupType()) {
        case StartupType::CriticalBattery:
            handleSwitchApplication(
                std::make_unique<SwitchRequest>(
                    service::name::appmgr, resolveHomeApplication(), gui::window::name::bell_battery_shutdown, nullptr)
                    .get());

            break;
        default:
            ApplicationManagerCommon::handleStart(msg);
        }
    }

    auto ApplicationManager::handleDisplayLanguageChange(app::manager::DisplayLanguageChangeRequest *msg) -> bool
    {
        return ApplicationManagerCommon::handleDisplayLanguageChange(msg);


@@ 70,7 84,6 @@ namespace app::manager
        });
        connect(typeid(AlarmActivated), convertibleToActionHandler);
        connect(typeid(AlarmDeactivated), convertibleToActionHandler);
        connect(typeid(BatteryShutdown), convertibleToActionHandler);
        connect(typeid(BedtimeNotification), convertibleToActionHandler);
        connect(typeid(ChangeHomescreenLayoutMessage), convertibleToActionHandler);
    }

M products/BellHybrid/services/appmgr/CMakeLists.txt => products/BellHybrid/services/appmgr/CMakeLists.txt +0 -1
@@ 9,7 9,6 @@ target_sources(appmgr
        include/appmgr/messages/AlarmMessage.hpp
        include/appmgr/ApplicationManager.hpp
        include/appmgr/IdleHandler.hpp
        include/appmgr/messages/BatteryShutdown.hpp
        include/appmgr/messages/ChangeHomescreenLayoutMessage.hpp
        include/appmgr/messages/ChangeHomescreenLayoutParams.hpp
        include/appmgr/messages/PowerOffPopupRequestParams.hpp

M products/BellHybrid/services/appmgr/include/appmgr/ApplicationManager.hpp => products/BellHybrid/services/appmgr/include/appmgr/ApplicationManager.hpp +1 -0
@@ 16,6 16,7 @@ namespace app::manager
                           const ApplicationName &_rootApplicationName);

      protected:
        void handleStart(StartAllowedMessage *msg) override;
        auto handleAction(ActionEntry &action) -> ActionProcessStatus override;
        auto handleDisplayLanguageChange(DisplayLanguageChangeRequest *msg) -> bool override;


D products/BellHybrid/services/appmgr/include/appmgr/messages/BatteryShutdown.hpp => products/BellHybrid/services/appmgr/include/appmgr/messages/BatteryShutdown.hpp +0 -23
@@ 1,23 0,0 @@
// 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 <Service/Message.hpp>
#include <apps-common/popups/data/PopupRequestParams.hpp>
#include <service-appmgr/Actions.hpp>
#include <service-appmgr/messages/ActionRequest.hpp>

class BatteryShutdown : public sys::DataMessage, public app::manager::actions::ConvertibleToAction
{
  public:
    BatteryShutdown() : sys::DataMessage{MessageType::MessageTypeUninitialized}
    {}

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

M products/BellHybrid/sys/SystemManager.cpp => products/BellHybrid/sys/SystemManager.cpp +0 -10
@@ 7,10 7,7 @@
#include <system/messages/SystemManagerMessage.hpp>

#include <appmgr/messages/AlarmMessage.hpp>
#include <appmgr/messages/BatteryShutdown.hpp>
#include <service-appmgr/messages/SwitchRequest.hpp>
#include <service-appmgr/Constants.hpp>
#include <service-appmgr/Controller.hpp>

namespace sys
{


@@ 44,13 41,6 @@ namespace sys
        return MessageNone{};
    }

    void SystemManager::batteryShutdownLevelAction()
    {
        auto msg = std::make_shared<BatteryShutdown>();
        bus.sendUnicast(msg, service::name::appmgr);
        SystemManagerCommon::batteryShutdownLevelAction();
    }

    void SystemManager::handleShutdown()
    {
        set(State::ShutdownReady);

M products/BellHybrid/sys/include/sys/SystemManager.hpp => products/BellHybrid/sys/include/sys/SystemManager.hpp +0 -2
@@ 19,8 19,6 @@ namespace sys

        auto handleAlarmActivationStatusChangeRequest(AlarmActivationStatusChangeRequest *request) -> MessagePointer;

        void batteryShutdownLevelAction() override;

        void handleShutdown() override;
    };
} // namespace sys

M products/PurePhone/PurePhoneMain.cpp => products/PurePhone/PurePhoneMain.cpp +2 -1
@@ 195,7 195,8 @@ int main()
    systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>());
#endif
#ifdef ENABLE_SERVICE_GUI
    systemServices.emplace_back(sys::CreatorFor<service::gui::ServiceGUI>());
    systemServices.emplace_back(
        sys::CreatorFor<service::gui::ServiceGUI>(gui::Size{BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y}));
#endif
#if ENABLE_SERVICE_TEST
    systemServices.emplace_back(sys::CreatorFor<service::test::ServiceTest>());

M products/PurePhone/services/appmgr/ApplicationManager.cpp => products/PurePhone/services/appmgr/ApplicationManager.cpp +1 -0
@@ 591,6 591,7 @@ namespace app::manager
            ApplicationManagerCommon::handleStart(msg);
            break;
        case StartupType::LowBattery:
        case StartupType::CriticalBattery:
            handleSwitchApplication(std::make_unique<SwitchRequest>(
                                        service::name::appmgr, app::name_desktop, window::name::dead_battery, nullptr)
                                        .get());