~aleteoryx/muditaos

c424b6728020563f3d0cf6dc25fb12f9ada14b4f — Mateusz Piesta 3 years ago b7330da
[BH-1515] Revert bedtime changes

Due to many regressions these changes
introduced, we decided to revert them.

The old PR will be used as a foundation for
another fix attempt(probably including major
refactor of the alarm operations module).
30 files changed, 199 insertions(+), 406 deletions(-)

M module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp
M module-apps/apps-common/CMakeLists.txt
M module-services/service-time/AlarmOperations.cpp
M module-services/service-time/AlarmOperations.hpp
M module-services/service-time/tests/CMakeLists.txt
M module-services/service-time/tests/tests-AlarmOperations.cpp
D module-services/service-time/tests/tests-AlarmOperations.hpp
M products/BellHybrid/alarms/BellAlarmHandler.cpp
M products/BellHybrid/alarms/CMakeLists.txt
M products/BellHybrid/alarms/include/AbstractAlarmAction.hpp
R {module-apps/apps-common/popups/data => products/BellHybrid/alarms/include/popups}/BedtimeReminderPopupRequestParams.hpp
M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp
M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp
M products/BellHybrid/alarms/src/actions/NotifyGUIAction.cpp
M products/BellHybrid/alarms/src/actions/NotifyGUIAction.hpp
M products/BellHybrid/alarms/src/actions/NotifyGUIBedtimeReminderAction.cpp
M products/BellHybrid/alarms/src/actions/NotifyGUIBedtimeReminderAction.hpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp
M products/BellHybrid/apps/common/CMakeLists.txt
M products/BellHybrid/apps/common/include/common/data/BatteryUtils.hpp
M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp
M products/BellHybrid/apps/common/include/common/popups/BedtimeNotificationWindow.hpp
M products/BellHybrid/apps/common/src/popups/BedtimeNotificationWindow.cpp
M products/BellHybrid/services/appmgr/include/appmgr/messages/AlarmMessage.hpp
M products/BellHybrid/services/time/AlarmOperations.cpp
M products/BellHybrid/services/time/include/time/AlarmOperations.hpp
M products/BellHybrid/services/time/tests/CMakeLists.txt
M products/BellHybrid/services/time/tests/test-BellAlarmOperations.cpp
M test/CMakeLists.txt
M module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp => module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp +0 -14
@@ 7,7 7,6 @@
#include "service-db/Settings.hpp"
#include "service-db/agents/settings/SystemSettings.hpp"
#include "popups/data/PopupData.hpp"
#include "popups/data/BedtimeReminderPopupRequestParams.hpp"

namespace app
{


@@ 134,19 133,6 @@ namespace app
                                  std::make_unique<gui::AlarmPopupRequestParams>(popupParams));
                return true;
            });

        popupBlueprint.registerBlueprint(
            ID::BedtimeNotification, [&](gui::popup::ID id, std::unique_ptr<gui::PopupRequestParams> &params) {
                auto popupParams = dynamic_cast<gui::BedtimeReminderPopupRequestParams *>(params.get());
                if (popupParams == nullptr) {
                    return false;
                }

                switchWindowPopup(gui::popup::resolveWindowName(id),
                                  params->getDisposition(),
                                  std::make_unique<gui::BedtimeReminderPopupRequestParams>(popupParams->eventRecord));
                return true;
            });
    }

    std::optional<gui::popup::Blueprint> ApplicationCommon::popupBlueprintFallback(gui::popup::ID id)

M module-apps/apps-common/CMakeLists.txt => module-apps/apps-common/CMakeLists.txt +0 -1
@@ 77,7 77,6 @@ target_sources(apps-common
        widgets/TimeSetFmtSpinner.hpp
        actions/AlarmRingingData.hpp
        actions/AlarmTriggeredAction.hpp
        popups/data/BedtimeReminderPopupRequestParams.hpp

        models/SongContext.hpp
        models/SongsRepository.hpp

M module-services/service-time/AlarmOperations.cpp => module-services/service-time/AlarmOperations.cpp +14 -30
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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 "AlarmOperations.hpp"


@@ 128,13 128,18 @@ namespace alarms

    void AlarmOperationsCommon::turnOffRingingAlarm(const std::uint32_t id, OnTurnOffRingingAlarm callback)
    {
        bool ongoingEventsResult = turnOffAlarmIfFoundInOngoingEvents(id);
        bool bedtimeEventsResult = turnOffAlarmIfFoundInBedtime(id);
        if (not ongoingEventsResult and not bedtimeEventsResult) {
            LOG_ERROR("Trying to turn off nonexisting event ID %d", static_cast<int>(id));
        auto found = findSingleEventById(ongoingSingleEvents, id);
        if (found == ongoingSingleEvents.end()) {
            LOG_ERROR("Trying to turn off nonexisting event");
            callback(false);
            return;
        }
        switchAlarmExecution(*(*found), false);
        ongoingSingleEvents.erase(found);

        processOngoingEvents();

        handleActiveAlarmsCountChange();
        callback(true);
    }



@@ 333,26 338,6 @@ namespace alarms
        }
    }

    bool AlarmOperationsCommon::turnOffAlarmIfFoundInOngoingEvents(std::uint32_t id)
    {
        auto found = findSingleEventById(ongoingSingleEvents, id);
        if (found == ongoingSingleEvents.end()) {
            return false;
        }

        switchAlarmExecution(*(*found), false);
        ongoingSingleEvents.erase(found);
        processOngoingEvents();
        handleActiveAlarmsCountChange();

        return true;
    }

    bool AlarmOperationsCommon::turnOffAlarmIfFoundInBedtime(const std::uint32_t id)
    {
        return false;
    }

    void AlarmOperationsCommon::onAlarmTurnedOff(const std::shared_ptr<AlarmEventRecord> &event,
                                                 alarms::AlarmType alarmType)
    {}


@@ 448,16 433,15 @@ namespace alarms
        callback(std::move(snoozedEvents));
    }

    auto findSingleEventById(EventsContainer<SingleEventRecord> &events, const std::uint32_t id)
        -> EventsContainer<SingleEventRecord>::iterator
    auto findSingleEventById(std::vector<std::unique_ptr<SingleEventRecord>> &events, const std::uint32_t id)
        -> std::vector<std::unique_ptr<SingleEventRecord>>::iterator
    {
        return std::find_if(events.begin(), events.end(), [id](const std::unique_ptr<SingleEventRecord> &event) {
            return id == event->parent->ID;
        });
    }

    auto findSnoozedEventById(EventsContainer<SnoozedAlarmEventRecord> &events, const std::uint32_t id)
        -> EventsContainer<SnoozedAlarmEventRecord>::iterator
    auto findSnoozedEventById(std::vector<std::unique_ptr<SnoozedAlarmEventRecord>> &events, const std::uint32_t id)
        -> std::vector<std::unique_ptr<SnoozedAlarmEventRecord>>::iterator
    {
        return std::find_if(events.begin(), events.end(), [id](const std::unique_ptr<SnoozedAlarmEventRecord> &event) {
            return id == event->parent->ID;

M module-services/service-time/AlarmOperations.hpp => module-services/service-time/AlarmOperations.hpp +8 -13
@@ 15,9 15,6 @@

namespace alarms
{
    template <typename T>
    using EventsContainer = std::vector<std::unique_ptr<T>>;

    class IAlarmOperations
    {
      public:


@@ 117,17 114,14 @@ namespace alarms
        AlarmHandlerFactory alarmHandlerFactory;

        // Events we are waiting for (on one timepoint)
        EventsContainer<SingleEventRecord> nextSingleEvents;
        EventsContainer<SingleEventRecord> ongoingSingleEvents;
        EventsContainer<SnoozedAlarmEventRecord> snoozedSingleEvents;
        std::vector<std::unique_ptr<SingleEventRecord>> nextSingleEvents;
        std::vector<std::unique_ptr<SingleEventRecord>> ongoingSingleEvents;
        std::vector<std::unique_ptr<SnoozedAlarmEventRecord>> snoozedSingleEvents;

        alarms::AlarmType getAlarmEventType(const SingleEventRecord &event);
        virtual void handleAlarmEvent(const std::shared_ptr<AlarmEventRecord> &event,
                                      alarms::AlarmType alarmType,
                                      bool newStateOn);
        virtual bool turnOffAlarmIfFoundInBedtime(std::uint32_t id);
        bool turnOffAlarmIfFoundInOngoingEvents(std::uint32_t id);
        void switchAlarmExecution(const SingleEventRecord &singleAlarmEvent, bool newStateOn);

      private:
        GetCurrentTime getCurrentTimeCallback;


@@ 145,6 139,7 @@ namespace alarms
                                     std::vector<AlarmEventRecord> records,
                                     OnGetAlarmsProcessed handledCallback);
        void checkAndUpdateCache(AlarmEventRecord record);
        void switchAlarmExecution(const SingleEventRecord &singleAlarmEvent, bool newStateOn);
        void processEvents(TimePoint now);
        void processOngoingEvents();
        void processNextEventsQueue(const TimePoint now);


@@ 165,8 160,8 @@ namespace alarms
            IAlarmOperations::GetCurrentTime getCurrentTimeCallback) const override;
    };

    auto findSingleEventById(EventsContainer<SingleEventRecord> &events, const std::uint32_t id)
        -> EventsContainer<SingleEventRecord>::iterator;
    auto findSnoozedEventById(EventsContainer<SnoozedAlarmEventRecord> &events, const std::uint32_t id)
        -> EventsContainer<SnoozedAlarmEventRecord>::iterator;
    auto findSingleEventById(std::vector<std::unique_ptr<SingleEventRecord>> &events, const std::uint32_t id)
        -> std::vector<std::unique_ptr<SingleEventRecord>>::iterator;
    auto findSnoozedEventById(std::vector<std::unique_ptr<SnoozedAlarmEventRecord>> &events, const std::uint32_t id)
        -> std::vector<std::unique_ptr<SnoozedAlarmEventRecord>>::iterator;
} // namespace alarms

M module-services/service-time/tests/CMakeLists.txt => module-services/service-time/tests/CMakeLists.txt +10 -19
@@ 19,25 19,16 @@ add_catch2_executable(
        module-db
)

add_library(service-time-alarm-operations-source OBJECT
    tests-AlarmOperations.cpp)

target_link_libraries(service-time-alarm-operations-source
    PUBLIC
add_gtest_executable(
    NAME 
        service-time-alarm-operations
    SRCS
        tests-AlarmOperations.cpp
    LIBS
        module-sys
        service-time
        gtest_main
        gmock
        log-api)

target_include_directories(service-time-alarm-operations-source
    PUBLIC
        $<TARGET_PROPERTY:service-time,INCLUDE_DIRECTORIES>)

add_executable(googletest-service-time-alarm-operations)
target_link_libraries(googletest-service-time-alarm-operations
    PUBLIC
    service-time-alarm-operations-source
    INCLUDE
        $<TARGET_PROPERTY:service-time,INCLUDE_DIRECTORIES>
    DEFS
        COMMON_ALARM_OPERATIONS_TEST
)

add_gtest_manually_prepared_target(NAME googletest-service-time-alarm-operations)

M module-services/service-time/tests/tests-AlarmOperations.cpp => module-services/service-time/tests/tests-AlarmOperations.cpp +111 -10
@@ 1,22 1,123 @@
// Copyright (c) 2017-2022, 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 "tests-AlarmOperations.hpp"
namespace
#include <AlarmOperations.hpp>
#include <AlarmRepository.hpp>
#include <service-time/AlarmHandler.hpp>

#include <module-db/Interface/AlarmEventRecord.hpp>

#include <gtest/gtest.h>
#include <gmock/gmock.h>

class MockAlarmHandler : public alarms::AlarmHandler
{
    alarms::IAlarmOperations::OnUpdateAlarmProcessed universalBoolCallback = [](bool success) {
        EXPECT_EQ(success, true);
    };
    alarms::IAlarmOperations::GetCurrentTime timeInjector = []() {
        return TimePointFromStringWithShift("2022-11-11 05:00:00");
    };
} // namespace
  public:
    MOCK_METHOD(bool, handle, (const AlarmEventRecord &record), ());
    MOCK_METHOD(bool, handleOff, (const AlarmEventRecord &record), ());
};

class MockAlarmEventsRepository : public alarms::AbstractAlarmEventsRepository
{
  public:
    std::vector<AlarmEventRecord> nextRecords;

    MOCK_METHOD(void,
                getAlarmEvent,
                (const std::uint32_t alarmId, const alarms::OnGetAlarmEventCallback &callback),
                ());
    MOCK_METHOD(void,
                getAlarmEvents,
                (std::uint32_t offset, std::uint32_t limit, const alarms::OnGetAlarmEventsCallback &callback),
                ());
    MOCK_METHOD(void, toggleAll, (const bool toggle, const alarms::OnToggleAll &callback), ());

    auto addAlarmEvent(const AlarmEventRecord &alarmEvent, const alarms::OnAddAlarmEventCallback &callback) -> void
    {
        addSingleEvent(alarmEvent);
        callback({true});
    }

    auto updateAlarmEvent(const AlarmEventRecord &alarmEvent, const alarms::OnAddAlarmEventCallback &callback) -> void
    {
        nextRecords.erase(std::remove_if(nextRecords.begin(),
                                         nextRecords.end(),
                                         [&alarmEvent](const AlarmEventRecord &ae) { return ae.ID == alarmEvent.ID; }),
                          nextRecords.end());
        addSingleEvent(alarmEvent);
        callback({true});
    }
    auto removeAlarmEvent(const std::uint32_t alarmId, const alarms::OnRemoveAlarmEventCallback &callback) -> void
    {
        nextRecords.erase(std::remove_if(nextRecords.begin(),
                                         nextRecords.end(),
                                         [&alarmId](const AlarmEventRecord &ae) { return ae.ID == alarmId; }),
                          nextRecords.end());
        callback({true});
    }

    void getAlarmEventsInRange(std::uint32_t offset,
                               std::uint32_t limit,
                               const alarms::OnGetAlarmEventsInRangeCallback &callback)
    {
        callback({nextRecords, nextRecords.size()});
    }

    void getAlarmEnabledEvents(const alarms::OnGetAlarmEventsCallback &callback)
    {
        std::vector<AlarmEventRecord> result;
        for (const auto &rec : nextRecords) {
            if (rec.enabled) {
                result.push_back(rec);
            }
        }
        callback({result});
    }

    void addSingleEvent(const AlarmEventRecord record)
    {
        nextRecords.push_back(record);
    }
};

/// Time point from string with current test machine time shift
TimePoint TimePointFromStringWithShift(std::string timeString)
{
    const auto timeToCalc = TimePointFromString("2000-01-01 12:00:00");
    const auto fromTimeT  = std::chrono::system_clock::to_time_t(timeToCalc);
    const auto fromLocal  = std::localtime(&fromTimeT);
    fromLocal->tm_hour    = 12;
    fromLocal->tm_min     = 0;
    auto time             = TimePointFloorMinutes(std::chrono::system_clock::from_time_t(std::mktime(fromLocal)));
    auto currentTimeShift = timeToCalc - time;

    return TimePointFromString(timeString.c_str()) - currentTimeShift;
}

alarms::IAlarmOperations::GetCurrentTime timeInjector = []() {
    return TimePointFromStringWithShift("2022-11-11 05:00:00");
};
alarms::IAlarmOperations::OnUpdateAlarmProcessed universalBoolCallback = [](bool success) { EXPECT_EQ(success, true); };

class AlarmOperationsFixture : public ::testing::Test
{
  protected:
    std::unique_ptr<alarms::IAlarmOperations> getMockedAlarmOperations(
        std::unique_ptr<MockAlarmEventsRepository> &alarmRepo);
};

#if defined COMMON_ALARM_OPERATIONS_TEST
std::unique_ptr<alarms::IAlarmOperations> AlarmOperationsFixture::getMockedAlarmOperations(
    std::unique_ptr<MockAlarmEventsRepository> &alarmRepo)
{
    return std::make_unique<alarms::AlarmOperationsCommon>(std::move(alarmRepo), timeInjector);
}
#endif

constexpr auto defRRule   = "";
constexpr auto defMusic   = "";
constexpr auto defEnabled = true;
constexpr auto defSnooze  = 15;

TEST_F(AlarmOperationsFixture, getEnabledEvents)
{

D module-services/service-time/tests/tests-AlarmOperations.hpp => module-services/service-time/tests/tests-AlarmOperations.hpp +0 -110
@@ 1,110 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <service-time/AlarmHandler.hpp>
#include <module-db/Interface/AlarmEventRecord.hpp>
#include <AlarmOperations.hpp>
#include <AlarmRepository.hpp>

class MockAlarmHandler : public alarms::AlarmHandler
{
  public:
    MOCK_METHOD(bool, handle, (const AlarmEventRecord &record), ());
    MOCK_METHOD(bool, handleOff, (const AlarmEventRecord &record), ());
};

class MockAlarmEventsRepository : public alarms::AbstractAlarmEventsRepository
{
  public:
    std::vector<AlarmEventRecord> nextRecords;

    MOCK_METHOD(void,
                getAlarmEvent,
                (const std::uint32_t alarmId, const alarms::OnGetAlarmEventCallback &callback),
                ());
    MOCK_METHOD(void,
                getAlarmEvents,
                (std::uint32_t offset, std::uint32_t limit, const alarms::OnGetAlarmEventsCallback &callback),
                ());
    MOCK_METHOD(void, toggleAll, (const bool toggle, const alarms::OnToggleAll &callback), ());

    auto addAlarmEvent(const AlarmEventRecord &alarmEvent, const alarms::OnAddAlarmEventCallback &callback) -> void
    {
        addSingleEvent(alarmEvent);
        callback({true});
    }

    auto updateAlarmEvent(const AlarmEventRecord &alarmEvent, const alarms::OnAddAlarmEventCallback &callback) -> void
    {
        nextRecords.erase(std::remove_if(nextRecords.begin(),
                                         nextRecords.end(),
                                         [&alarmEvent](const AlarmEventRecord &ae) { return ae.ID == alarmEvent.ID; }),
                          nextRecords.end());
        addSingleEvent(alarmEvent);
        callback({true});
    }
    auto removeAlarmEvent(const std::uint32_t alarmId, const alarms::OnRemoveAlarmEventCallback &callback) -> void
    {
        nextRecords.erase(std::remove_if(nextRecords.begin(),
                                         nextRecords.end(),
                                         [&alarmId](const AlarmEventRecord &ae) { return ae.ID == alarmId; }),
                          nextRecords.end());
        callback({true});
    }

    void getAlarmEventsInRange(std::uint32_t offset,
                               std::uint32_t limit,
                               const alarms::OnGetAlarmEventsInRangeCallback &callback)
    {
        callback({nextRecords, nextRecords.size()});
    }

    void getAlarmEnabledEvents(const alarms::OnGetAlarmEventsCallback &callback)
    {
        std::vector<AlarmEventRecord> result;
        for (const auto &rec : nextRecords) {
            if (rec.enabled) {
                result.push_back(rec);
            }
        }
        callback({result});
    }

    void addSingleEvent(const AlarmEventRecord record)
    {
        nextRecords.push_back(record);
    }
};

namespace
{
    /// Time point from string with current test machine time shift
    TimePoint TimePointFromStringWithShift(std::string timeString)
    {
        const auto timeToCalc = TimePointFromString("2000-01-01 12:00:00");
        const auto fromTimeT  = std::chrono::system_clock::to_time_t(timeToCalc);
        const auto fromLocal  = std::localtime(&fromTimeT);
        fromLocal->tm_hour    = 12;
        fromLocal->tm_min     = 0;
        auto time             = TimePointFloorMinutes(std::chrono::system_clock::from_time_t(std::mktime(fromLocal)));
        auto currentTimeShift = timeToCalc - time;

        return TimePointFromString(timeString.c_str()) - currentTimeShift;
    }

} // namespace

class AlarmOperationsFixture : public ::testing::Test
{
  protected:
    virtual std::unique_ptr<alarms::IAlarmOperations> getMockedAlarmOperations(
        std::unique_ptr<MockAlarmEventsRepository> &alarmRepo);
};

constexpr auto defRRule   = "";
constexpr auto defMusic   = "";
constexpr auto defEnabled = true;
constexpr auto defSnooze  = 15;

M products/BellHybrid/alarms/BellAlarmHandler.cpp => products/BellHybrid/alarms/BellAlarmHandler.cpp +1 -1
@@ 17,7 17,7 @@ namespace alarms
        auto result{true};
        if (record.enabled) {
            for (const auto &action : actions) {
                result &= action->execute(record.ID);
                result &= action->execute();
            }
        }
        return result;

M products/BellHybrid/alarms/CMakeLists.txt => products/BellHybrid/alarms/CMakeLists.txt +1 -0
@@ 20,6 20,7 @@ target_sources(alarms
        include/AlarmSoundPaths.hpp
        include/popups/AlarmActivatedPopupRequestParams.hpp
        include/popups/AlarmDeactivatedPopupRequestParams.hpp
        include/popups/BedtimeReminderPopupRequestParams.hpp
)

target_include_directories(alarms

M products/BellHybrid/alarms/include/AbstractAlarmAction.hpp => products/BellHybrid/alarms/include/AbstractAlarmAction.hpp +4 -7
@@ 1,18 1,15 @@
// Copyright (c) 2017-2022, 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 <Tables/Record.hpp>
#include <cstdint>

namespace alarms
{
    class AbstractAlarmAction
    {
      public:
        virtual ~AbstractAlarmAction()      = default;
        virtual bool execute(Record record) = 0;
        virtual bool turnOff()              = 0;
        virtual ~AbstractAlarmAction() = default;
        virtual bool execute()         = 0;
        virtual bool turnOff()         = 0;
    };
} // namespace alarms

R module-apps/apps-common/popups/data/BedtimeReminderPopupRequestParams.hpp => products/BellHybrid/alarms/include/popups/BedtimeReminderPopupRequestParams.hpp +2 -6
@@ 1,20 1,16 @@
// Copyright (c) 2017-2022, 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 <apps-common/popups/data/PopupRequestParams.hpp>
#include <Tables/Record.hpp>

namespace gui
{
    class BedtimeReminderPopupRequestParams : public PopupRequestParams
    {
      public:
        BedtimeReminderPopupRequestParams(Record record)
            : PopupRequestParams{gui::popup::ID::BedtimeNotification}, eventRecord{record}
        BedtimeReminderPopupRequestParams() : PopupRequestParams{gui::popup::ID::BedtimeNotification}
        {}

        Record eventRecord;
    };
} // namespace gui

M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp => products/BellHybrid/alarms/src/actions/FrontlightAction.cpp +6 -6
@@ 18,7 18,7 @@ namespace alarms
        {
          public:
            explicit ManualFrontlightAction(sys::Service &service);
            bool execute(Record record) override;
            bool execute() override;
            bool turnOff() override;

          private:


@@ 31,7 31,7 @@ namespace alarms
        {
          public:
            explicit LinearProgressFrontlightAction(sys::Service &service);
            bool execute(Record record) override;
            bool execute() override;
            bool turnOff() override;

          private:


@@ 60,7 60,7 @@ namespace alarms
                                                                    service::ServiceProxy{service.weak_from_this()}}
    {}

    bool FrontlightAction::execute([[maybe_unused]] Record record)
    bool FrontlightAction::execute()
    {
        std::string settingString;



@@ 84,7 84,7 @@ namespace alarms
        case SettingsDependency::None:
            break;
        }
        return pimpl->execute(record);
        return pimpl->execute();
    }

    bool FrontlightAction::turnOff()


@@ 109,7 109,7 @@ namespace alarms
    ManualFrontlightAction::ManualFrontlightAction(sys::Service &service) : service{service}
    {}

    bool ManualFrontlightAction::execute([[maybe_unused]] Record record)
    bool ManualFrontlightAction::execute()
    {
        auto params = prepareParameters();
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(


@@ 136,7 136,7 @@ namespace alarms
        settings.init(service::ServiceProxy{service.weak_from_this()});
    }

    bool LinearProgressFrontlightAction::execute([[maybe_unused]] Record record)
    bool LinearProgressFrontlightAction::execute()
    {
        const auto params = prepareParameters();
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightSetAutoProgressiveModeParams>(params),

M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp => products/BellHybrid/alarms/src/actions/FrontlightAction.hpp +1 -1
@@ 29,7 29,7 @@ namespace alarms
        FrontlightAction(sys::Service &service,
                         Mode mode,
                         SettingsDependency settingsDependency = SettingsDependency::None);
        bool execute(Record record) override;
        bool execute() override;
        bool turnOff() override;

      private:

M products/BellHybrid/alarms/src/actions/NotifyGUIAction.cpp => products/BellHybrid/alarms/src/actions/NotifyGUIAction.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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 "NotifyGUIAction.hpp"


@@ 10,7 10,7 @@ namespace alarms
{
    NotifyGUIAction::NotifyGUIAction(sys::Service &service) : service{service}
    {}
    bool NotifyGUIAction::execute([[maybe_unused]] Record record)
    bool NotifyGUIAction::execute()
    {
        return service.bus.sendUnicast(std::make_shared<app::actions::AlarmTriggeredAction>(), service::name::appmgr);
    }

M products/BellHybrid/alarms/src/actions/NotifyGUIAction.hpp => products/BellHybrid/alarms/src/actions/NotifyGUIAction.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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


@@ 13,7 13,7 @@ namespace alarms
    {
      public:
        explicit NotifyGUIAction(sys::Service &service);
        bool execute(Record record) override;
        bool execute() override;
        bool turnOff() override;

      private:

M products/BellHybrid/alarms/src/actions/NotifyGUIBedtimeReminderAction.cpp => products/BellHybrid/alarms/src/actions/NotifyGUIBedtimeReminderAction.cpp +3 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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 "NotifyGUIBedtimeReminderAction.hpp"


@@ 10,12 10,10 @@ namespace alarms
{
    NotifyGUIBedtimeReminderAction::NotifyGUIBedtimeReminderAction(sys::Service &service) : service{service}
    {}

    bool NotifyGUIBedtimeReminderAction::execute(Record record)
    bool NotifyGUIBedtimeReminderAction::execute()
    {
        return service.bus.sendUnicast(std::make_shared<BedtimeNotification>(record), service::name::appmgr);
        return service.bus.sendUnicast(std::make_shared<BedtimeNotification>(), service::name::appmgr);
    }

    bool NotifyGUIBedtimeReminderAction::turnOff()
    {
        return true;

M products/BellHybrid/alarms/src/actions/NotifyGUIBedtimeReminderAction.hpp => products/BellHybrid/alarms/src/actions/NotifyGUIBedtimeReminderAction.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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


@@ 13,7 13,7 @@ namespace alarms
    {
      public:
        explicit NotifyGUIBedtimeReminderAction(sys::Service &service);
        bool execute(Record record) override;
        bool execute() override;
        bool turnOff() override;

      private:

M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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 "AlarmSoundPaths.hpp"


@@ 35,7 35,7 @@ namespace alarms
        const auto msg       = std::make_shared<service::AudioStopRequest>(stopPlaybackVec);
        return service.bus.sendUnicast(msg, service::audioServiceName);
    }
    bool PlayAudioAction::execute([[maybe_unused]] Record record)
    bool PlayAudioAction::execute()
    {
        const auto tone = settings.getValue(toneSetting, settings::SettingsScope::Global);
        std::optional<std::chrono::minutes> duration{};

M products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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


@@ 19,7 19,7 @@ namespace alarms
    {
      public:
        bool turnOff() override;
        bool execute(Record record) override;
        bool execute() override;
        explicit PlayAudioAction(sys::Service &service,
                                 const std::filesystem::path &tonesDirPath,
                                 std::string_view toneSetting,

M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +0 -1
@@ 128,7 128,6 @@ target_link_libraries(application-bell-common
        module-gui
        bell::db
        Microsoft.GSL::GSL
        bell::alarms
        )

if (${ENABLE_TESTS})

M products/BellHybrid/apps/common/include/common/data/BatteryUtils.hpp => products/BellHybrid/apps/common/include/common/data/BatteryUtils.hpp +0 -1
@@ 7,7 7,6 @@
#include <algorithm>
#include <optional>
#include <string>
#include <array>

#include <Units.hpp>


M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp => products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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

M products/BellHybrid/apps/common/include/common/popups/BedtimeNotificationWindow.hpp => products/BellHybrid/apps/common/include/common/popups/BedtimeNotificationWindow.hpp +1 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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


@@ 23,14 23,11 @@ namespace gui

        app::ApplicationCommon *app;
        Icon *icon = nullptr;
        Record currentEventRecord;
        bool onInput(const InputEvent &inputEvent) override;
        void returnToPreviousWindow();
        void buildInterface() override;

      public:
        bool handleSwitchData(gui::SwitchData *data) override;

        explicit BedtimeNotificationWindow(app::ApplicationCommon *app);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };

M products/BellHybrid/apps/common/src/popups/BedtimeNotificationWindow.cpp => products/BellHybrid/apps/common/src/popups/BedtimeNotificationWindow.cpp +1 -23
@@ 1,17 1,15 @@
// Copyright (c) 2017-2022, 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 <audio/AudioMessage.hpp>
#include <apps-common/popups/Popups.hpp>
#include <apps-common/popups/data/PopupRequestParams.hpp>
#include <popups/data/BedtimeReminderPopupRequestParams.hpp>
#include <common/popups/BedtimeNotificationWindow.hpp>
#include <gui/input/InputEvent.hpp>
#include <gui/widgets/Icon.hpp>
#include <i18n/i18n.hpp>
#include <purefs/filesystem_paths.hpp>
#include <service-appmgr/Controller.hpp>
#include <service-time/AlarmServiceAPI.hpp>

namespace gui
{


@@ 44,25 42,6 @@ namespace gui
        icon->image->setMargins(Margins(0, icon::image_top_margin, 0, icon::image_bottom_margin));
        icon->text->setFont(style::window::font::verybiglight);
    }

    bool BedtimeNotificationWindow::handleSwitchData(SwitchData *data)
    {
        if (data == nullptr) {
            LOG_ERROR("Received null pointer");
            return false;
        }

        auto *eventData = dynamic_cast<gui::BedtimeReminderPopupRequestParams *>(data);
        if (eventData == nullptr) {
            LOG_ERROR("eventData is null pointer");
            return false;
        }

        currentEventRecord = eventData->eventRecord;

        return true;
    }

    void BedtimeNotificationWindow::onBeforeShow(ShowMode mode, [[maybe_unused]] SwitchData *data)
    {
        WindowWithTimer::onBeforeShow(mode, data);


@@ 76,7 55,6 @@ namespace gui

    void BedtimeNotificationWindow::returnToPreviousWindow()
    {
        alarms::AlarmServiceAPI::requestTurnOffRingingAlarm(app, currentEventRecord.ID);
        detachTimerIfExists();
        app::manager::Controller::sendAction(
            application,

M products/BellHybrid/services/appmgr/include/appmgr/messages/AlarmMessage.hpp => products/BellHybrid/services/appmgr/include/appmgr/messages/AlarmMessage.hpp +4 -8
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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,7 6,7 @@
#include <Service/Message.hpp>
#include <popups/AlarmActivatedPopupRequestParams.hpp>
#include <popups/AlarmDeactivatedPopupRequestParams.hpp>
#include <popups/data/BedtimeReminderPopupRequestParams.hpp>
#include <popups/BedtimeReminderPopupRequestParams.hpp>
#include <service-appmgr/Actions.hpp>
#include <service-appmgr/messages/ActionRequest.hpp>



@@ 39,16 39,12 @@ class AlarmDeactivated : public sys::DataMessage, public app::manager::actions::
class BedtimeNotification : public sys::DataMessage, public app::manager::actions::ConvertibleToAction
{
  public:
    BedtimeNotification(Record record) : sys::DataMessage{MessageType::MessageTypeUninitialized}, eventRecord{record}
    BedtimeNotification() : sys::DataMessage{MessageType::MessageTypeUninitialized}
    {}

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

    Record eventRecord;
};

M products/BellHybrid/services/time/AlarmOperations.cpp => products/BellHybrid/services/time/AlarmOperations.cpp +2 -52
@@ 152,18 152,6 @@ namespace alarms
          bedtime(std::move(bedtimeSettingsProvider))
    {}

    bool AlarmOperations::turnOffAlarmIfFoundInBedtime(const std::uint32_t id)
    {
        if (not bedtime.isEventInContainer(id)) {
            return false;
        }

        switchAlarmExecution(*(*bedtime.findEvent(id)), false);
        bedtime.removeAllEvents();

        return true;
    }

    void AlarmOperations::minuteUpdated(TimePoint now)
    {
        /**


@@ 213,10 201,8 @@ namespace alarms
    void AlarmOperations::processBedtime(TimePoint now)
    {
        if (bedtime.decide(now)) {

            auto bedtimeEvent = bedtime.createEvent();
            bedtime.pushEvent(bedtimeEvent);

            auto bedtimeEvent           = std::make_shared<AlarmEventRecord>();
            bedtimeEvent.get()->enabled = true;
            handleAlarmEvent(bedtimeEvent, alarms::AlarmType::BedtimeReminder, true);
        }
    }


@@ 296,9 282,7 @@ namespace alarms

        handleAlarmEvent(event, alarms::AlarmType::PreWakeUpChime, false);
        handleAlarmEvent(event, alarms::AlarmType::PreWakeUpFrontlight, false);
        handleAlarmEvent(event, alarms::AlarmType::BedtimeReminder, false);
    }

    bool AlarmOperations::isBedtimeAllowed() const
    {
        return ongoingSingleEvents.empty() && snoozedSingleEvents.empty() && not preWakeUp.isActive();


@@ 352,40 336,6 @@ namespace alarms
        return activated && isTimeForBed(now, time);
    }

    auto Bedtime::createEvent() -> std::shared_ptr<AlarmEventRecord>
    {
        auto bedtimeEvent     = std::make_shared<AlarmEventRecord>();
        bedtimeEvent->enabled = true;
        bedtimeEvent->ID      = nextFreeId;
        nextFreeId++;

        return bedtimeEvent;
    }

    void Bedtime::pushEvent(const std::shared_ptr<AlarmEventRecord> &bedtimeEvent)
    {
        auto bedtimeSingleEvent    = std::make_unique<SingleEventRecord>();
        bedtimeSingleEvent->parent = bedtimeEvent;

        bedtimeSingleEvents.push_back(std::move(bedtimeSingleEvent));
    }

    bool Bedtime::isEventInContainer(std::uint32_t id)
    {
        return findEvent(id) == bedtimeSingleEvents.end() ? false : true;
    }

    EventsContainer<SingleEventRecord>::iterator Bedtime::findEvent(uint32_t id)
    {
        return findSingleEventById(bedtimeSingleEvents, id);
    }

    void Bedtime::removeAllEvents()
    {
        bedtimeSingleEvents.clear();
        nextFreeId = resonableIdOffset;
    }

    auto Bedtime::isTimeForBed(const TimePoint &now, const time_t &bedtime) -> bool
    {
        auto time_tNow    = TimePointToTimeT(now);

M products/BellHybrid/services/time/include/time/AlarmOperations.hpp => products/BellHybrid/services/time/include/time/AlarmOperations.hpp +0 -10
@@ 80,18 80,10 @@ namespace alarms
      public:
        explicit Bedtime(std::unique_ptr<AbstractBedtimeSettingsProvider> &&settingsProvider);
        auto decide(TimePoint now) -> bool;
        auto createEvent() -> std::shared_ptr<AlarmEventRecord>;
        void pushEvent(const std::shared_ptr<AlarmEventRecord> &bedtimeEvent);
        bool isEventInContainer(std::uint32_t id);
        EventsContainer<SingleEventRecord>::iterator findEvent(std::uint32_t id);
        void removeAllEvents();

      private:
        auto isTimeForBed(const TimePoint &now, const time_t &bedtime) -> bool;
        static constexpr auto resonableIdOffset = 1000;
        uint32_t nextFreeId{resonableIdOffset};

        EventsContainer<SingleEventRecord> bedtimeSingleEvents;
        const std::unique_ptr<AbstractBedtimeSettingsProvider> settingsProvider;
    };



@@ 104,8 96,6 @@ namespace alarms
                        std::unique_ptr<SnoozeChimeSettingsProvider> &&snoozeChimeSettingsProvider,
                        std::unique_ptr<AbstractBedtimeSettingsProvider> &&BedtimeModel);

        bool turnOffAlarmIfFoundInBedtime(const std::uint32_t id) override;

      private:
        void minuteUpdated(TimePoint now) override;
        void stopAllSnoozedAlarms() override;

M products/BellHybrid/services/time/tests/CMakeLists.txt => products/BellHybrid/services/time/tests/CMakeLists.txt +0 -1
@@ 4,7 4,6 @@ add_gtest_executable(
    SRCS
        test-BellAlarmOperations.cpp
    LIBS
        service-time-alarm-operations-source
        module-sys
        bell::time
    INCLUDE

M products/BellHybrid/services/time/tests/test-BellAlarmOperations.cpp => products/BellHybrid/services/time/tests/test-BellAlarmOperations.cpp +18 -23
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, 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 <AlarmOperations.hpp>


@@ 8,16 8,15 @@
#include <products/BellHybrid/services/time/include/time/AlarmOperations.hpp>

#include <gtest/gtest.h>
#include "tests/tests-AlarmOperations.hpp"

// Included a .cpp file with AlarmOperations tests for the common part (the base class' implementation).
// It needs to be built into this test in order to test the possible regression introduced by
// the Bell-specific AlarmOperations class.
// Generally, this should not be solved this way in other cases.
#include <service-time/tests/tests-AlarmOperations.cpp>

namespace
{
    alarms::IAlarmOperations::OnUpdateAlarmProcessed universalBoolCallback = [](bool success) {
        EXPECT_EQ(success, true);
    };
    alarms::IAlarmOperations::GetCurrentTime timeInjector = []() {
        return TimePointFromStringWithShift("2022-11-11 05:00:00");
    };

    class MockedPreWakeUpSettingsProvider : public alarms::PreWakeUpSettingsProvider
    {
      public:


@@ 96,22 95,18 @@ namespace
                                                         std::move(snoozeChimeSettingsProvider),
                                                         std::move(bedtimeSettingsProvider));
    }

    class BellSpecificAlarmOperationsFixture : public AlarmOperationsFixture
    {
      protected:
        std::unique_ptr<alarms::IAlarmOperations> getMockedAlarmOperations(
            std::unique_ptr<MockAlarmEventsRepository> &alarmRepo) override
        {
            return ::getMockedAlarmOperations(alarmRepo,
                                              std::make_unique<MockedPreWakeUpSettingsProvider>(),
                                              std::make_unique<MockedSnoozeChimeSettingsProvider>(),
                                              std::make_unique<MockedBedtimeModel>());
        }
    };

} // namespace

// This function replaces the `getMockedAlarmOperations` function from `service-time/tests/tests-AlarmOperations.cpp`
std::unique_ptr<alarms::IAlarmOperations> AlarmOperationsFixture::getMockedAlarmOperations(
    std::unique_ptr<MockAlarmEventsRepository> &alarmRepo)
{
    return ::getMockedAlarmOperations(alarmRepo,
                                      std::make_unique<MockedPreWakeUpSettingsProvider>(),
                                      std::make_unique<MockedSnoozeChimeSettingsProvider>(),
                                      std::make_unique<MockedBedtimeModel>());
}

TEST(PreWakeUp, TooEarlyForPreWakeUp)
{
    alarms::PreWakeUp preWakeUp(std::make_unique<MockedPreWakeUpSettingsProvider>());

M test/CMakeLists.txt => test/CMakeLists.txt +1 -49
@@ 94,7 94,7 @@ function(add_gtest_executable)
    set(_TESTNAME "googletest-${_TEST_ARGS_NAME}")

    if(NOT _TEST_ARGS_SRCS)
        message(FATAL_ERROR "You must provide test sources for ${_TESTNAME}")
	message(FATAL_ERROR "You must provide test sources for ${_TESTNAME}")
    endif(NOT _TEST_ARGS_SRCS)

    get_directory_property(_TEST_ENTITY TEST_ENTITY)


@@ 244,52 244,4 @@ function(add_test_entity)
    add_dependencies(check-${_ARGS_NAME} unittests-${_ARGS_NAME})
endfunction()

function(add_gtest_manually_prepared_target)
    cmake_parse_arguments(
        _TEST_ARGS
        ""
        "NAME"
        ""
        ${ARGN}
    )

    if(NOT _TEST_ARGS_NAME)
        message(FATAL_ERROR "You must provide a test name")
    endif(NOT _TEST_ARGS_NAME)

    target_compile_options(${_TEST_ARGS_NAME} PUBLIC "-fsanitize=address")
    target_link_options(${_TEST_ARGS_NAME} PUBLIC "-fsanitize=address")

    # disable logs in unit tests
    if (NOT ${ENABLE_TEST_LOGS})
        target_sources(${_TEST_ARGS_NAME} PRIVATE ${ROOT_TEST_DIR}/mock-logs.cpp)
        target_sources(${_TEST_ARGS_NAME} PRIVATE ${ROOT_TEST_DIR}/mock-freertos-tls.cpp)
    endif (NOT ${ENABLE_TEST_LOGS})

    set(_TEST_LABELS "")
    if(_TEST_ARGS_USE_FS)
        enable_test_filesystem()
    endif()

    target_compile_options(${_TEST_ARGS_NAME} PUBLIC "-pthread")
    target_link_options(${_TEST_ARGS_NAME} PUBLIC "-pthread")

    add_dependencies(unittests ${_TEST_ARGS_NAME})
    add_dependencies(check ${_TEST_ARGS_NAME})

    get_directory_property(_TEST_ENTITY TEST_ENTITY)
    if(_TEST_ENTITY)
        add_dependencies(unittests-${_TEST_ENTITY} ${_TEST_ARGS_NAME})
        list(APPEND _TEST_LABELS ${_TEST_ENTITY})
    endif()

    gtest_add_tests(
        TARGET ${_TEST_ARGS_NAME}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        TEST_LIST _TEST_LIST
    )

    set_tests_properties(${_TEST_LIST} PROPERTIES LABELS ${_TEST_LABELS})
endfunction()

set(_CATCH_DISCOVER_TESTS_SCRIPT ${_CATCH_DISCOVER_TESTS_SCRIPT} PARENT_SCOPE)