~aleteoryx/muditaos

efef7dcf7f71c84d8adfb20b0d3b313f1bd1240e — Piotr Tański 4 years ago 9098f69
[EGD-6111] Timers refactored

Deep refactor of system timers.
70 files changed, 874 insertions(+), 715 deletions(-)

M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/GuiTimer.cpp
M module-apps/GuiTimer.hpp
M module-apps/application-antenna/ApplicationAntenna.cpp
M module-apps/application-antenna/ApplicationAntenna.hpp
M module-apps/application-calendar/windows/EventReminderWindow.cpp
M module-apps/application-calendar/windows/EventReminderWindow.hpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-call/ApplicationCall.hpp
M module-apps/application-call/windows/CallWindow.cpp
M module-apps/application-call/windows/CallWindow.hpp
M module-apps/application-clock/ApplicationClock.cpp
M module-apps/application-clock/ApplicationClock.hpp
M module-apps/application-meditation/widgets/MeditationTimer.cpp
M module-apps/application-meditation/widgets/MeditationTimer.hpp
M module-apps/application-settings-new/windows/DisplayLightWindow.cpp
M module-apps/application-settings-new/windows/DisplayLightWindow.hpp
M module-bsp/board/linux/vibrator/vibrator.cpp
M module-bsp/board/rt1051/bsp/vibrator/vibrator.cpp
M module-bsp/bsp/vibrator/vibrator.hpp
D module-gui/gui/core/Timer.hpp
M module-gui/gui/widgets/Item.cpp
M module-gui/gui/widgets/Item.hpp
M module-services/service-antenna/ServiceAntenna.cpp
M module-services/service-antenna/service-antenna/ServiceAntenna.hpp
M module-services/service-appmgr/model/ApplicationManager.cpp
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp
M module-services/service-cellular/CellularRequestHandler.cpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/service-cellular/ServiceCellular.hpp
M module-services/service-desktop/ServiceDesktop.cpp
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp
M module-services/service-desktop/service-desktop/WorkerDesktop.hpp
M module-services/service-eink/ServiceEink.cpp
M module-services/service-eink/ServiceEink.hpp
M module-services/service-evtmgr/EventManager.cpp
M module-services/service-evtmgr/api/EventManagerServiceAPI.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp
M module-services/service-evtmgr/service-evtmgr/EventManagerServiceAPI.hpp
M module-services/service-evtmgr/vibra/Vibra.cpp
M module-services/service-evtmgr/vibra/Vibra.hpp
M module-services/service-fileindexer/StartupIndexer.cpp
M module-services/service-fileindexer/StartupIndexer.hpp
M module-services/service-fota/ServiceFota.cpp
M module-services/service-fota/service-fota/ServiceFota.hpp
M module-services/service-gui/ServiceGUI.cpp
M module-services/service-gui/ServiceGUI.hpp
M module-services/service-time/ServiceTime.hpp
M module-services/service-time/service-time/TimeEvents.hpp
M module-services/service-time/timeEvents/TimeEvents.cpp
M module-sys/CMakeLists.txt
M module-sys/Service/Service.cpp
M module-sys/Service/Service.hpp
D module-sys/Service/Timer.cpp
D module-sys/Service/Timer.hpp
D module-sys/Service/TimerMessage.cpp
M module-sys/SystemManager/SystemManager.cpp
M module-sys/SystemManager/SystemManager.hpp
A module-sys/Timers/SystemTimer.cpp
A module-sys/Timers/SystemTimer.hpp
A module-sys/Timers/Timer.hpp
A module-sys/Timers/TimerFactory.cpp
A module-sys/Timers/TimerFactory.hpp
A module-sys/Timers/TimerHandle.cpp
A module-sys/Timers/TimerHandle.hpp
R module-sys/{Service => Timers}/TimerMessage.hpp
M module-apps/Application.cpp => module-apps/Application.cpp +10 -10
@@ 6,8 6,7 @@
#include "GuiTimer.hpp"      // for GuiTimer
#include "Item.hpp"          // for Item
#include "MessageType.hpp"   // for MessageType
#include "Service/Timer.hpp" // for Timer
#include "Timer.hpp"         // for Timer
#include "module-sys/Timers/TimerFactory.hpp" // for Timer
#include "TopBar.hpp"
#include "Translator.hpp"                // for KeyInputSim...
#include "common_data/EventStore.hpp"    // for Battery


@@ 94,8 93,10 @@ namespace app
                                                                       : gui::top_bar::TimeMode::Time24h);
        bus.channels.push_back(sys::BusChannel::ServiceCellularNotifications);

        longPressTimer = std::make_unique<sys::Timer>("LongPress", this, key_timer_ms);
        longPressTimer->connect([&](sys::Timer &) { longPressTimerCallback(); });
        longPressTimer = sys::TimerFactory::createPeriodicTimer(this,
                                                                "LongPress",
                                                                std::chrono::milliseconds{key_timer_ms},
                                                                [this](sys::Timer &) { longPressTimerCallback(); });

        connect(typeid(AppRefreshMessage),
                [this](sys::Message *msg) -> sys::MessagePointer { return handleAppRefresh(msg); });


@@ 136,7 137,7 @@ namespace app
            messageInputEventApplication(this, this->GetName(), iev);
            // clean previous key
            keyTranslator->prev_key_press = {};
            longPressTimer->stop();
            longPressTimer.stop();
        }
    }



@@ 301,10 302,10 @@ namespace app
    {
        AppInputEventMessage *msg = reinterpret_cast<AppInputEventMessage *>(msgl);
        if (msg->getEvent().state == gui::InputEvent::State::keyPressed) {
            longPressTimer->start();
            longPressTimer.start();
        }
        else if (msg->getEvent().state == gui::InputEvent::State::keyReleasedShort) {
            longPressTimer->stop();
            longPressTimer.stop();
        }
        if (not windowsStack.isEmpty() && getCurrentWindow()->onInput(msg->getEvent())) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);


@@ 746,10 747,9 @@ namespace app
        return windowsStack.get(name);
    }

    void Application::connect(std::unique_ptr<app::GuiTimer> &&timer, gui::Item *item)
    void Application::connect(GuiTimer *timer, gui::Item *item)
    {
        timer->sysapi.connect(item);
        item->attachTimer(std::move(timer));
        item->attachTimer(timer);
    }

    const gui::top_bar::Configuration &Application::getTopBarConfiguration() const noexcept

M module-apps/Application.hpp => module-apps/Application.hpp +3 -7
@@ 11,6 11,7 @@
#include "Service/Common.hpp"              // for ReturnCodes
#include "Service/Message.hpp"             // for MessagePointer
#include "Service/Service.hpp"             // for Service
#include "Timers/TimerHandle.hpp"
#include "SwitchData.hpp"                  // for SwitchData
#include "SystemManager/SystemManager.hpp" // for SystemManager
#include "bsp/keyboard/key_codes.hpp"      // for bsp


@@ 31,7 32,6 @@

namespace app
{
    class GuiTimer;
    class WindowsStack;
} // namespace app
namespace gui


@@ 50,10 50,6 @@ namespace gui
{
    class KeyInputSimpleTranslation;
}
namespace sys
{
    class Timer;
}
namespace settings
{
    class Settings;


@@ 181,7 177,7 @@ namespace app
        std::unordered_map<manager::actions::ActionId, OnActionReceived> receivers;

      public:
        std::unique_ptr<sys::Timer> longPressTimer;
        sys::TimerHandle longPressTimer;
        void clearLongPressTimeout();

        Application(std::string name,


@@ 355,7 351,7 @@ namespace app
        /// to avoid conflicts with connect below
        using Service::connect;
        /// connects item with GuiTimer and stores it in app
        void connect(std::unique_ptr<GuiTimer> &&timer, gui::Item *item);
        void connect(GuiTimer *timer, gui::Item *item);

      protected:
        /// key translator to handle

M module-apps/GuiTimer.cpp => module-apps/GuiTimer.cpp +66 -21
@@ 3,54 3,99 @@

#include "GuiTimer.hpp"
#include "Item.hpp"                    // for Item
#include "Service/Timer.hpp"           // for Timer, Timer::Type, Timer::Ty...

#include "module-apps/Application.hpp" // for Application
#include <memory>                      // for allocator

#include "module-sys/Timers/SystemTimer.hpp" // for Timer, Timer::Type, Timer::Ty...
#include "module-sys/Timers/TimerFactory.hpp"

#include <functional>

namespace app
{
    namespace
    {
        constexpr auto toSysTimerType(gui::Timer::Type type) noexcept -> sys::Timer::Type
        auto guiTypeToSysType(GuiTimer::Type type) noexcept
        {
            if (type == gui::Timer::Type::Single) {
                return sys::Timer::Type::SingleShot;
            if (type == GuiTimer::Type::Periodic) {
                return sys::timer::Type::Periodic;
            }
            return sys::Timer::Type::Periodic;
            return sys::timer::Type::SingleShot;
        }
    } // namespace

    class GuiTimer::Impl
    {
      public:
        Impl(Application *parent,
             gui::Item *item,
             const std::string &name,
             std::chrono::milliseconds timeout,
             Type type);
        std::unique_ptr<sys::timer::SystemTimer> timer;
    };

    GuiTimer::Impl::Impl(
        Application *parent, gui::Item *item, const std::string &name, std::chrono::milliseconds timeout, Type type)
        : timer{std::make_unique<sys::timer::SystemTimer>(parent, name, timeout, guiTypeToSysType(type))}
    {
        timer->connect([item](sys::Timer &self) { item->onTimer(self); });
    }

    GuiTimer::GuiTimer(
        Application *parent, gui::Item *item, const std::string &name, std::chrono::milliseconds timeout, Type type)
        : pimpl(std::make_unique<GuiTimer::Impl>(parent, item, name, timeout, type)), item{item}
    {}

    GuiTimer::~GuiTimer() noexcept
    {
        item->detachTimer(*(pimpl->timer));
    }

    void GuiTimer::start()
    {
        sys::Timer::start();
        pimpl->timer->start();
    }

    void GuiTimer::stop()
    {
        sys::Timer::stop();
        pimpl->timer->stop();
    }

    void GuiTimer::reset()
    void GuiTimer::restart(std::chrono::milliseconds newInterval)
    {
        sys::Timer::start();
        pimpl->timer->restart(newInterval);
    }

    void GuiTimer::setInterval(gui::ms time)
    bool GuiTimer::isActive() const noexcept
    {
        sys::Timer::setInterval(time);
        return pimpl->timer->isActive();
    }

    GuiTimer::GuiTimer(Application *parent) : GuiTimer("GUI", parent)
    {}
    sys::TimerHandle GuiTimerFactory::createSingleShotTimer(Application *parent,
                                                            gui::Item *item,
                                                            const std::string &name,
                                                            std::chrono::milliseconds interval)
    {
        return createGuiTimer(parent, item, name, interval, GuiTimer::Type::SingleShot);
    }

    GuiTimer::GuiTimer(const std::string &name, Application *parent, gui::ms timeout, gui::Timer::Type type)
        : sys::Timer(name, parent, timeout, toSysTimerType(type)), sysapi{*this}
    {}
    sys::TimerHandle GuiTimerFactory::createPeriodicTimer(Application *parent,
                                                          gui::Item *item,
                                                          const std::string &name,
                                                          std::chrono::milliseconds interval)
    {
        return createGuiTimer(parent, item, name, interval, GuiTimer::Type::Periodic);
    }

    void GuiTimer::Sysapi::connect(gui::Item *item)
    sys::TimerHandle GuiTimerFactory::createGuiTimer(Application *parent,
                                                     gui::Item *item,
                                                     const std::string &name,
                                                     std::chrono::milliseconds interval,
                                                     GuiTimer::Type type)
    {
        if (item != nullptr) {
            parent.connect([item, this](sys::Timer &timer) { item->onTimer(parent); });
        }
        auto timer = new GuiTimer{parent, item, name, interval, type};
        parent->connect(timer, item);
        return sys::TimerHandle{timer};
    }
} // namespace app

M module-apps/GuiTimer.hpp => module-apps/GuiTimer.hpp +46 -38
@@ 1,16 1,14 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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/Timer.hpp"             // for Timer
#include <module-gui/gui/core/Timer.hpp> // for ms, Timer
#include <string>                        // for string
#include "module-sys/Timers/Timer.hpp"       // for Timer
#include "module-sys/Timers/TimerHandle.hpp" // for TimerHandle

#include <memory>
#include <string> // for string

namespace app
{
    class Application;
} // namespace app
namespace gui
{
    class Item;


@@ 18,42 16,52 @@ namespace gui

namespace app
{

    class Application;

    /// proxies system Timer capabilities to gui::Timer and disconnects dependencies
    /// by default one time run
    class GuiTimer : public gui::Timer, protected sys::Timer
    /// Proxies system timer capabilities to the gui layer
    class GuiTimer : public sys::Timer
    {
      public:
        /// gui timer default named GUI, infinite timeout on start
        explicit GuiTimer(Application *parent);
        /// gui timer with user name, infinite timeout on start
        GuiTimer(const std::string &name,
                 Application *parent,
                 gui::ms timeout       = sys::Timer::timeout_infinite,
                 gui::Timer::Type type = gui::Timer::Single);
        /// there is no valid reason to create timer without app
        GuiTimer() = delete;

        /// @defgroup interface
        /// @ {
        enum class Type
        {
            SingleShot,
            Periodic
        };

        GuiTimer(Application *parent,
                 gui::Item *item,
                 const std::string &name,
                 std::chrono::milliseconds timeout,
                 Type type);
        ~GuiTimer() noexcept override;

        void start() override;
        void restart(std::chrono::milliseconds newInterval) override;
        void stop() override;
        void reset() override;
        void setInterval(gui::ms time) override;
        /// @ }
        bool isActive() const noexcept override;

        /// interface to trigger timing callback
        class Sysapi
        {
            friend Application;
            GuiTimer &parent;
            void connect(gui::Item *item);

          public:
            Sysapi(GuiTimer &parent) : parent(parent)
            {}
        } sysapi;
        class Impl;
        std::unique_ptr<Impl> pimpl;
        gui::Item *item = nullptr;
    };

    class GuiTimerFactory
    {
      public:
        static sys::TimerHandle createSingleShotTimer(Application *parent,
                                                      gui::Item *item,
                                                      const std::string &name,
                                                      std::chrono::milliseconds interval);
        static sys::TimerHandle createPeriodicTimer(Application *parent,
                                                    gui::Item *item,
                                                    const std::string &name,
                                                    std::chrono::milliseconds interval);

      private:
        static sys::TimerHandle createGuiTimer(Application *parent,
                                               gui::Item *item,
                                               const std::string &name,
                                               std::chrono::milliseconds interval,
                                               GuiTimer::Type type);
    };
}; // namespace app

M module-apps/application-antenna/ApplicationAntenna.cpp => module-apps/application-antenna/ApplicationAntenna.cpp +5 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*


@@ 9,7 9,7 @@
 */

#include "ApplicationAntenna.hpp"
#include "Service/Timer.hpp"
#include "module-sys/Timers/TimerFactory.hpp"
#include "module-cellular/at/response.hpp"
#include <service-cellular/CellularServiceAPI.hpp>



@@ 40,9 40,9 @@ namespace app
        : Application(name, parent, startInBackground, antennaApplicationStackSize)
    {
        bus.channels.push_back(sys::BusChannel::AntennaNotifications);
        appTimer = std::make_unique<sys::Timer>("Antena", this, 2000);
        appTimer->connect([=](sys::Timer &) { timerHandler(); });
        appTimer->start();
        appTimer = sys::TimerFactory::createPeriodicTimer(
            this, "Antena", std::chrono::milliseconds{2000}, [this](sys::Timer &) { timerHandler(); });
        appTimer.start();
    }

    ApplicationAntenna::~ApplicationAntenna()

M module-apps/application-antenna/ApplicationAntenna.hpp => module-apps/application-antenna/ApplicationAntenna.hpp +3 -2
@@ 1,8 1,9 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-sys/Timers/TimerHandle.hpp>
#include <Application.hpp>
#include <service-cellular/CellularServiceAPI.hpp>
#include <windows/AppWindow.hpp>


@@ 26,7 27,7 @@ namespace app
    class ApplicationAntenna : public app::Application
    {
      protected:
        std::unique_ptr<sys::Timer> appTimer;
        sys::TimerHandle appTimer;
        void timerHandler(void);
        bool cellularRequestInProgress = false;
        bsp::cellular::antenna antenna;

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

#include "EventReminderWindow.hpp"
#include <Timers/TimerFactory.hpp>
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "module-apps/application-calendar/data/CalendarData.hpp"
#include <gui/widgets/Window.hpp>


@@ 18,9 19,10 @@ namespace gui
    {
        buildInterface();

        reminderTimer = std::make_unique<sys::Timer>(
            "CalendarReminderTimer", app, reminderLifeDuration, sys::Timer::Type::SingleShot);
        reminderTimer->connect([=](sys::Timer &) { reminderTimerCallback(); });
        reminderTimer = sys::TimerFactory::createSingleShotTimer(app,
                                                                 "CalendarReminderTimer",
                                                                 std::chrono::milliseconds{reminderLifeDuration},
                                                                 [this](sys::Timer &) { reminderTimerCallback(); });
    }

    EventReminderWindow::~EventReminderWindow()


@@ 106,13 108,12 @@ namespace gui

    void EventReminderWindow::startTimer()
    {
        reminderTimer->connect([=](sys::Timer &) { reminderTimerCallback(); });
        reminderTimer->reload();
        reminderTimer.start();
    }

    void EventReminderWindow::destroyTimer()
    {
        reminderTimer->stop();
        reminderTimer.stop();
    }

    auto EventReminderWindow::handleSwitchData(SwitchData *data) -> bool

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

#pragma once


@@ 9,7 9,7 @@
#include <module-db/Interface/EventsRecord.hpp>
#include <Text.hpp>
#include <Label.hpp>
#include <module-sys/Service/Timer.hpp>
#include <module-sys/Timers/TimerHandle.hpp>

namespace gui
{


@@ 18,7 18,7 @@ namespace gui
    class EventReminderWindow : public gui::AppWindow
    {
      private:
        std::unique_ptr<sys::Timer> reminderTimer;
        sys::TimerHandle reminderTimer;

      protected:
        std::shared_ptr<EventsRecord> eventRecord;

M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +13 -16
@@ 26,6 26,7 @@
#include <cassert>
#include <module-apps/application-phonebook/data/PhonebookItemData.hpp>
#include <module-services/service-db/service-db/DBServiceAPI.hpp>
#include <module-sys/Timers/TimerFactory.hpp>

namespace app
{


@@ 91,9 92,9 @@ namespace app
    void ApplicationCall::CallerIdHandler(const CellularCallerIdMessage *const msg)
    {
        if (getState() == call::State::IDLE) {
            if (callerIdTimer) {
                callerIdTimer->stop();
                callerIdTimer.reset(nullptr);
            if (callerIdTimer.isValid()) {
                callerIdTimer.stop();
                callerIdTimer.reset();
            }
            manager::Controller::sendAction(
                this, manager::actions::Call, std::make_unique<app::IncomingCallData>(msg->number));


@@ 103,19 104,15 @@ namespace app
    void ApplicationCall::IncomingCallHandler(const CellularIncominCallMessage *const msg)
    {
        if (getState() == call::State::IDLE) {
            constexpr sys::ms callerIdTimeout = 1000;
            constexpr auto callerIdTimeout = std::chrono::milliseconds{1000};
            callerIdTimer =
                std::make_unique<sys::Timer>("CallerIdTimer", this, callerIdTimeout, sys::Timer::Type::SingleShot);
            callerIdTimer->connect([=](sys::Timer &) {
                callerIdTimer->stop();
                manager::Controller::sendAction(
                    this,
                    manager::actions::Call,
                    std::make_unique<app::IncomingCallData>(utils::PhoneNumber().getView()));
            });
            if (callerIdTimer) {
                callerIdTimer->start();
            }
                sys::TimerFactory::createSingleShotTimer(this, "CallerIdTimer", callerIdTimeout, [=](sys::Timer &) {
                    manager::Controller::sendAction(
                        this,
                        manager::actions::Call,
                        std::make_unique<app::IncomingCallData>(utils::PhoneNumber().getView()));
                });
            callerIdTimer.start();
        }
    }



@@ 143,7 140,7 @@ namespace app

            switch (msg->type) {
            case CellularNotificationMessage::Type::CallAborted: {
                callerIdTimer.reset(nullptr);
                callerIdTimer.reset();
                CallAbortHandler();
            } break;
            case CellularNotificationMessage::Type::CallActive: {

M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +2 -2
@@ 7,7 7,7 @@

#include <Application.hpp>
#include <Service/Message.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerHandle.hpp>
#include <SystemManager/SystemManager.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <time/time_conversion.hpp>


@@ 74,7 74,7 @@ namespace app
        void CallerIdHandler(const CellularCallerIdMessage *const msg);
        void RingingHandler(const CellularRingingMessage *const msg);

        std::unique_ptr<sys::Timer> callerIdTimer;
        sys::TimerHandle callerIdTimer;

      protected:
        call::State state = call::State::IDLE;

M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +11 -20
@@ 383,31 383,22 @@ namespace gui

    void CallWindow::connectTimerOnExit()
    {
        auto timer = std::make_unique<app::GuiTimer>(application);
        timer->setInterval(getDelayedStopTime());

        timerCallback = [this](Item &, Timer &timer) {
        timerCallback = [this](Item &, sys::Timer &timer) {
            LOG_DEBUG("Delayed exit timer callback");
            setState(State::IDLE);
            detachTimer(timer);
            app::manager::Controller::switchBack(application);
            return true;
        };
        timer->start();
        application->connect(std::move(timer), this);
        delayedExitTimer =
            app::GuiTimerFactory::createSingleShotTimer(application, this, "DelayedExitTimer", getDelayedStopTime());
        delayedExitTimer.start();
    }

    void CallWindow::runCallTimer()
    {
        static const sys::ms one_second = 1000;
        stop_timer                      = false;
        auto timer = std::make_unique<app::GuiTimer>("CallTime", application, one_second, Timer::Continous);
        durationLabel->timerCallback = [&](Item &item, Timer &timer) {
            if (stop_timer) {
                timer.stop();
                item.detachTimer(timer);
                return true;
            }
        constexpr auto callTimeTimeout = std::chrono::seconds{1};
        callTimer = app::GuiTimerFactory::createPeriodicTimer(application, durationLabel, "CallTime", callTimeTimeout);
        durationLabel->timerCallback = [&](Item &item, sys::Timer &timer) {
            std::chrono::time_point<std::chrono::system_clock> systemUnitDuration(callDuration);
            updateDuration(std::chrono::system_clock::to_time_t(systemUnitDuration));
            callDuration++;


@@ 415,14 406,14 @@ namespace gui
            application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
            return true;
        };
        timer->start();
        application->connect(std::move(timer), durationLabel);
        callTimer.start();
    }

    void CallWindow::stopCallTimer()
    {
        callDuration = std::chrono::seconds().zero();
        stop_timer   = true;
        if (callTimer.isActive()) {
            callTimer.stop();
        }
    }

} /* namespace gui */

M module-apps/application-call/windows/CallWindow.hpp => module-apps/application-call/windows/CallWindow.hpp +3 -2
@@ 18,9 18,10 @@ namespace gui
    {
      private:
        gui::KeyInputMappedTranslation translator;
        sys::TimerHandle callTimer;
        sys::TimerHandle delayedExitTimer;
        std::chrono::seconds callDuration                   = std::chrono::seconds().zero();
        bool stop_timer                                     = false;
        static constexpr inline sys::ms callDelayedStopTime = 3000;
        static constexpr inline auto callDelayedStopTime    = std::chrono::milliseconds{3000};

        [[nodiscard]] auto getDelayedStopTime() const
        {

M module-apps/application-clock/ApplicationClock.cpp => module-apps/application-clock/ApplicationClock.cpp +6 -6
@@ 1,9 1,8 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

// module-gui
#include "AppWindow.hpp"
#include "Service/Timer.hpp"
#include "gui/widgets/Window.hpp"

// module-utils


@@ 11,6 10,7 @@
#include <service-evtmgr/EVMessages.hpp>
#include <service-evtmgr/EventManager.hpp>
#include <service-appmgr/model/ApplicationManager.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
// MessageType
#include "MessageType.hpp"
// this module


@@ 26,9 26,9 @@ namespace app
                                       sys::ServicePriority priority)
        : Application(name, parent, startInBackground, stackDepth, priority)
    {
        timerClock = std::make_unique<sys::Timer>("Clock", this, 1000);
        timerClock->connect([&](sys::Timer &) { timerClockCallback(); });
        timerClock->start();
        timerClock = sys::TimerFactory::createPeriodicTimer(
            this, "Clock", std::chrono::milliseconds{1000}, [&](sys::Timer &) { timerClockCallback(); });
        timerClock.start();
    }

    void ApplicationClock::timerClockCallback()


@@ 76,7 76,7 @@ namespace app

    sys::ReturnCodes ApplicationClock::DeinitHandler()
    {
        timerClock->stop();
        timerClock.stop();
        return sys::ReturnCodes::Success;
    }


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

#pragma once


@@ 7,6 7,7 @@
#include "gui/widgets/Label.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/ProgressBar.hpp"
#include "module-sys/Timers/TimerHandle.hpp"

namespace app
{


@@ 14,7 15,7 @@ namespace app

    class ApplicationClock : public Application
    {
        std::unique_ptr<sys::Timer> timerClock;
        sys::TimerHandle timerClock;
        void timerClockCallback();

      public:

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

#include "MeditationTimer.hpp"


@@ 15,7 15,7 @@ namespace gui
{
    namespace
    {
        constexpr gui::ms TimerInterval{1000};
        constexpr auto TimerInterval = std::chrono::milliseconds{1000};
    } // namespace

    MeditationTimer::MeditationTimer(std::uint32_t x,


@@ 103,19 103,15 @@ namespace gui
    void MeditationTimer::startTimer()
    {
        assert(application != nullptr);
        auto timerTask =
            std::make_unique<app::GuiTimer>("MeditationTimer", application, TimerInterval, Timer::Type::Continous);
        timerCallback = [this](Item &it, Timer &timerTask) { return onTimerTimeout(it, timerTask); };
        timerTask->start();
        application->connect(std::move(timerTask), this);
        timerCallback = [this](Item &it, sys::Timer &task) { return onTimerTimeout(it, task); };
        timerTask     = app::GuiTimerFactory::createPeriodicTimer(application, this, "MeditationTimer", TimerInterval);
        timerTask.start();
    }

    auto MeditationTimer::onTimerTimeout(Item &self, Timer &timerTask) -> bool
    auto MeditationTimer::onTimerTimeout(Item &self, sys::Timer &task) -> bool
    {
        if (isStopped() || isFinished()) {
            timerTask.stop();
            detachTimer(timerTask);

            task.stop();
            if (isFinished() && timeoutCallback != nullptr) {
                timeoutCallback();
            }

M module-apps/application-meditation/widgets/MeditationTimer.hpp => module-apps/application-meditation/widgets/MeditationTimer.hpp +4 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 6,12 6,12 @@
#include <atomic>
#include <chrono>

#include <module-apps/GuiTimer.hpp>
#include <application-meditation/ApplicationMeditation.hpp>

#include "BoxLayout.hpp"
#include "ProgressBar.hpp"
#include "Text.hpp"
#include "Timer.hpp"

namespace gui
{


@@ 42,7 42,7 @@ namespace gui
        void onReset();

        void startTimer();
        [[nodiscard]] auto onTimerTimeout(Item &self, Timer &timerTask) -> bool;
        [[nodiscard]] auto onTimerTimeout(Item &self, sys::Timer &timerTask) -> bool;
        [[nodiscard]] auto isFinished() const noexcept -> bool;
        [[nodiscard]] auto intervalReached() const noexcept -> bool;
        [[nodiscard]] auto calculatePercentageValue() const noexcept -> unsigned int;


@@ 53,6 53,7 @@ namespace gui
        std::chrono::seconds intervalPeriod{std::chrono::seconds::zero()};
        bool hasInterval = false;

        sys::TimerHandle timerTask;
        app::ApplicationMeditation *application = nullptr;
        CircularProgressBar *progressBar        = nullptr;
        Text *timer                             = nullptr;

M module-apps/application-settings-new/windows/DisplayLightWindow.cpp => module-apps/application-settings-new/windows/DisplayLightWindow.cpp +7 -9
@@ 6,7 6,6 @@
#include "OptionSetting.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "OptionSetting.hpp"
#include "GuiTimer.hpp"

#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <i18n/i18n.hpp>


@@ 24,21 23,20 @@ namespace gui

        setTitle(utils::localize.get("app_settings_display_display_light"));

        timerTask = std::make_unique<app::GuiTimer>(
            "AmbientLightTimer", application, gui::lighting::AMBIENT_LIGHT_TIMER_MS, Timer::Type::Continous);
        timerCallback = [this](Item &it, Timer &task) { return onTimerTimeout(it, task); };
        timerTask->start();
        application->connect(std::move(timerTask), this);
        timerCallback = [this](Item &it, sys::Timer &task) { return onTimerTimeout(it, task); };
        timerTask     = app::GuiTimerFactory::createPeriodicTimer(
            application, this, "AmbientLightTimer", std::chrono::milliseconds{gui::lighting::AMBIENT_LIGHT_TIMER_MS});
        timerTask.start();
    }

    DisplayLightWindow::~DisplayLightWindow()
    {
        if (timerTask != nullptr) {
            timerTask->stop();
        if (timerTask.isActive()) {
            timerTask.stop();
        }
    }

    auto DisplayLightWindow::onTimerTimeout(Item &self, Timer &task) -> bool
    auto DisplayLightWindow::onTimerTimeout(Item &self, sys::Timer &task) -> bool
    {
        ambientLight = bsp::light_sensor::readout();
        refreshOptionsList();

M module-apps/application-settings-new/windows/DisplayLightWindow.hpp => module-apps/application-settings-new/windows/DisplayLightWindow.hpp +3 -2
@@ 3,6 3,7 @@

#pragma once

#include <module-apps/GuiTimer.hpp>
#include <module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <module-apps/application-settings-new/widgets/SpinBox.hpp>
#include <module-apps/application-settings-new/ApplicationSettings.hpp>


@@ 33,7 34,7 @@ namespace gui
        std::uint8_t brightnessValue                                     = 0;
        app::settingsInterface::ScreenLightSettings *screenLightSettings = nullptr;
        float ambientLight                                               = 0.0;
        std::unique_ptr<app::GuiTimer> timerTask;
        [[nodiscard]] auto onTimerTimeout(Item &self, Timer &task) -> bool;
        sys::TimerHandle timerTask;
        [[nodiscard]] auto onTimerTimeout(Item &self, sys::Timer &task) -> bool;
    };
} // namespace gui

M module-bsp/board/linux/vibrator/vibrator.cpp => module-bsp/board/linux/vibrator/vibrator.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "bsp/vibrator/vibrator.hpp"


@@ 17,7 17,7 @@ namespace bsp
        {
            LOG_DEBUG("vibration ends  \t\U0001f6d1\U0001f4f3");
        }
        void init(sys::ms pulse)
        void init(std::chrono::milliseconds pulse)
        {}
        void deinit()
        {}

M module-bsp/board/rt1051/bsp/vibrator/vibrator.cpp => module-bsp/board/rt1051/bsp/vibrator/vibrator.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "bsp/vibrator/vibrator.hpp"


@@ 24,7 24,7 @@ namespace bsp
            port->WritePin(static_cast<uint32_t>(BoardDefinitions::VIBRATOR_EN), 0);
        }

        void init(sys::ms pulse)
        void init(std::chrono::milliseconds pulse)
        {
            port = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::VIBRATOR_GPIO), DriverGPIOParams{});
            port->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output,

M module-bsp/bsp/vibrator/vibrator.hpp => module-bsp/bsp/vibrator/vibrator.hpp +2 -2
@@ 1,6 1,6 @@
#pragma once

#include <Service/Timer.hpp>
#include <module-sys/Timers/Timer.hpp>
#include <Utils.hpp>

#include <chrono>


@@ 23,7 23,7 @@ namespace bsp

        void enable();
        void disable();
        void init(sys::ms pulse = static_cast<sys::ms>(defaultVibraPulseMs));
        void init(std::chrono::milliseconds pulse = std::chrono::milliseconds{defaultVibraPulseMs});
        void deinit();
    } // namespace vibrator
} // namespace bsp

D module-gui/gui/core/Timer.hpp => module-gui/gui/core/Timer.hpp +0 -41
@@ 1,41 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

namespace gui
{
    using ms = unsigned int;

    /// gui::Timer helper class to be used as passed to gui::Item `onTimer` function
    /// this interface should be connected to real timer build with system Timer
    /// all gui timers should be `Coarse` timers
    class Timer
    {
      public:
        virtual ~Timer() = default;
        enum Type
        {
            Single,   /// single run timer
            Continous /// free running timers
        };
        virtual void start()              = 0;
        virtual void stop()               = 0;
        virtual void reset()              = 0;
        virtual void setInterval(ms time) = 0;
        [[nodiscard]] auto interval() const -> ms;

      protected:
        Type type = Single;

      public:
        [[nodiscard]] auto getType() const -> Type
        {
            return type;
        }
        virtual void setType(Type new_type)
        {
            type = new_type;
        };
    };
}; // namespace gui

M module-gui/gui/widgets/Item.cpp => module-gui/gui/widgets/Item.cpp +7 -7
@@ 1,12 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Item.hpp"
#include "BoundingBox.hpp" // for BoundingBox, BoundingBox::(anonymous)
#include "InputEvent.hpp"  // for InputEvent, KeyCode, InputEvent::State
#include "Navigation.hpp"  // for Navigation
#include "Timer.hpp"       // for Timer
#include <Timer.hpp>
#include <algorithm> // for find
#include <list>      // for list<>::iterator, list, operator!=, _List...
#include <memory>


@@ 515,7 513,7 @@ namespace gui
        return false;
    }

    auto Item::onTimer(Timer &timer) -> bool
    auto Item::onTimer(sys::Timer &timer) -> bool
    {
        if (timerCallback != nullptr) {
            return timerCallback(*this, timer);


@@ 523,10 521,12 @@ namespace gui
        return false;
    }

    void Item::detachTimer(Timer &timer)
    void Item::detachTimer(sys::Timer &timer)
    {
        auto el = std::find_if(timers.begin(), timers.end(), [&](auto &el) -> bool { return el.get() == &timer; });
        timers.erase(el);
        const auto it = std::find_if(timers.begin(), timers.end(), [&timer](auto &ptr) { return ptr == &timer; });
        if (it != timers.end()) {
            timers.erase(it);
        }
    }

    void Item::accept(GuiVisitor &visitor)

M module-gui/gui/widgets/Item.hpp => module-gui/gui/widgets/Item.hpp +8 -11
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 16,6 16,7 @@
#include <utility>              // for move
#include <core/DrawCommandForward.hpp>
#include <module-gui/gui/widgets/visitor/GuiVisitor.hpp>
#include <module-sys/Timers/Timer.hpp>

namespace gui
{


@@ 25,10 26,6 @@ namespace gui
{
    class Navigation;
} // namespace gui
namespace gui
{
    class Timer;
}

namespace gui
{


@@ 147,7 144,7 @@ namespace gui
        /// callback when timer is called on Item and onTimer is executed
        /// @param `this` : item
        /// @param `timer` : which triggered this callback
        std::function<bool(Item &, Timer &)> timerCallback = nullptr;
        std::function<bool(Item &, sys::Timer &)> timerCallback = nullptr;

        /// callback on navigation, called when item passes navigation to handle by its children
        /// @param `InputEvent` : input event e.g. key pressed


@@ 197,7 194,7 @@ namespace gui
        virtual bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim);
        /// called on Timer event in application, triggeres timerCallback
        /// @param : timer timer element which triggered this action
        virtual bool onTimer(Timer &timer);
        virtual bool onTimer(sys::Timer &timer);

        /// @}



@@ 378,13 375,13 @@ namespace gui
        /// @note this is needed so that timer for element would live as long as element lives.
        /// @details Timers can be attached to Item
        /// in order to pass on an ownership of timer to application/widget which uses its functionalities.
        void attachTimer(std::unique_ptr<Timer> &&timer)
        void attachTimer(sys::Timer *timer)
        {
            timers.emplace_back(std::move(timer));
            timers.push_back(timer);
        }

        /// remove timer from item and as a result - destory it.
        void detachTimer(Timer &timer);
        void detachTimer(sys::Timer &timer);

        /// simple check function to determine if item is active && visible.
        /// @return true if item is active and visible. Otherwise false.


@@ 407,7 404,7 @@ namespace gui

      private:
        /// list of attached timers to item.
        std::list<std::unique_ptr<Timer>> timers;
        std::list<sys::Timer *> timers;
    };
    /// gets navigation direction (LEFT,RIGHT,UP,DOWN) based on incoming input event
    /// @param[in] evt : input event e.g. key pressed

M module-services/service-antenna/ServiceAntenna.cpp => module-services/service-antenna/ServiceAntenna.cpp +14 -18
@@ 13,7 13,7 @@
#include <MessageType.hpp>
#include <module-utils/state/ServiceState.hpp>
#include <projdefs.h>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
#include <service-cellular/State.hpp>
#include <service-cellular/CellularServiceAPI.hpp>
#include <service-cellular/CellularMessage.hpp>


@@ 59,22 59,19 @@ ServiceAntenna::ServiceAntenna()
    : sys::Service(service::name::antenna, "", antennaServiceStackSize, sys::ServicePriority::Idle)
{
    LOG_INFO("[%s] Initializing", service::name::antenna);

    timer = std::make_unique<sys::Timer>("Antena", this, 5000, sys::Timer::Type::Periodic);
    timer->connect([&](sys::Timer &) {
        timer->stop();
        auto stateToSet = state->get();
        if (state->timeoutOccured(cpp_freertos::Ticks::GetTicks())) {
            LOG_WARN("State [ %s ] timeout occured, setting [ %s ] state",
                     c_str(state->get()),
                     c_str(state->getTimeoutState()));
            stateToSet = state->getTimeoutState();
        }
        state->set(stateToSet);
    });

    state = new utils::state::State<antenna::State>(this);

    timer = sys::TimerFactory::createPeriodicTimer(
        this, "Antenna", std::chrono::seconds{5}, [this](sys::Timer & /*timer*/) {
            timer.stop();
            auto stateToSet = state->get();
            if (state->timeoutOccured(cpp_freertos::Ticks::GetTicks())) {
                LOG_WARN("State [ %s ] timeout occured, setting [ %s ] state",
                         c_str(state->get()),
                         c_str(state->getTimeoutState()));
                stateToSet = state->getTimeoutState();
            }
            state->set(stateToSet);
        });
    bus.channels.push_back(sys::BusChannel::ServiceCellularNotifications);
    bus.channels.push_back(sys::BusChannel::AntennaNotifications);
}


@@ 258,8 255,7 @@ bool ServiceAntenna::HandleStateChange(antenna::State state)
    }
    if (!ret) {
        LOG_WARN("State [ %s ] not handled. Reloading timer.", c_str(state));
        timer->reload();
        timer->start();
        timer.start();
    }
    return ret;
}

M module-services/service-antenna/service-antenna/ServiceAntenna.hpp => module-services/service-antenna/service-antenna/ServiceAntenna.hpp +2 -5
@@ 10,6 10,7 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Worker.hpp>
#include <Timers/TimerHandle.hpp>
#include <service-db/DBServiceName.hpp>

#include <algorithm>


@@ 17,10 18,6 @@
#include <cstdint>
#include <memory>

namespace sys
{
    class Timer;
} // namespace sys
namespace utils
{
    namespace state


@@ 67,7 64,7 @@ class ServiceAntenna : public sys::Service
    utils::state::State<antenna::State> *state;
    bool HandleStateChange(antenna::State state);

    std::unique_ptr<sys::Timer> timer;
    sys::TimerHandle timer;

    bsp::cellular::antenna currentAntenna;
    uint32_t lastCsq    = 0;

M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +12 -15
@@ 7,7 7,7 @@
#include <module-apps/messages/AppMessage.hpp>
#include <Common.hpp>
#include <Service/Message.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
#include <SystemManager/SystemManager.hpp>
#include <SystemManager/messages/SystemManagerMessage.hpp>
#include <application-call/ApplicationCall.hpp>


@@ 105,17 105,14 @@ namespace app::manager
                                           const ApplicationName &_rootApplicationName)
        : Service{serviceName, {}, ApplicationManagerStackDepth},
          ApplicationManagerBase(std::move(launchers)), rootApplicationName{_rootApplicationName},
          actionsRegistry{[this](ActionEntry &action) { return handleAction(action); }},
          autoLockEnabled(false), autoLockTimer{std::make_unique<sys::Timer>(timerBlock,
                                                                             this,
                                                                             std::numeric_limits<sys::ms>::max(),
                                                                             sys::Timer::Type::SingleShot)},
          actionsRegistry{[this](ActionEntry &action) { return handleAction(action); }}, autoLockEnabled(false),
          settings(std::make_unique<settings::Settings>(this)),
          phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
    {
        autoLockTimer = sys::TimerFactory::createSingleShotTimer(
            this, timerBlock, sys::timer::InfiniteTimeout, [this](sys::Timer &) { onPhoneLocked(); });
        bus.channels.push_back(sys::BusChannel::PhoneModeChanges);
        registerMessageHandlers();
        autoLockTimer->connect([this](sys::Timer &) { onPhoneLocked(); });
    }

    sys::ReturnCodes ApplicationManager::InitHandler()


@@ 231,7 228,7 @@ namespace app::manager
        });
        connect(typeid(PreventBlockingRequest), [this](sys::Message *) {
            if (autoLockEnabled) {
                autoLockTimer->reload();
                autoLockTimer.start();
            }
            return std::make_shared<sys::ResponseMessage>();
        });


@@ 847,18 844,18 @@ namespace app::manager

        auto focusedApp = getFocusedApplication();
        if (focusedApp == nullptr || focusedApp->preventsAutoLocking()) {
            autoLockTimer->reload();
            autoLockTimer.start();
            return;
        }
        if (phoneModeObserver->isTetheringOn()) {
            autoLockTimer->reload();
            autoLockTimer.start();
            return;
        }
        std::unique_ptr<gui::SwitchData> appSwitchData = std::make_unique<gui::SwitchData>("AutoLock");
        std::unique_ptr<ActionRequest> actionRequest =
            std::make_unique<ActionRequest>(rootApplicationName, actions::AutoLock, std::move(appSwitchData));
        handleActionRequest(actionRequest.get());
        autoLockTimer->reload();
        autoLockTimer.start();
    }
    void ApplicationManager::displayLanguageChanged(std::string value)
    {


@@ 870,7 867,7 @@ namespace app::manager
    }
    void ApplicationManager::lockTimeChanged(std::string value)
    {
        autoLockTimer->stop();
        autoLockTimer.stop();
        /// It should not be allowed to set this timeout to less then 1s.
        if (utils::getNumericValue<unsigned int>(value) < 1000) {
            autoLockEnabled = false;


@@ 879,12 876,12 @@ namespace app::manager
        }
        ///> Something went wrong - reload timer
        if (value.empty()) {
            autoLockTimer->reload();
            autoLockTimer.start();
            return;
        }
        autoLockEnabled = true;
        autoLockTimer->setInterval(utils::getNumericValue<unsigned int>(value));
        autoLockTimer->reload();
        const auto interval = std::chrono::milliseconds{utils::getNumericValue<unsigned int>(value)};
        autoLockTimer.restart(interval);
        //?any additional action needed here?
    }
    void ApplicationManager::inputLanguageChanged(std::string value)

M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +5 -5
@@ 14,7 14,7 @@
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <Timers/TimerHandle.hpp>
#include <PhoneModes/Observer.hpp>
#include <SwitchData.hpp>



@@ 161,10 161,10 @@ namespace app::manager
        bool autoLockEnabled; ///< a flag which indicates whether the autoLockTimer should be armed.
                              /// @note: The flag value depends on database settings "gs_lock_time". If the
                              /// "gs_lock_time" is set to less than 1000 ms, it will be false, otherwise true.
        std::unique_ptr<sys::Timer> autoLockTimer; //< auto-lock timer to count time from last user's activity.
                                                   // If it reaches time defined in settings database application
                                                   // manager is sending signal to Application Desktop in order to
                                                   // lock screen.
        sys::TimerHandle autoLockTimer; //< auto-lock timer to count time from last user's activity.
                                        // If it reaches time defined in settings database application
                                        // manager is sending signal to Application Desktop in order to
                                        // lock screen.
        std::unique_ptr<settings::Settings> settings;
        std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;
        void displayLanguageChanged(std::string value);

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

#include "service-cellular/CellularRequestHandler.hpp"


@@ 6,7 6,8 @@
#include "service-cellular/ServiceCellular.hpp"

#include "Service/Message.hpp"
#include "Service/Timer.hpp"
#include "module-sys/Timers/TimerHandle.hpp"
#include "module-sys/Timers/TimerFactory.hpp"

#include "service-cellular/requests/CallRequest.hpp"
#include "service-cellular/requests/SupplementaryServicesRequest.hpp"


@@ 65,7 66,7 @@ void CellularRequestHandler::handle(cellular::CallRequest &request, at::Result &
        return;
    }
    // activate call state timer
    cellular.callStateTimer->reload();
    cellular.callStateTimer.start();
    // Propagate "Ringing" notification into system
    cellular.bus.sendMulticast(std::make_shared<CellularRingingMessage>(request.getNumber()),
                               sys::BusChannel::ServiceCellularNotifications);

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

#include "endpoints/developerMode/event/ATRequest.hpp"


@@ 36,7 36,7 @@
#include <Result.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
#include <Tables/CalllogTable.hpp>
#include <Tables/Record.hpp>
#include <Utils.hpp>


@@ 176,12 176,12 @@ ServiceCellular::ServiceCellular()
    bus.channels.push_back(sys::BusChannel::ServiceEvtmgrNotifications);
    bus.channels.push_back(sys::BusChannel::PhoneModeChanges);

    callStateTimer = std::make_unique<sys::Timer>("call_state", this, 1000);
    callStateTimer->connect([&](sys::Timer &) { CallStateTimerHandler(); });
    stateTimer = std::make_unique<sys::Timer>("state", this, 1000);
    stateTimer->connect([&](sys::Timer &) { handleStateTimer(); });
    ussdTimer = std::make_unique<sys::Timer>("ussd", this, 1000);
    ussdTimer->connect([&](sys::Timer &) { handleUSSDTimer(); });
    callStateTimer = sys::TimerFactory::createPeriodicTimer(
        this, "call_state", std::chrono::milliseconds{1000}, [this](sys::Timer &) { CallStateTimerHandler(); });
    stateTimer = sys::TimerFactory::createPeriodicTimer(
        this, "state", std::chrono::milliseconds{1000}, [&](sys::Timer &) { handleStateTimer(); });
    ussdTimer = sys::TimerFactory::createPeriodicTimer(
        this, "ussd", std::chrono::milliseconds{1000}, [this](sys::Timer &) { handleUSSDTimer(); });

    ongoingCall.setStartCallAction([=](const CalllogRecord &rec) {
        auto call = DBServiceAPI::CalllogAdd(this, rec);


@@ 1872,13 1872,13 @@ bool ServiceCellular::handle_status_check(void)
void ServiceCellular::startStateTimer(uint32_t timeout)
{
    stateTimeout = timeout;
    stateTimer->reload();
    stateTimer.start();
}

void ServiceCellular::stopStateTimer()
{
    stateTimeout = 0;
    stateTimer->stop();
    stateTimer.stop();
}

void ServiceCellular::handleStateTimer(void)


@@ 1979,7 1979,7 @@ void ServiceCellular::handleUSSDTimer(void)
    }
    else {
        LOG_WARN("USSD timeout occured, abotrig current session");
        ussdTimer->stop();
        ussdTimer.stop();
        CellularServiceAPI::USSDRequest(this, CellularUSSDMessage::RequestType::abortSesion);
    }
}


@@ 1999,10 1999,10 @@ void ServiceCellular::setUSSDTimer(void)
        break;
    }
    if (ussdTimeout == ussd::noTimeout) {
        ussdTimer->stop();
        ussdTimer.stop();
        return;
    }
    ussdTimer->reload();
    ussdTimer.start();
}

std::shared_ptr<cellular::RawCommandRespAsync> ServiceCellular::handleCellularStartOperatorsScan(


@@ 2184,7 2184,7 @@ auto ServiceCellular::handleCellularHangupCallMessage(CellularHangupCallMessage 
    if (channel) {
        if (channel->cmd(at::AT::ATH)) {
            AntennaServiceAPI::LockRequest(this, antenna::lockState::unlocked);
            callStateTimer->stop();
            callStateTimer.stop();
            if (!ongoingCall.endCall(CellularCall::Forced::True)) {
                LOG_ERROR("Failed to end ongoing call");
            }


@@ 2230,7 2230,7 @@ auto ServiceCellular::handleCellularListCallsMessage(CellularMessage *msg) -> st
        if (it != std::end(data)) {
            auto notification = std::make_shared<CellularCallActiveNotification>();
            bus.sendMulticast(std::move(notification), sys::BusChannel::ServiceCellularNotifications);
            callStateTimer->stop();
            callStateTimer.stop();
            return std::make_shared<CellularResponseMessage>(true);
        }
    }


@@ 2450,7 2450,7 @@ auto ServiceCellular::handleCallActiveNotification(sys::Message *msg) -> std::sh
}
auto ServiceCellular::handleCallAbortedNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    callStateTimer->stop();
    callStateTimer.stop();
    auto ret = ongoingCall.endCall();
    return std::make_shared<CellularResponseMessage>(ret);
}

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +4 -7
@@ 21,6 21,7 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/CpuSentinel.hpp>
#include <Timers/TimerHandle.hpp>
#include <bsp/common.hpp>
#include <utf8/UTF8.hpp>
#include <optional> // for optional


@@ 48,10 49,6 @@ namespace db
        class SMSSearchByTypeResult;
    } // namespace query
} // namespace db
namespace sys
{
    class Timer;
} // namespace sys

namespace packet_data
{


@@ 170,9 167,9 @@ class ServiceCellular : public sys::Service
    std::shared_ptr<sys::CpuSentinel> cpuSentinel;

    // used for polling for call state
    std::unique_ptr<sys::Timer> callStateTimer;
    std::unique_ptr<sys::Timer> stateTimer;
    std::unique_ptr<sys::Timer> ussdTimer;
    sys::TimerHandle callStateTimer;
    sys::TimerHandle stateTimer;
    sys::TimerHandle ussdTimer;
    void CallStateTimerHandler();
    DLC_channel::Callback_t notificationCallback = nullptr;


M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +9 -6
@@ 20,6 20,7 @@
#include <service-db/QueryMessage.hpp>
#include <purefs/filesystem_paths.hpp>
#include <module-sys/SystemManager/SystemManager.hpp>
#include <module-sys/Timers/TimerFactory.hpp>

#include <cinttypes>
#include <filesystem>


@@ 91,8 92,11 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
        desktopWorker->run();
    }

    transferTimer = std::make_unique<sys::Timer>("WorkerDesktop file upload", this, sdesktop::file_transfer_timeout);
    transferTimer->connect([&](sys::Timer &) { desktopWorker->cancelTransferOnTimeout(); });
    transferTimer =
        sys::TimerFactory::createPeriodicTimer(this,
                                               "WorkerDesktop file upload",
                                               std::chrono::milliseconds{sdesktop::file_transfer_timeout},
                                               [this](sys::Timer &) { desktopWorker->cancelTransferOnTimeout(); });

    connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) {
        auto request = static_cast<sdesktop::developerMode::DeveloperModeRequest *>(msg);


@@ 175,13 179,12 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
        if (timerStateMsg != nullptr && timerStateMsg->messageType == MessageType::TransferTimer) {
            switch (timerStateMsg->req) {
            case sdesktop::transfer::TransferTimerState::Start:
                transferTimer->start();
                break;
                [[fallthrough]];
            case sdesktop::transfer::TransferTimerState::Reload:
                transferTimer->reload();
                transferTimer.start();
                break;
            case sdesktop::transfer::TransferTimerState::Stop:
                transferTimer->stop();
                transferTimer.stop();
                break;
            case sdesktop::transfer::TransferTimerState::None:
                [[fallthrough]];

M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +2 -1
@@ 10,6 10,7 @@
#include "Service/Common.hpp"  // for ReturnCodes, ServicePowerMode
#include "Service/Message.hpp" // for MessagePointer, DataMessage (ptr only), ResponseMessage (ptr only)
#include "Service/Service.hpp" // for Service
#include "Timers/TimerHandle.hpp"
#include "Constants.hpp"
#include "WorkerDesktop.hpp"
#include "USBSecurityModel.hpp"


@@ 87,7 88,7 @@ class ServiceDesktop : public sys::Service
  private:
    std::unique_ptr<sdesktop::USBSecurityModel> usbSecurityModel;
    std::unique_ptr<settings::Settings> settings;
    std::unique_ptr<sys::Timer> transferTimer;
    sys::TimerHandle transferTimer;
    std::unique_ptr<sdesktop::bluetooth::BluetoothMessagesHandler> btMsgHandler;
};


M module-services/service-desktop/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/service-desktop/WorkerDesktop.hpp +0 -1
@@ 8,7 8,6 @@
#include "Service/Message.hpp"
#include "Service/Service.hpp"
#include "Service/Worker.hpp"
#include "Service/Timer.hpp"
#include "parser/ParserFSM.hpp"
#include "endpoints/EndpointFactory.hpp"
#include "bsp/usb/usb.hpp"

M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +7 -8
@@ 7,6 7,7 @@
#include <service-gui/messages/EinkInitialized.hpp>
#include <service-gui/Common.hpp>
#include <time/ScopedTime.hpp>
#include <Timers/TimerFactory.hpp>

#include <log/log.hpp>
#include <messages/EinkMessage.hpp>


@@ 28,10 29,10 @@ namespace service::eink
    } // namespace

    ServiceEink::ServiceEink(const std::string &name, std::string parent)
        : sys::Service(name, std::move(parent), ServceEinkStackDepth), currentState{State::Running},
          displayPowerOffTimer{
              std::make_unique<sys::Timer>(this, displayPowerOffTimeout.count(), sys::Timer::Type::SingleShot)}
        : sys::Service(name, std::move(parent), ServceEinkStackDepth), currentState{State::Running}
    {
        displayPowerOffTimer = sys::TimerFactory::createSingleShotTimer(
            this, "einkDisplayPowerOff", displayPowerOffTimeout, [this](sys::Timer &) { display.powerOff(); });
        connect(typeid(EinkModeMessage),
                [this](sys::Message *message) -> sys::MessagePointer { return handleEinkModeChangedMessage(message); });



@@ 40,8 41,6 @@ namespace service::eink

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

        displayPowerOffTimer->connect([this](sys::Timer &it) { display.powerOff(); });
    }

    sys::MessagePointer ServiceEink::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *response)


@@ 143,9 142,9 @@ namespace service::eink

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

        auto displayPowerOffTimerReload = gsl::finally([this]() { displayPowerOffTimer->reload(); });
        auto displayPowerOffTimerReload = gsl::finally([this]() { displayPowerOffTimer.start(); });

        if (const auto status = prepareDisplay(refreshMode, WaveformTemperature::KEEP_CURRENT);
            status != EinkStatus_e ::EinkOK) {


@@ 179,7 178,7 @@ namespace service::eink
    {
        EinkStatus_e status;

        displayPowerOffTimer->stop();
        displayPowerOffTimer.stop();
        display.powerOn();

        const auto temperature = behaviour == WaveformTemperature::KEEP_CURRENT ? display.getLastTemperature()

M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +2 -2
@@ 6,7 6,7 @@
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <Timers/TimerHandle.hpp>
#include <Service/CpuSentinel.hpp>

#include "EinkDisplay.hpp"


@@ 62,7 62,7 @@ namespace service::eink

        EinkDisplay display;
        State currentState;
        std::unique_ptr<sys::Timer> displayPowerOffTimer;
        sys::TimerHandle displayPowerOffTimer;
        std::shared_ptr<sys::CpuSentinel> cpuSentinel;
    };
} // namespace service::eink

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +8 -5
@@ 15,6 15,7 @@
#include <BaseInterface.hpp>
#include <MessageType.hpp>
#include <Service/Worker.hpp>
#include <Timers/TimerFactory.hpp>
#include <SystemManager/Constants.hpp>
#include <SystemManager/SystemManager.hpp>
#include <bsp/common.hpp>


@@ 55,8 56,11 @@ namespace

EventManager::EventManager(const std::string &name)
    : sys::Service(name, "", stackDepth),
      settings(std::make_shared<settings::Settings>(this)), loggerTimer{std::make_unique<sys::Timer>(
                                                                loggerTimerName, this, loggerDelayMs)},
      settings(std::make_shared<settings::Settings>(this)), loggerTimer{sys::TimerFactory::createPeriodicTimer(
                                                                this,
                                                                loggerTimerName,
                                                                std::chrono::milliseconds{loggerDelayMs},
                                                                [this](sys::Timer & /*timer*/) { dumpLogsToFile(); })},
      screenLightControl(std::make_unique<screen_light_control::ScreenLightControl>(settings, this)),
      Vibra(std::make_unique<vibra_handle::Vibra>(this))
{


@@ 64,8 68,7 @@ EventManager::EventManager(const std::string &name)
    alarmTimestamp = 0;
    alarmID        = 0;
    bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
    loggerTimer->connect([&](sys::Timer &) { dumpLogsToFile(); });
    loggerTimer->start();
    loggerTimer.start();
}

EventManager::~EventManager()


@@ 391,7 394,7 @@ bool EventManager::processKeypadBacklightRequest(bsp::keypad_backlight::Action a
    return response;
}

bool EventManager::processVibraRequest(bsp::vibrator::Action act, sys::ms RepetitionTime)
bool EventManager::processVibraRequest(bsp::vibrator::Action act, std::chrono::milliseconds RepetitionTime)
{
    switch (act) {
    case bsp::vibrator::Action::pulse:

M module-services/service-evtmgr/api/EventManagerServiceAPI.cpp => module-services/service-evtmgr/api/EventManagerServiceAPI.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-evtmgr/EventManagerServiceAPI.hpp>


@@ 60,7 60,7 @@ void EventManagerServiceAPI::vibraStop(sys::Service *serv)
/*
 * @brief Call repetitive vibra pulses for given time [ms]
 */
void EventManagerServiceAPI::vibraPulseRepeat(sys::Service *serv, sys::ms time)
void EventManagerServiceAPI::vibraPulseRepeat(sys::Service *serv, std::chrono::milliseconds time)
{
    serv->bus.sendUnicast(std::make_shared<sevm::VibraMessage>(bsp::vibrator::Action::pulseRepeat, time),
                          service::name::evt_manager);

M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp +16 -13
@@ 1,11 1,11 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ScreenLightControl.hpp"

#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
#include <agents/settings/SystemSettings.hpp>

namespace screen_light_control


@@ 36,9 36,14 @@ namespace screen_light_control
    ScreenLightControl::ScreenLightControl(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
        : settings(settings)
    {
        controlTimer = std::make_unique<sys::Timer>("LightControlTimer", parent, CONTROL_TIMER_MS);
        readoutTimer = std::make_unique<sys::Timer>("LightSensorReadoutTimer", parent, READOUT_TIMER_MS);

        controlTimer = sys::TimerFactory::createPeriodicTimer(parent,
                                                              "LightControlTimer",
                                                              std::chrono::milliseconds{CONTROL_TIMER_MS},
                                                              [this](sys::Timer &) { controlTimerCallback(); });
        readoutTimer = sys::TimerFactory::createPeriodicTimer(parent,
                                                              "LightSensorReadoutTimer",
                                                              std::chrono::milliseconds{READOUT_TIMER_MS},
                                                              [this](sys::Timer &) { readoutTimerCallback(); });
        initFromSettings();
    }



@@ 130,16 135,14 @@ namespace screen_light_control

    void ScreenLightControl::enableTimers()
    {
        controlTimer->connect([&](sys::Timer &) { controlTimerCallback(); });
        readoutTimer->connect([&](sys::Timer &) { readoutTimerCallback(); });
        controlTimer->start();
        readoutTimer->start();
        controlTimer.start();
        readoutTimer.start();
    }

    void ScreenLightControl::disableTimers()
    {
        controlTimer->stop();
        readoutTimer->stop();
        controlTimer.stop();
        readoutTimer.stop();
    }

    void ScreenLightControl::setAutomaticModeParameters(const Parameters &params)


@@ 197,8 200,8 @@ namespace screen_light_control
    {
        bsp::eink_frontlight::turnOff();
        bsp::light_sensor::standby();
        controlTimer->stop();
        readoutTimer->stop();
        controlTimer.stop();
        readoutTimer.stop();
        lightOn = false;
    }
} // namespace screen_light_control

M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp +4 -8
@@ 1,17 1,13 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-sys/Timers/TimerHandle.hpp>
#include <service-db/service-db/Settings.hpp>
#include "ControlFunctions.hpp"
#include <Utils.hpp>

namespace sys
{
    class Timer;
}

/// Screen light control algorithm. Automatic/Manual mode of operation.
/// Processing of ambient light sensor input to screen brightness output.
namespace screen_light_control


@@ 91,8 87,8 @@ namespace screen_light_control
        static constexpr inline auto CONTROL_TIMER_MS = 25;
        static constexpr inline auto READOUT_TIMER_MS = 500;

        std::unique_ptr<sys::Timer> controlTimer;
        std::unique_ptr<sys::Timer> readoutTimer;
        sys::TimerHandle controlTimer;
        sys::TimerHandle readoutTimer;

        bool lightOn                                               = false;
        screen_light_control::ScreenLightMode automaticMode        = ScreenLightMode::Manual;

M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +3 -3
@@ 16,7 16,6 @@
#include <bsp/torch/torch.hpp>
#include <bsp/keypad_backlight/keypad_backlight.hpp>
#include <vibra/Vibra.hpp>
#include <Timer.hpp>

#include <string>



@@ 149,12 148,13 @@ namespace sevm
    class VibraMessage : public Message
    {
      public:
        VibraMessage(bsp::vibrator::Action act, sys::ms rptTime = bsp::vibrator::defaultVibraPauseMs)
        VibraMessage(bsp::vibrator::Action act,
                     std::chrono::milliseconds rptTime = std::chrono::milliseconds{bsp::vibrator::defaultVibraPauseMs})
            : Message(MessageType::VibraPulseMessage), action(act), repetitionTime(rptTime)
        {}

        bsp::vibrator::Action action;
        sys::ms repetitionTime;
        std::chrono::milliseconds repetitionTime;
    };

} /* namespace sevm*/

M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +4 -3
@@ 9,7 9,7 @@
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <Timers/TimerHandle.hpp>
#include <Service/Worker.hpp>
#include <bsp/common.hpp>
#include <bsp/keyboard/key_codes.hpp>


@@ 31,12 31,13 @@ class EventManager : public sys::Service
    static constexpr auto stackDepth = 4096;
    void handleMinuteUpdate(time_t timestamp);
    bool processKeypadBacklightRequest(bsp::keypad_backlight::Action act);
    bool processVibraRequest(bsp::vibrator::Action act, sys::ms RepetitionTime = static_cast<sys::ms>(1000));
    bool processVibraRequest(bsp::vibrator::Action act,
                             std::chrono::milliseconds RepetitionTime = std::chrono::milliseconds{1000});
    void toggleTorchOnOff();
    void toggleTorchColor();

    std::shared_ptr<settings::Settings> settings;
    std::unique_ptr<sys::Timer> loggerTimer;
    sys::TimerHandle loggerTimer;

  protected:
    std::unique_ptr<WorkerEvent> EventWorker;

M module-services/service-evtmgr/service-evtmgr/EventManagerServiceAPI.hpp => module-services/service-evtmgr/service-evtmgr/EventManagerServiceAPI.hpp +4 -3
@@ 1,12 1,13 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 <chrono>

#include <MessageType.hpp>
#include <Service/Message.hpp>
#include <bsp/common.hpp>
#include <Service/Timer.hpp>

namespace sys
{


@@ 36,7 37,7 @@ namespace EventManagerServiceAPI
    /*
     * @brief Call repetitive vibra pulses for given time [ms]
     */
    void vibraPulseRepeat(sys::Service *serv, sys::ms time);
    void vibraPulseRepeat(sys::Service *serv, std::chrono::milliseconds time);

    /*
     * @brief Call repetitive vibra pulses until stop message is sent

M module-services/service-evtmgr/vibra/Vibra.cpp => module-services/service-evtmgr/vibra/Vibra.cpp +39 -32
@@ 1,41 1,40 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Vibra.hpp"
#include "SystemManager/Constants.hpp"
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>

#include <common_data/EventStore.hpp>

namespace vibra_handle
{
    Vibra::Vibra(sys::Service *parent)
    Vibra::Vibra(sys::Service *parent) : parent{parent}
    {
        vibratorTimerOneshot =
            std::make_unique<sys::Timer>("VibraOneshotTimer", parent, bsp::vibrator::defaultVibraPulseMs);
        vibratorTimerPause =
            std::make_unique<sys::Timer>("VibraPauseTimer", parent, bsp::vibrator::defaultVibraPauseMs);

        vibratorTimerOneshot->connect(nullTimerCallback);
        vibratorTimerPause->connect(nullTimerCallback);

        vibratorTimerOneshot->stop();
        vibratorTimerPause->stop();
    }

    void Vibra::intPulse(bool repetitive)
    {
        if (repetitive) {
            vibratorTimerOneshot->connect([&](sys::Timer &) {
                bsp::vibrator::disable();
                vibratorTimerPause->start();
            });
            vibratorTimer =
                sys::TimerFactory::createSingleShotTimer(parent,
                                                         "VibraOneshotTimer",
                                                         std::chrono::milliseconds{bsp::vibrator::defaultVibraPulseMs},
                                                         [this](sys::Timer & /*timer*/) {
                                                             bsp::vibrator::disable();
                                                             vibratorTimerPause.start();
                                                         });
        }
        else {
            vibratorTimerOneshot->connect([&](sys::Timer &) { bsp::vibrator::disable(); });
            vibratorTimer =
                sys::TimerFactory::createSingleShotTimer(parent,
                                                         "VibraOneshotTimer",
                                                         std::chrono::milliseconds{bsp::vibrator::defaultVibraPulseMs},
                                                         [](sys::Timer & /*timer*/) { bsp::vibrator::disable(); });
        }

        bsp::vibrator::enable();
        vibratorTimerOneshot->start();
        vibratorTimer.start();
    }

    void Vibra::Pulse()


@@ 43,24 42,32 @@ namespace vibra_handle
        intPulse(false);
    }

    void Vibra::PulseRepeat(sys::ms time)
    void Vibra::PulseRepeat(std::chrono::milliseconds time)
    {
        repetitions = static_cast<int>(time) / (static_cast<int>(bsp::vibrator::defaultVibraPulseMs) +
                                                static_cast<int>(bsp::vibrator::defaultVibraPauseMs));
        repetitions = static_cast<int>(time.count()) / (static_cast<int>(bsp::vibrator::defaultVibraPulseMs) +
                                                        static_cast<int>(bsp::vibrator::defaultVibraPauseMs));

        vibratorTimerPause->connect([&](sys::Timer &) {
            if (repetitions) /// call itself for calculated number of repetitions
            {
                repetitions--;
                intPulse(true);
            }
        });
        vibratorTimerPause = sys::TimerFactory::createSingleShotTimer(
            parent,
            "VibraPauseTimer",
            std::chrono::milliseconds{bsp::vibrator::defaultVibraPauseMs},
            [this](sys::Timer & /*timer*/) {
                if (repetitions > 0) // call itself for calculated number of repetitions
                {
                    repetitions--;
                    intPulse(true);
                }
            });
        intPulse(true);
    }

    void Vibra::PulseRepeat()
    {
        vibratorTimerPause->connect([&](sys::Timer &) { intPulse(true); });
        vibratorTimerPause =
            sys::TimerFactory::createSingleShotTimer(parent,
                                                     "VibraPauseTimer",
                                                     std::chrono::milliseconds{bsp::vibrator::defaultVibraPauseMs},
                                                     [&](sys::Timer & /*timer*/) { intPulse(true); });
        intPulse(true);
    }



@@ 68,8 75,8 @@ namespace vibra_handle
    {
        repetitions = 1;
        bsp::vibrator::disable();
        vibratorTimerPause->stop();
        vibratorTimerOneshot->stop();
        vibratorTimerPause.stop();
        vibratorTimer.stop();
    }

} // namespace vibra_handle

M module-services/service-evtmgr/vibra/Vibra.hpp => module-services/service-evtmgr/vibra/Vibra.hpp +6 -6
@@ 1,14 1,14 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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/Service.hpp>
#include <Timers/TimerHandle.hpp>
#include <bsp/vibrator/vibrator.hpp>

namespace sys
{
    class Timer;
    class Service;
} // namespace sys



@@ 25,17 25,17 @@ namespace vibra_handle
        /// set the same way.
        void Pulse();
        /// but we also want to repeat pulses during eg. full length of ringtone
        void PulseRepeat(sys::ms time);
        void PulseRepeat(std::chrono::milliseconds time);
        void PulseRepeat(); /// infinite repeat ... until stop summoned
        void PulseRepeatStop();

      private:
        std::unique_ptr<sys::Timer> vibratorTimerOneshot;
        std::unique_ptr<sys::Timer> vibratorTimerPause;
        sys::TimerHandle vibratorTimer;
        sys::TimerHandle vibratorTimerPause;
        sys::Service *parent;

        int repetitions = 1;

        void intPulse(bool repetitive);
        std::function<void(sys::Timer &)> nullTimerCallback{};
    };
} // namespace vibra_handle

M module-services/service-fileindexer/StartupIndexer.cpp => module-services/service-fileindexer/StartupIndexer.cpp +14 -13
@@ 1,8 1,9 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "StartupIndexer.hpp"
#include "messages/FileChangeMessage.hpp"
#include <Timers/TimerFactory.hpp>
#include <filesystem>
//#include <ff_stdio_listdir_recursive.h>
#include <purefs/filesystem_paths.hpp>


@@ 58,18 59,18 @@ namespace service::detail
    // Setup timers for notification
    auto StartupIndexer::setupTimers(std::shared_ptr<sys::Service> svc, std::string_view svc_name) -> void
    {
        if (!mIdxTimer) {
            mIdxTimer = std::make_unique<sys::Timer>("file_indexing", svc.get(), timer_indexing_time);
            mIdxTimer->connect([this, svc](sys::Timer &) {
                if (!mMsgs.empty()) {
                    svc->bus.sendUnicast(mMsgs.front(), std::string(service::name::file_indexer));
                    mMsgs.pop_front();
                }
                else {
                    mIdxTimer->stop();
                }
            });
            mIdxTimer->start();
        if (!mIdxTimer.isValid()) {
            mIdxTimer = sys::TimerFactory::createPeriodicTimer(
                svc.get(), "file_indexing", std::chrono::milliseconds{timer_indexing_time}, [this, svc](sys::Timer &) {
                    if (!mMsgs.empty()) {
                        svc->bus.sendUnicast(mMsgs.front(), std::string(service::name::file_indexer));
                        mMsgs.pop_front();
                    }
                    else {
                        mIdxTimer.stop();
                    }
                });
            mIdxTimer.start();
        }
    }
} // namespace service::detail

M module-services/service-fileindexer/StartupIndexer.hpp => module-services/service-fileindexer/StartupIndexer.hpp +3 -3
@@ 1,10 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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/Service.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerHandle.hpp>

#include <list>



@@ 50,6 50,6 @@ namespace service::detail

      private:
        std::list<std::shared_ptr<msg::FileChangeMessage>> mMsgs;
        std::unique_ptr<sys::Timer> mIdxTimer;
        sys::TimerHandle mIdxTimer;
    };
} // namespace service::detail

M module-services/service-fota/ServiceFota.cpp => module-services/service-fota/ServiceFota.cpp +7 -7
@@ 11,7 11,7 @@
#include <Modem/TS0710/DLC_channel.h>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
#include <log/log.hpp>
#include <module-cellular/at/Result.hpp>
#include <module-cellular/at/UrcFactory.hpp>


@@ 47,12 47,12 @@ namespace FotaService
        bus.channels.push_back(sys::BusChannel::ServiceFotaNotifications);
        bus.channels.push_back(sys::BusChannel::ServiceCellularNotifications);

        connectionTimer = std::make_unique<sys::Timer>("Fota", this, defaultTimer);
        connectionTimer->connect([&](sys::Timer &) {
            std::shared_ptr<InternetRequestMessage> msg =
                std::make_shared<InternetRequestMessage>(MessageType::CellularListCurrentCalls);
            bus.sendUnicast(msg, service::name::fota);
        });
        connectionTimer = sys::TimerFactory::createPeriodicTimer(
            this, "Fota", std::chrono::milliseconds{defaultTimer}, [this](sys::Timer &) {
                std::shared_ptr<InternetRequestMessage> msg =
                    std::make_shared<InternetRequestMessage>(MessageType::CellularListCurrentCalls);
                bus.sendUnicast(msg, service::name::fota);
            });
        registerMessageHandlers();
    }


M module-services/service-fota/service-fota/ServiceFota.hpp => module-services/service-fota/service-fota/ServiceFota.hpp +2 -6
@@ 11,6 11,7 @@
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Timers/TimerHandle.hpp>
#include <service-cellular/ServiceCellular.hpp>

#include <service-db/DBServiceName.hpp>


@@ 23,11 24,6 @@
class DLC_channel;
class FotaUrcHandler;

namespace sys
{
    class Timer;
} // namespace sys

namespace service::name
{
    constexpr inline auto fota = "ServiceFota";


@@ 89,7 85,7 @@ namespace FotaService
         */
        sys::MessagePointer handleRawProgress(sys::Message *req);

        std::unique_ptr<sys::Timer> connectionTimer;
        sys::TimerHandle connectionTimer;
        void getApnConfiguration();
        void getConfig();
        void getActiveCotext();

M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +9 -9
@@ 17,6 17,7 @@
#include <service-eink/messages/ImageMessage.hpp>
#include <service-eink/messages/EinkMessage.hpp>
#include <service-eink/messages/PrepareDisplayEarlyRequest.hpp>
#include <Timers/TimerFactory.hpp>
#include <SystemManager/SystemManager.hpp>

#include <gsl/gsl_util>


@@ 37,8 38,6 @@ namespace service::gui
    ServiceGUI::ServiceGUI(const std::string &name, std::string parent)
        : sys::Service(name, parent, ServiceGuiStackDepth), commandsQueue{std::make_unique<DrawCommandsQueue>(
                                                                CommandsQueueCapacity)},
          contextReleaseTimer{
              std::make_unique<sys::Timer>(this, ContextReleaseTimeout.count(), sys::Timer::Type::SingleShot)},
          currentState{State::NotInitialised}, lastRenderScheduled{false}, waitingForLastRender{false}
    {
        initAssetManagers();


@@ 210,12 209,13 @@ namespace service::gui
    {
        // Whenever the response from ServiceEink doesn't come, the context has to be released automatically after a
        // timeout.
        contextReleaseTimer->connect([this, contextId](sys::Timer &it) {
            eink::ImageDisplayedNotification notification{contextId};
            handleImageDisplayedNotification(&notification);
            LOG_WARN("Context #%d released after timeout. Does ServiceEink respond properly?", contextId);
        });
        contextReleaseTimer->start();
        contextReleaseTimer = sys::TimerFactory::createSingleShotTimer(
            this, "contextRelease", ContextReleaseTimeout, [this, contextId](sys::Timer &it) {
                eink::ImageDisplayedNotification notification{contextId};
                handleImageDisplayedNotification(&notification);
                LOG_WARN("Context #%d released after timeout. Does ServiceEink respond properly?", contextId);
            });
        contextReleaseTimer.start();
    }

    void ServiceGUI::cacheRender(int contextId, ::gui::RefreshModes refreshMode)


@@ 241,7 241,7 @@ namespace service::gui
        const auto msg       = static_cast<eink::ImageDisplayedNotification *>(message);
        const auto contextId = msg->getContextId();
        contextPool->returnContext(contextId);
        contextReleaseTimer->stop();
        contextReleaseTimer.stop();
        setState(State::Idle);

        // Even if the next render is already cached, if any context in the pool is currently being processed, then

M module-services/service-gui/ServiceGUI.hpp => module-services/service-gui/ServiceGUI.hpp +2 -2
@@ 7,7 7,7 @@
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <Timers/TimerHandle.hpp>

#include <service-db/DBServiceName.hpp>



@@ 89,7 89,7 @@ namespace service::gui
        std::unique_ptr<DrawCommandsQueue> commandsQueue;
        std::unique_ptr<::gui::ColorScheme> colorSchemeUpdate;
        std::optional<CachedRender> cachedRender;
        std::unique_ptr<sys::Timer> contextReleaseTimer;
        sys::TimerHandle contextReleaseTimer;
        State currentState;
        bool lastRenderScheduled;
        bool waitingForLastRender;

M module-services/service-time/ServiceTime.hpp => module-services/service-time/ServiceTime.hpp +0 -1
@@ 14,7 14,6 @@
#include <Service/Service.hpp>
#include <module-db/queries/calendar/QueryEventsEdit.hpp>
#include <module-db/queries/calendar/QueryEventsGet.hpp>
#include <module-sys/Service/Timer.hpp>

#include <functional>
#include <string> // for allocator, string

M module-services/service-time/service-time/TimeEvents.hpp => module-services/service-time/service-time/TimeEvents.hpp +6 -6
@@ 1,11 1,11 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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/Service.hpp>
#include <module-db/queries/calendar/QueryEventsEdit.hpp>
#include <module-sys/Service/Timer.hpp>
#include <module-sys/Timers/TimerHandle.hpp>

#include <cstdint>
#include <memory>


@@ 25,10 25,10 @@ namespace stm
    class TimeEvents
    {
      private:
        bool timersProcessingStarted               = false;
        std::unique_ptr<sys::Timer> fireEventTimer = nullptr;
        sys::Service *serv                         = nullptr;
        std::unique_ptr<sys::Timer> &timer();
        bool timersProcessingStarted = false;
        sys::TimerHandle fireEventTimer;
        sys::Service *serv = nullptr;
        sys::TimerHandle &timer();

      protected:
        sys::Service *service()

M module-services/service-time/timeEvents/TimeEvents.cpp => module-services/service-time/timeEvents/TimeEvents.cpp +10 -9
@@ 1,10 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-time/TimeEvents.hpp>

#include <Common/Query.hpp>
#include <Service/Timer.hpp>
#include <module-sys/Timers/TimerFactory.hpp>

#include <utility>



@@ 25,11 25,13 @@ namespace stm
        stopTimer();
    }

    std::unique_ptr<sys::Timer> &TimeEvents::timer()
    sys::TimerHandle &TimeEvents::timer()
    {
        if (fireEventTimer == nullptr) {
            fireEventTimer = std::make_unique<sys::Timer>(
                timerName(), service(), eventTimerInitInterval, sys::Timer::Type::SingleShot);
        if (!fireEventTimer.isValid()) {
            fireEventTimer = sys::TimerFactory::createSingleShotTimer(
                service(), timerName(), std::chrono::milliseconds{eventTimerInitInterval}, [this](sys::Timer &) {
                    fireEventTimerCallback();
                });
        }
        return fireEventTimer;
    }


@@ 58,7 60,7 @@ namespace stm

    void TimeEvents::stopTimer()
    {
        timer()->stop();
        timer().stop();
    }

    void TimeEvents::recreateTimer(uint32_t interval)


@@ 68,8 70,7 @@ namespace stm
            return;
        }

        timer()->connect([=](sys::Timer &) { fireEventTimerCallback(); });
        timer()->reload(interval);
        timer().restart(std::chrono::milliseconds{interval});
    }

    void TimeEvents::fireEventTimerCallback()

M module-sys/CMakeLists.txt => module-sys/CMakeLists.txt +3 -1
@@ 12,7 12,9 @@ set(SOURCES
        ${CMAKE_CURRENT_SOURCE_DIR}/Service/Worker.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Service/Message.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Service/Service.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Service/Timer.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Timers/SystemTimer.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Timers/TimerHandle.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Timers/TimerFactory.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Service/CpuSentinel.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/PhoneModes/Subject.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/PhoneModes/Observer.cpp

M module-sys/Service/Service.cpp => module-sys/Service/Service.cpp +30 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Service.hpp"


@@ 7,8 7,9 @@
#include "Service/Common.hpp"  // for BusChannels, ReturnCodes, ReturnCodes...
#include "Service/Mailbox.hpp" // for Mailbox
#include "Service/Message.hpp" // for Message, MessagePointer, DataMessage, Resp...
#include "Timer.hpp"           // for Timer
#include "TimerMessage.hpp"    // for TimerMessage
#include "Timers/SystemTimer.hpp"
#include "module-sys/Timers/TimerHandle.hpp"  // for Timer
#include "module-sys/Timers/TimerMessage.hpp" // for TimerMessage
#include "log/debug.hpp"       // for DEBUG_SERVICE_MESSAGES
#include "log/log.hpp"         // for LOG_ERROR, LOG_DEBUG, LOG_FATAL
#include "mutex.hpp"           // for cpp_freertos


@@ 201,16 202,29 @@ namespace sys
            return ReturnCodes::Failure;
        }

        auto timer = timers.get(timer_message->getTimer());
        if (timer == timers.noTimer()) {
        auto sysTimer = timer_message->getTimer();
        auto timer    = timers.get(sysTimer);
        if (timer == nullptr) {
            LOG_ERROR("No such timer registered in Service");
            return ReturnCodes::Failure;
        }

        (*timer)->onTimeout();
        timer->onTimeout();
        return ReturnCodes::Success;
    }

    void Service::Timers::attach(timer::SystemTimer *timer)
    {
        list.push_back(timer);
    }

    void Service::Timers::detach(timer::SystemTimer *timer)
    {
        const auto it = std::find(list.begin(), list.end(), timer);
        if (it != list.end()) {
            list.erase(it);
        }
    }

    void Service::Timers::stop()
    {
        for (auto timer : list) {


@@ 218,6 232,15 @@ namespace sys
        }
    }

    auto Service::Timers::get(timer::SystemTimer *timer) noexcept -> timer::SystemTimer *
    {
        auto it = std::find(list.begin(), list.end(), timer);
        if (it == list.end()) {
            return nullptr;
        }
        return *it;
    }

    void Service::sendCloseReadyMessage(Service *service)
    {
        auto msg = std::make_shared<sys::ReadyToCloseMessage>();

M module-sys/Service/Service.hpp => module-sys/Service/Service.hpp +11 -26
@@ 25,11 25,13 @@

namespace sys
{
    class Timer;
} // namespace sys
namespace sys
{
    struct Proxy;
    class Timer;

    namespace timer
    {
        class SystemTimer;
    } // namespace timer
} // namespace sys

namespace sys


@@ 121,33 123,16 @@ namespace sys

        class Timers
        {

            friend Timer;
            friend timer::SystemTimer;

          private:
            std::vector<Timer *> list;
            auto attach(Timer *timer)
            {
                list.push_back(timer);
            }

            void detach(Timer *timer)
            {
                list.erase(std::find(list.begin(), list.end(), timer));
            }
            std::vector<timer::SystemTimer *> list;
            void attach(timer::SystemTimer *timer);
            void detach(timer::SystemTimer *timer);

          public:
            void stop();

            [[nodiscard]] auto get(Timer *timer) const
            {
                return std::find(list.begin(), list.end(), timer);
            }

            [[nodiscard]] auto noTimer() const
            {
                return std::end(list);
            }
            [[nodiscard]] auto get(timer::SystemTimer *timer) noexcept -> timer::SystemTimer *;
        } timers;

      public:

D module-sys/Service/Timer.cpp => module-sys/Service/Timer.cpp +0 -120
@@ 1,120 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Timer.hpp"
#include "Service.hpp"
#include "TimerMessage.hpp"
#include <log/log.hpp>
#include <projdefs.h>
#include <limits>
#include <memory>
#include <cstdint>

#if DEBUG_TIMER == 1
#define log_debug(...) LOG_DEBUG(__VA_ARGS__)
#else
#define log_debug(...)
#endif

#define log_error(...) LOG_ERROR(__VA_ARGS__)
#define log_warn(...)  LOG_WARN(__VA_ARGS__)

namespace sys
{

    const ms Timer::timeout_infinite = std::numeric_limits<ms>().max();
    static uint32_t timer_id;

    auto toName(const std::string &val, uint32_t no) -> std::string
    {
        return val + "_" + std::to_string(no);
    }

    Timer::Timer(const std::string &name, Service *service, ms interval, Type type)
        : cpp_freertos::Timer((toName(name, timer_id)).c_str(), pdMS_TO_TICKS(interval), type == Type::Periodic),
          parent(service), type(type), interval(interval), name(toName(name, timer_id))
    {
        if (service != nullptr) {
            service->getTimers().attach(this);
        }
        else {
            log_error("Bad timer creation!");
        }
        ++timer_id;
        log_debug("Timer %s created %s", name.c_str(), type == Type::Periodic ? "periodic" : "singleshot");
    }

    Timer::Timer(Service *parent, ms interval, Type type) : Timer("Timer", parent, interval, type)
    {}

    Timer::~Timer()
    {
        parent->getTimers().detach(this);
        stop();
    }

    void Timer::Run()
    {
        auto msg = std::make_shared<TimerMessage>(this);
        if (parent == nullptr) {
            log_error("Timer %s error: no parent service", name.c_str());
            return;
        }
        if (!parent->bus.sendUnicast(msg, parent->GetName())) {
            LOG_ERROR("Timer %s error: bus error", name.c_str());
            return;
        }
    }

    void Timer::start()
    {
        log_debug("Timer %s start!", name.c_str());
        isActive = true;
        Start(0);
    }

    void Timer::reload(ms from_time)
    {
        Stop(0); // to avoid retriggering timer
        if (from_time != 0) {
            interval = from_time;
            SetPeriod(pdMS_TO_TICKS(interval));
        }
        log_debug("Timer %s reload!", name.c_str());
        isActive = true;
        Start(0); // start with no waittime
    }

    void Timer::stop()
    {
        log_debug("Timer %s stop!", name.c_str());
        // make sure callback is not called even if it is already in the queue
        isActive = false;
        Stop(0);
    }

    void Timer::setInterval(ms new_interval)
    {
        log_debug("Timer %s set interval to: %d ms!", name.c_str(), static_cast<unsigned int>(interval));
        interval = new_interval;
        SetPeriod(pdMS_TO_TICKS(new_interval), 0);
    }

    void Timer::onTimeout()
    {
        log_debug("Timer %s tick", name.c_str());
        if (callback != nullptr && isActive) {
            log_debug("Timer %s callback run!", name.c_str());
            callback(*this);
            return;
        }
        log_warn(
            "callback from %s non valid - %d, or not active - %d", name.c_str(), callback == nullptr, isActive != true);
    }

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

} // namespace sys

D module-sys/Service/Timer.hpp => module-sys/Service/Timer.hpp +0 -88
@@ 1,88 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 "FreeRTOS.h"
#include "portmacro.h"                             // for TickType_t
#include <module-os/RTOSWrapper/include/timer.hpp> // for Timer
#include <functional>                              // for function
#include <string>                                  // for string
#include <atomic>
namespace sys
{
    class Service;
} // namespace sys

namespace sys
{
    using ms = unsigned int;

    /// Base timer for all coarse timers in system
    class Timer : private cpp_freertos::Timer
    {
      public:
        static const ms timeout_infinite;

        enum class Type
        {
            Periodic,
            SingleShot
        };

        /// Create named timer and register it in parent
        /// @param name this will be name of timer + postfix
        /// @param parent service on which behalf timer events will be sent and received
        /// @param interval time for next timer event in
        Timer(const std::string &name, Service *parent, ms interval, Type type = Type::Periodic);

        /// Create timer with default name `_<id_number>` and register it in parent
        /// @param parent service on which behalf timer events will be sent and received
        /// @param interval time for next timer event in
        Timer(Service *parent, ms interval, Type type = Type::Periodic);

        Timer()              = delete;
        Timer(const Timer &) = delete;
        Timer operator=(const Timer &) = delete;

        /// just to stop timer
        ~Timer() override;

        /// This is final by design - to avoid missuse we send Timer notification to Service
        /// and then handle it like any other event. Not by callback as this could cause unrestricted access (no mutex)
        void Run() final;

        /// executed when we receive timeout notification (from overriden Run()) on bus
        void onTimeout();

        /// @defgroup API
        /// {
        void start();
        void reload(ms from_time = 0);
        void stop();
        void setInterval(ms new_interval);
        bool isCurrentlyActive() const noexcept;
        /// }

      protected:
        Service *parent = nullptr;

      private:
        Type type;
        ms interval;
        std::function<void(Timer &)> callback = nullptr;
        std::atomic_bool isActive             = false;
        const std::string name;

      public:
        void connect(std::function<void(Timer &)> new_callback)
        {
            callback = new_callback;
        }

        [[nodiscard]] constexpr auto getName() const -> const std::string &
        {
            return name;
        }
    };
}; // namespace sys

D module-sys/Service/TimerMessage.cpp => module-sys/Service/TimerMessage.cpp +0 -0
M module-sys/SystemManager/SystemManager.cpp => module-sys/SystemManager/SystemManager.cpp +14 -12
@@ 16,7 16,6 @@
#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <service-appmgr/messages/UserPowerDownRequest.hpp>
#include <Service/Timer.hpp>
#include <service-desktop/service-desktop/Constants.hpp>
#include <service-cellular/CellularServiceAPI.hpp>
#include <service-cellular/CellularMessage.hpp>


@@ 29,6 28,7 @@
#include "messages/PhoneModeRequest.hpp"
#include "messages/TetheringStateRequest.hpp"
#include <time/ScopedTime.hpp>
#include "Timers/TimerFactory.hpp"

const inline size_t systemManagerStack = 4096 * 2;



@@ 167,9 167,9 @@ namespace sys
        // Start System manager
        StartService();

        cpuStatisticsTimer = std::make_unique<sys::Timer>("cpuStatistics", this, constants::timerInitInterval.count());
        cpuStatisticsTimer->connect([&](sys::Timer &) { CpuStatisticsTimerHandler(); });
        cpuStatisticsTimer->start();
        cpuStatisticsTimer = sys::TimerFactory::createPeriodicTimer(
            this, "cpuStatistics", constants::timerInitInterval, [this](sys::Timer &) { CpuStatisticsTimerHandler(); });
        cpuStatisticsTimer.start();
    }

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


@@ 309,14 309,16 @@ namespace sys
        }

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

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


@@ 326,7 328,7 @@ namespace sys
            // All services responded
            if (readyForCloseRegister.empty()) {
                LOG_INFO("All services ready to close.");
                servicesPreShutdownRoutineTimeout->stop();
                servicesPreShutdownRoutineTimeout.stop();
                CloseServices();
            }
        }


@@ 433,11 435,11 @@ namespace sys

            if (msg->getAction() == sys::CpuFrequencyMessage::Action::Increase) {
                powerManager->IncreaseCpuFrequency();
                cpuStatisticsTimer->reload();
                cpuStatisticsTimer.start();
            }
            else if (msg->getAction() == sys::CpuFrequencyMessage::Action::Decrease) {
                powerManager->DecreaseCpuFrequency();
                cpuStatisticsTimer->reload();
                cpuStatisticsTimer.start();
            }

            return sys::MessageNone{};


@@ 599,7 601,7 @@ namespace sys
    {
        if (!cpuStatisticsTimerInit) {
            cpuStatisticsTimerInit = true;
            cpuStatisticsTimer->setInterval(constants::timerPeriodInterval.count());
            cpuStatisticsTimer.restart(constants::timerPeriodInterval);
        }

        cpuStatistics->Update();

M module-sys/SystemManager/SystemManager.hpp => module-sys/SystemManager/SystemManager.hpp +3 -2
@@ 19,6 19,7 @@
#include "Service/Mailbox.hpp"
#include "Service/Service.hpp"
#include "Service/ServiceCreator.hpp"
#include "Timers/TimerHandle.hpp"
#include "PowerManager.hpp"
#include "PhoneModes/Subject.hpp"
#include <common_data/RawKey.hpp>


@@ 183,8 184,8 @@ namespace sys
        bool cpuStatisticsTimerInit{false};

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

A module-sys/Timers/SystemTimer.cpp => module-sys/Timers/SystemTimer.cpp +116 -0
@@ 0,0 1,116 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SystemTimer.hpp"
#include "module-sys/Service/Service.hpp"
#include "TimerMessage.hpp"
#include <log/log.hpp>
#include <projdefs.h>
#include <memory>

#if DEBUG_TIMER == 1
#define log_debug(...) LOG_DEBUG(__VA_ARGS__)
#else
#define log_debug(...)
#endif

namespace sys::timer
{
    SystemTimer::SystemTimer(Service *parent,
                             const std::string &name,
                             std::chrono::milliseconds interval,
                             timer::Type type)
        : cpp_freertos::Timer(name.c_str(), pdMS_TO_TICKS(interval.count()), type == timer::Type::Periodic), name{name},
          interval{interval}, type{type}, parent{parent}
    {
        attachToService();
        log_debug("%s %s timer created", name.c_str(), type == Type::Periodic ? "periodic" : "single-shot");
    }

    void SystemTimer::attachToService()
    {
        assert(parent != nullptr);
        parent->getTimers().attach(this);
    }

    SystemTimer::~SystemTimer() noexcept
    {
        parent->getTimers().detach(this);
    }

    void SystemTimer::Run()
    {
        auto msg = std::make_shared<TimerMessage>(this);
        if (const auto ret = parent->bus.sendUnicast(std::move(msg), parent->GetName()); !ret) {
            LOG_ERROR("Timer %s error: bus error", name.c_str());
        }
    }

    void SystemTimer::start()
    {
        log_debug("Timer %s start", name.c_str());
        stopTimerIfActive();
        startTimer();
    }

    void SystemTimer::restart(std::chrono::milliseconds newInterval)
    {
        log_debug("Timer %s restart", name.c_str());
        stopTimerIfActive();
        setInterval(newInterval);
        startTimer();
    }

    void SystemTimer::stopTimerIfActive()
    {
        if (active) {
            cpp_freertos::Timer::Stop(0);
        }
    }

    void SystemTimer::startTimer()
    {
        active = true;
        cpp_freertos::Timer::Start(0);
    }

    void SystemTimer::stop()
    {
        log_debug("Timer %s stop!", name.c_str());
        // make sure callback is not called even if it is already in the queue
        active = false;
        cpp_freertos::Timer::Stop(0);
    }

    void SystemTimer::setInterval(std::chrono::milliseconds value)
    {
        log_debug("Timer %s set interval to %ld ms!", name.c_str(), static_cast<long int>(value.count()));
        interval = value;
        cpp_freertos::Timer::SetPeriod(pdMS_TO_TICKS(interval.count()), 0);
    }

    void SystemTimer::onTimeout()
    {
        log_debug("Timer %s tick", name.c_str());
        if (!callback) {
            LOG_WARN("Timer %s error: Callback is not valid.", name.c_str());
            return;
        }
        if (!isActive()) {
            LOG_WARN("Timer %s error: Timer is not active.", name.c_str());
            return;
        }
        log_debug("Timer %s runs callback", name.c_str());
        callback(*this);
    }

    bool SystemTimer::isActive() const noexcept
    {
        return active;
    }

    void SystemTimer::connect(timer::TimerCallback &&newCallback) noexcept
    {
        callback = std::move(newCallback);
    }
} // namespace sys::timer

A module-sys/Timers/SystemTimer.hpp => module-sys/Timers/SystemTimer.hpp +61 -0
@@ 0,0 1,61 @@
// 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 "FreeRTOS.h"
#include "portmacro.h"                             // for TickType_t
#include <module-os/RTOSWrapper/include/timer.hpp> // for Timer
#include "Timer.hpp"
#include <functional> // for function
#include <string>     // for string
#include <atomic>

namespace sys
{
    class Service;
} // namespace sys

namespace sys::timer
{
    class SystemTimer : public Timer, private cpp_freertos::Timer
    {
      public:
        /// Create named timer and register it in parent
        /// @param parent service on which behalf timer events will be sent and received
        /// @param name this will be name of timer + postfix
        /// @param interval time for next timer event in
        /// @param type type of timer
        SystemTimer(Service *parent, const std::string &name, std::chrono::milliseconds interval, timer::Type type);
        SystemTimer(const SystemTimer &)     = delete;
        SystemTimer(SystemTimer &&) noexcept = delete;
        SystemTimer &operator=(const SystemTimer &) = delete;
        SystemTimer &operator=(SystemTimer &&) noexcept = delete;
        ~SystemTimer() noexcept override;

        void start() override;
        void restart(std::chrono::milliseconds newInterval) override;
        void stop() override;
        bool isActive() const noexcept override;

        void setInterval(std::chrono::milliseconds value);
        void connect(timer::TimerCallback &&newCallback) noexcept;
        void onTimeout();

      private:
        /// This is final by design - to avoid missuse we send Timer notification to Service
        /// and then handle it like any other event. Not by callback as this could cause unrestricted access (no mutex)
        void Run() final;
        /// executed when we receive timeout notification (from overriden Run()) on bus
        void startTimer();
        void stopTimerIfActive();
        void attachToService();

        std::string name;
        timer::TimerCallback callback;
        std::chrono::milliseconds interval;
        timer::Type type;
        Service *parent         = nullptr;
        std::atomic_bool active = false;
    };
}; // namespace sys::timer

A module-sys/Timers/Timer.hpp => module-sys/Timers/Timer.hpp +32 -0
@@ 0,0 1,32 @@
// 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 <chrono>
#include <functional>

namespace sys
{
    class Timer; // Forward declaration
    namespace timer
    {
        using TimerCallback                   = std::function<void(Timer &)>;
        inline constexpr auto InfiniteTimeout = std::chrono::milliseconds::max();
        enum class Type
        {
            Periodic,
            SingleShot
        };
    } // namespace timer

    class Timer
    {
      public:
        virtual ~Timer() noexcept                                   = default;
        virtual void start()                                        = 0;
        virtual void restart(std::chrono::milliseconds newInterval) = 0;
        virtual void stop()                                         = 0;
        virtual bool isActive() const noexcept                      = 0;
    };
} // namespace sys

A module-sys/Timers/TimerFactory.cpp => module-sys/Timers/TimerFactory.cpp +29 -0
@@ 0,0 1,29 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TimerFactory.hpp"

#include "SystemTimer.hpp"

namespace sys
{
    TimerHandle TimerFactory::createSingleShotTimer(Service *parent,
                                                    const std::string &name,
                                                    std::chrono::milliseconds interval,
                                                    timer::TimerCallback &&callback)
    {
        auto timer = new timer::SystemTimer(parent, name, interval, timer::Type::SingleShot);
        timer->connect(std::move(callback));
        return TimerHandle{timer};
    }

    TimerHandle TimerFactory::createPeriodicTimer(Service *parent,
                                                  const std::string &name,
                                                  std::chrono::milliseconds interval,
                                                  timer::TimerCallback &&callback)
    {
        auto timer = new timer::SystemTimer(parent, name, interval, timer::Type::Periodic);
        timer->connect(std::move(callback));
        return TimerHandle{timer};
    }
} // namespace sys

A module-sys/Timers/TimerFactory.hpp => module-sys/Timers/TimerFactory.hpp +29 -0
@@ 0,0 1,29 @@
// 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 <string>

#include "TimerHandle.hpp"

namespace sys
{
    class Service; // Forward declaration
} // namespace sys

namespace sys
{
    class TimerFactory
    {
      public:
        static TimerHandle createSingleShotTimer(Service *parent,
                                                 const std::string &name,
                                                 std::chrono::milliseconds interval,
                                                 timer::TimerCallback &&callback);
        static TimerHandle createPeriodicTimer(Service *parent,
                                               const std::string &name,
                                               std::chrono::milliseconds interval,
                                               timer::TimerCallback &&callback);
    };
} // namespace sys

A module-sys/Timers/TimerHandle.cpp => module-sys/Timers/TimerHandle.cpp +64 -0
@@ 0,0 1,64 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TimerHandle.hpp"

namespace sys
{
    TimerHandle::TimerHandle(Timer *timer) noexcept : timer{timer}
    {}

    TimerHandle::TimerHandle(TimerHandle &&oth) noexcept
    {
        reset(oth.timer);
        oth.timer = nullptr;
    }

    TimerHandle &TimerHandle::operator=(TimerHandle &&oth) noexcept
    {
        if (this != &oth) {
            reset(oth.timer);
            oth.timer = nullptr;
        }
        return *this;
    }

    bool TimerHandle::isValid() const noexcept
    {
        return timer != nullptr;
    }

    void TimerHandle::reset(Timer *newTimer) noexcept
    {
        delete timer;
        timer = newTimer;
    }

    TimerHandle::~TimerHandle() noexcept
    {
        if (isValid()) {
            timer->stop();
        }
        reset();
    }

    void TimerHandle::start()
    {
        timer->start();
    }

    void TimerHandle::stop()
    {
        timer->stop();
    }

    void TimerHandle::restart(std::chrono::milliseconds newInterval)
    {
        timer->restart(newInterval);
    }

    bool TimerHandle::isActive() const noexcept
    {
        return isValid() ? timer->isActive() : false;
    }
} // namespace sys

A module-sys/Timers/TimerHandle.hpp => module-sys/Timers/TimerHandle.hpp +34 -0
@@ 0,0 1,34 @@
// 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 "Timer.hpp"

namespace sys
{
    class TimerHandle : public Timer
    {
      public:
        TimerHandle() noexcept = default;
        explicit TimerHandle(Timer *timer) noexcept;
        ~TimerHandle() noexcept override;

        TimerHandle(const TimerHandle &) = delete;
        TimerHandle &operator=(const TimerHandle &) = delete;

        TimerHandle(TimerHandle &&oth) noexcept;
        TimerHandle &operator=(TimerHandle &&oth) noexcept;

        bool isValid() const noexcept;
        void reset(Timer *newTimer = nullptr) noexcept;

        void start() override;
        void restart(std::chrono::milliseconds newInterval) override;
        void stop() override;
        bool isActive() const noexcept override;

      private:
        Timer *timer = nullptr;
    };
} // namespace sys

R module-sys/Service/TimerMessage.hpp => module-sys/Timers/TimerMessage.hpp +8 -10
@@ 1,26 1,24 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// 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 "Message.hpp"
#include "module-sys/Service/Message.hpp"

namespace sys
{

    class Timer;
    class Timer; // Forward declaration

    class TimerMessage : public SystemMessage
    {
        Timer *timer = nullptr;
        timer::SystemTimer *timer = nullptr;

      public:
        TimerMessage(Timer *timer) : SystemMessage(SystemMessageType::Timer, ServicePowerMode::Active), timer(timer)
        {
            type = Type::System;
        }
        explicit TimerMessage(timer::SystemTimer *timer)
            : SystemMessage(SystemMessageType::Timer, ServicePowerMode::Active), timer(timer)
        {}

        [[nodiscard]] auto getTimer() const -> Timer *
        [[nodiscard]] auto getTimer() noexcept -> timer::SystemTimer *
        {
            return timer;
        }