~aleteoryx/muditaos

8c53ac5fc2a658780685aa98983f692bd8f8e153 — mkamonMdt 4 years ago ba86303
[BH-851] PowerNap alarms implementation

The following commit provides an implementation to an PowerNap's alarm,
that provides appropriate abstraction for an alarm mechanics.

As the PowerNap's alarm can be active only on the application, the
implementation does not make use of Bell's AlarmHandlers.
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +12 -2
@@ 5,9 5,11 @@
#include "presenter/PowerNapMainWindowPresenter.hpp"
#include "presenter/PowerNapProgressPresenter.hpp"
#include "presenter/PowerNapSessionEndedPresenter.hpp"
#include "widgets/PowerNapAlarm.hpp"
#include "windows/PowerNapMainWindow.hpp"
#include "windows/PowerNapProgressWindow.hpp"
#include "windows/PowerNapSessionEndedWindow.hpp"
#include <service-audio/AudioMessage.hpp>

namespace app
{


@@ 16,9 18,11 @@ namespace app
                                                     sys::phone_modes::PhoneMode mode,
                                                     sys::bluetooth::BluetoothMode bluetoothMode,
                                                     StartInBackground startInBackground)
        : ApplicationBell(std::move(name), std::move(parent), mode, bluetoothMode, startInBackground)
        : ApplicationBell(std::move(name), std::move(parent), mode, bluetoothMode, startInBackground),
          alarm{std::make_unique<powernap::PowerNapAlarmImpl>(this)}
    {}

    ApplicationBellPowerNap::~ApplicationBellPowerNap() = default;
    sys::ReturnCodes ApplicationBellPowerNap::InitHandler()
    {
        auto ret = Application::InitHandler();


@@ 37,7 41,7 @@ namespace app
            return std::make_unique<gui::PowerNapMainWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(gui::window::name::powernapProgress, [this](Application *app, const std::string &name) {
            auto presenter = std::make_unique<powernap::PowerNapProgressPresenter>(app, settings.get());
            auto presenter = std::make_unique<powernap::PowerNapProgressPresenter>(app, settings.get(), *alarm);
            return std::make_unique<gui::PowerNapProgressWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(gui::window::name::powernapSessionEnded, [](Application *app, const std::string &name) {


@@ 55,6 59,12 @@ namespace app
            response != nullptr && response->retCode == sys::ReturnCodes::Success) {
            return retMsg;
        }

        if ((resp != nullptr) && typeid(*resp) == typeid(AudioStartPlaybackResponse)) {
            auto *msg = static_cast<AudioStartPlaybackResponse *>(resp);
            alarm->registerAudioStream(msg->token);
        }

        return sys::msgHandled();
    }
} // namespace app

M products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt => products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt +2 -0
@@ 19,6 19,7 @@ target_sources(application-bell-powernap
        presenter/PowerNapMainWindowPresenter.cpp
        presenter/PowerNapProgressPresenter.cpp
        presenter/PowerNapSessionEndedPresenter.cpp
        widgets/PowerNapAlarm.cpp
        windows/PowerNapMainWindow.cpp
        windows/PowerNapProgressWindow.cpp
        windows/PowerNapSessionEndedWindow.cpp


@@ 28,6 29,7 @@ target_sources(application-bell-powernap
        presenter/PowerNapMainWindowPresenter.hpp
        presenter/PowerNapProgressPresenter.hpp
        presenter/PowerNapSessionEndedPresenter.hpp
        widgets/PowerNapAlarm.hpp
        windows/PowerNapMainWindow.hpp
        windows/PowerNapProgressWindow.hpp
        windows/PowerNapSessionEndedWindow.hpp

M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp => products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp +8 -1
@@ 12,17 12,24 @@ namespace gui::window::name
}
namespace app
{
    namespace powernap
    {
        class PowerNapAlarmImpl;
    }

    inline constexpr auto applicationBellPowerNapName = "ApplicationBellPowerNap";

    class ApplicationBellPowerNap : public ApplicationBell
    {
        std::unique_ptr<powernap::PowerNapAlarmImpl> alarm;

      public:
        ApplicationBellPowerNap(std::string name                            = applicationBellPowerNapName,
                                std::string parent                          = "",
                                sys::phone_modes::PhoneMode mode            = sys::phone_modes::PhoneMode::Offline,
                                sys::bluetooth::BluetoothMode bluetoothMode = sys::bluetooth::BluetoothMode::Disabled,
                                StartInBackground startInBackground         = {false});

        ~ApplicationBellPowerNap();
        sys::ReturnCodes InitHandler() override;

        void createUserInterface() override;

M products/BellHybrid/apps/application-bell-powernap/models/PowerNapModel.cpp => products/BellHybrid/apps/application-bell-powernap/models/PowerNapModel.cpp +1 -1
@@ 9,7 9,7 @@
namespace
{
    constexpr std::chrono::minutes emptyValue{0};
    constexpr std::chrono::minutes spinnerDefaultValue{20};
    constexpr std::chrono::minutes spinnerDefaultValue{15};
} // namespace

namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp +18 -7
@@ 4,6 4,7 @@
#include "PowerNapProgressPresenter.hpp"
#include "application-bell-powernap/ApplicationBellPowerNap.hpp"
#include "data/PowerNapCommon.hpp"
#include "widgets/PowerNapAlarm.hpp"

#include <apps-common/widgets/ProgressTimerImpl.hpp>
#include <service-db/Settings.hpp>


@@ 21,12 22,14 @@ namespace
} // namespace
namespace app::powernap
{
    PowerNapProgressPresenter::PowerNapProgressPresenter(app::Application *app, settings::Settings *settings)
        : app{app}, settings{settings}, napAlarmTimer{sys::TimerFactory::createSingleShotTimer(
                                            app, powernapAlarmTimerName, powernapAlarmTimeout, [this](sys::Timer &) {
                                                onNapAlarmFinished();
                                            })}
    PowerNapProgressPresenter::PowerNapProgressPresenter(app::Application *app,
                                                         settings::Settings *settings,
                                                         PowerNapAlarm &alarm)
        : app{app}, settings{settings}, alarm{alarm},
          napAlarmTimer{sys::TimerFactory::createSingleShotTimer(
              app, powernapAlarmTimerName, powernapAlarmTimeout, [this](sys::Timer &) { onNapAlarmFinished(); })}
    {}

    void PowerNapProgressPresenter::initTimer(gui::Item *parent)
    {
        timer = std::make_unique<app::ProgressTimerImpl>(app, parent, powernapTimerName, timerTick);


@@ 39,6 42,12 @@ namespace app::powernap
        timer->reset(std::chrono::minutes{utils::getNumericValue<int>(value)});
        timer->start();
    }
    void PowerNapProgressPresenter::endNap()
    {
        timer->stop();
        napAlarmTimer.stop();
        onNapAlarmFinished();
    }
    app::ProgressTimerUIConfigurator &PowerNapProgressPresenter::getUIConfigurator() noexcept
    {
        Expects(timer != nullptr);


@@ 46,11 55,13 @@ namespace app::powernap
    }
    void PowerNapProgressPresenter::onNapFinished()
    {
        alarm.start();
        napAlarmTimer.start();
    }

    void PowerNapProgressPresenter::onNapAlarmFinished()
    {
        getView()->switchWindow();
        alarm.stop();
        getView()->napEnded();
    }

} // namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp +8 -2
@@ 22,6 22,7 @@ namespace settings

namespace app::powernap
{
    class PowerNapAlarm;
    class PowerNapProgressContract
    {
      public:


@@ 29,7 30,7 @@ namespace app::powernap
        {
          public:
            ~View() = default;
            virtual void switchWindow() = 0;
            virtual void napEnded() = 0;
        };

        class Presenter : public BasePresenter<PowerNapProgressContract::View>


@@ 38,24 39,29 @@ namespace app::powernap
            virtual void initTimer(gui::Item *parent)                              = 0;
            virtual app::ProgressTimerUIConfigurator &getUIConfigurator() noexcept = 0;
            virtual void activate()                                                = 0;
            virtual void endNap()                                                  = 0;
        };
    };

    class AlarmController;

    class PowerNapProgressPresenter : public PowerNapProgressContract::Presenter
    {
        app::Application *app        = nullptr;
        settings::Settings *settings = nullptr;
        PowerNapAlarm &alarm;
        std::unique_ptr<app::ProgressTimer> timer;
        sys::TimerHandle napAlarmTimer;

        void initTimer(gui::Item *parent) override;
        app::ProgressTimerUIConfigurator &getUIConfigurator() noexcept override;
        void activate() override;
        void endNap() override;

        void onNapFinished();
        void onNapAlarmFinished();

      public:
        PowerNapProgressPresenter(app::Application *app, settings::Settings *settings);
        PowerNapProgressPresenter(app::Application *app, settings::Settings *settings, PowerNapAlarm &alarm);
    };
} // namespace app::powernap

A products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.cpp => products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.cpp +37 -0
@@ 0,0 1,37 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PowerNapAlarm.hpp"

#include <purefs/filesystem_paths.hpp>
#include <service-audio/AudioServiceAPI.hpp>

namespace
{
    constexpr auto alarmAudioPath = "assets/audio/alarm/alarm_mudita_bell.mp3";
}

namespace app::powernap
{
    PowerNapAlarmImpl::PowerNapAlarmImpl(app::Application *app) : app{app}
    {}

    void PowerNapAlarmImpl::start()
    {
        AudioServiceAPI::PlaybackStart(
            app, audio::PlaybackType::Alarm, purefs::dir::getCurrentOSPath() / alarmAudioPath);
    }

    void PowerNapAlarmImpl::stop()
    {
        if (token.IsValid()) {
            AudioServiceAPI::Stop(app, token);
            token = audio::Token::MakeBadToken();
        }
    }

    void PowerNapAlarmImpl::registerAudioStream(audio::Token _token)
    {
        token = _token;
    }
} // namespace app::powernap

A products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.hpp => products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.hpp +36 -0
@@ 0,0 1,36 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <module-audio/Audio/AudioCommon.hpp>

namespace app
{
    class Application;
}

namespace app::powernap
{
    class PowerNapAlarm
    {
      public:
        virtual ~PowerNapAlarm() = default;

        virtual void start() = 0;
        virtual void stop()  = 0;
    };

    class PowerNapAlarmImpl : public PowerNapAlarm
    {
        app::Application *app{};
        audio::Token token;

        void start() override;
        void stop() override;

      public:
        explicit PowerNapAlarmImpl(app::Application *app);
        void registerAudioStream(audio::Token _token);
    };

} // namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp +3 -2
@@ 54,6 54,7 @@ namespace gui
        : AppWindow(app, gui::window::name::powernapProgress), presenter{std::move(presenter)}
    {
        buildInterface();
        this->presenter->attach(this);
    }

    void PowerNapProgressWindow::onBeforeShow(ShowMode mode, SwitchData *data)


@@ 93,13 94,13 @@ namespace gui
    {
        if (inputEvent.isShortRelease()) {
            if (inputEvent.is(KeyCode::KEY_RF) || inputEvent.is(KeyCode::KEY_ENTER)) {
                switchWindow();
                presenter->endNap();
                return true;
            }
        }
        return AppWindow::onInput(inputEvent);
    }
    void PowerNapProgressWindow::switchWindow()
    void PowerNapProgressWindow::napEnded()
    {
        application->switchWindow(gui::window::name::powernapSessionEnded, std::make_unique<gui::PowerNapSwitchData>());
    }

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp +1 -1
@@ 23,7 23,7 @@ namespace gui
        void buildLayout();
        void configureTimer();

        void switchWindow() override;
        void napEnded() override;

      public:
        PowerNapProgressWindow(app::Application *app,