~aleteoryx/muditaos

299be4daf6da880f495f4dc363e480d6ff0f0e9b — Piotr Tanski 5 years ago 6bbef80
[EGD-4151] Application manager actions introduced. (#905)

* [EGD-4151] Application manifest structure defined.
* [EGD-4156] Applications registry and basic action handler implemented.
72 files changed, 898 insertions(+), 422 deletions(-)

M changelog.md
M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/ApplicationLauncher.hpp
M module-apps/UiCommonActions.cpp
M module-apps/application-antenna/ApplicationAntenna.cpp
M module-apps/application-antenna/ApplicationAntenna.hpp
M module-apps/application-calculator/ApplicationCalculator.cpp
M module-apps/application-calculator/ApplicationCalculator.hpp
M module-apps/application-calendar/ApplicationCalendar.cpp
M module-apps/application-calendar/ApplicationCalendar.hpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-call/ApplicationCall.hpp
M module-apps/application-call/windows/EmergencyCallWindow.cpp
M module-apps/application-calllog/ApplicationCallLog.cpp
M module-apps/application-calllog/ApplicationCallLog.hpp
M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp
M module-apps/application-calllog/windows/CallLogMainWindow.cpp
M module-apps/application-clock/ApplicationClock.cpp
M module-apps/application-clock/ApplicationClock.hpp
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/ApplicationDesktop.hpp
M module-apps/application-desktop/windows/PowerOffWindow.cpp
M module-apps/application-desktop/windows/Update.cpp
M module-apps/application-meditation/ApplicationMeditation.cpp
M module-apps/application-meditation/ApplicationMeditation.hpp
M module-apps/application-messages/ApplicationMessages.cpp
M module-apps/application-messages/ApplicationMessages.hpp
M module-apps/application-messages/windows/MessagesMainWindow.cpp
M module-apps/application-messages/windows/SMSTemplatesWindow.cpp
M module-apps/application-music-player/ApplicationMusicPlayer.cpp
M module-apps/application-music-player/ApplicationMusicPlayer.hpp
M module-apps/application-notes/ApplicationNotes.cpp
M module-apps/application-notes/ApplicationNotes.hpp
M module-apps/application-notes/windows/NotesEditWindow.cpp
M module-apps/application-notes/windows/NotesMainWindow.cpp
M module-apps/application-phonebook/ApplicationPhonebook.cpp
M module-apps/application-phonebook/ApplicationPhonebook.hpp
M module-apps/application-phonebook/windows/PhonebookMainWindow.cpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings-new/ApplicationSettings.hpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/ApplicationSettings.hpp
M module-apps/application-settings/windows/BtScanWindow.cpp
M module-apps/application-settings/windows/BtWindow.cpp
M module-apps/application-settings/windows/DateTimeWindow.cpp
M module-apps/application-settings/windows/TestMessageWindow.cpp
M module-apps/application-settings/windows/UITestWindow.cpp
M module-apps/application-settings/windows/USSDWindow.cpp
M module-apps/application-special-input/ApplicationSpecialInput.cpp
M module-apps/application-special-input/ApplicationSpecialInput.hpp
M module-apps/messages/AppMessage.hpp
M module-apps/windows/Dialog.cpp
M module-apps/windows/OptionWindow.cpp
M module-services/service-antenna/ServiceAntenna.cpp
A module-services/service-appmgr/Actions.hpp
A module-services/service-appmgr/ApplicationManifest.cpp
A module-services/service-appmgr/ApplicationManifest.hpp
M module-services/service-appmgr/CMakeLists.txt
M module-services/service-appmgr/Controller.cpp
M module-services/service-appmgr/Controller.hpp
R module-services/service-appmgr/messages/{APMMessage => Message}.hpp
A module-services/service-appmgr/model/ApplicationHandle.cpp
A module-services/service-appmgr/model/ApplicationHandle.hpp
R module-services/service-appmgr/{ => model}/ApplicationManager.cpp
R module-services/service-appmgr/{ => model}/ApplicationManager.hpp
A module-services/service-appmgr/model/ApplicationsRegistry.cpp
A module-services/service-appmgr/model/ApplicationsRegistry.hpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/ServiceCellular.hpp
M source/MessageType.hpp
M source/main.cpp
M changelog.md => changelog.md +1 -0
@@ 15,6 15,7 @@

* `[cellular]` Handled properly SIM READY and SIM PIN URC messages with Action mockup
* `[calendar]` Rework to use database model instead of internal model in day events list.
* `[appmgr]` Application manager actions introduced.

### Fixed


M module-apps/Application.cpp => module-apps/Application.cpp +45 -9
@@ 62,16 62,16 @@ namespace app
        }
    }

    Application::Application(
        std::string name, std::string parent, bool startBackground, uint32_t stackDepth, sys::ServicePriority priority)
    Application::Application(std::string name,
                             std::string parent,
                             StartInBackground startInBackground,
                             uint32_t stackDepth,
                             sys::ServicePriority priority)
        : Service(name, parent, stackDepth, priority), default_window(gui::name::window::main_window),
          windowsStack(this), windowsFactory(), startBackground{startBackground}
          windowsStack(this), startInBackground{startInBackground}
    {
        keyTranslator = std::make_unique<gui::KeyInputSimpleTranslation>();
        busChannels.push_back(sys::BusChannels::ServiceCellularNotifications);
        if (startBackground) {
            setState(State::ACTIVE_BACKGROUND);
        }

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


@@ 223,6 223,9 @@ namespace app
        else if (msgl->messageType == MessageType::EVMMinuteUpdated) {
            return handleMinuteUpdated(msgl);
        }
        else if (msgl->messageType == MessageType::AppAction) {
            return handleAction(msgl);
        }
        else if (msgl->messageType == MessageType::AppSwitch) {
            return handleApplicationSwitch(msgl);
        }


@@ 333,6 336,21 @@ namespace app
        return msgHandled();
    }

    sys::Message_t Application::handleAction(sys::DataMessage *msgl)
    {
        auto *msg         = static_cast<AppActionRequest *>(msgl);
        const auto action = msg->getAction();
        try {
            const auto &actionHandler = receivers.at(action);
            auto &data                = msg->getData();
            actionHandler(std::move(data));
        }
        catch (const std::out_of_range &) {
            LOG_ERROR("Application %s is not able to handle action #%d", GetName().c_str(), action);
        }
        return msgHandled();
    }

    sys::Message_t Application::handleApplicationSwitch(sys::DataMessage *msgl)
    {
        auto *msg             = static_cast<AppSwitchMessage *>(msgl);


@@ 472,12 490,16 @@ namespace app
        setState(State::INITIALIZING);
        settings = DBServiceAPI::SettingsGet(this);

        const bool initialised = settings.dbID == 1;
        app::manager::Controller::registerApplication(this, initialised, startBackground);
        if (!initialised) {
        const auto status = (settings.dbID == 1) ? StartupStatus::Success : StartupStatus::Failure;
        app::manager::Controller::applicationInitialised(this, status, startInBackground);
        if (status == StartupStatus::Failure) {
            setState(State::DEACTIVATED);
            return sys::ReturnCodes::Failure;
        }

        if (startInBackground) {
            setState(State::ACTIVE_BACKGROUND);
        }
        return sys::ReturnCodes::Success;
    }



@@ 507,6 529,15 @@ namespace app
        return AudioServiceAPI::KeyPressed(this, step);
    }

    void Application::requestAction(sys::Service *sender,
                                    const ApplicationName &applicationName,
                                    manager::actions::ActionId actionId,
                                    manager::actions::ActionParamsPtr &&data)
    {
        auto msg = std::make_shared<AppActionRequest>(actionId, std::move(data));
        sys::Bus::SendUnicast(msg, applicationName, sender);
    }

    void Application::messageSwitchApplication(sys::Service *sender,
                                               std::string application,
                                               std::string window,


@@ 616,4 647,9 @@ namespace app
        timer->sysapi.connect(item);
        item->attachTimer(std::move(timer));
    }

    void Application::addActionReceiver(manager::actions::ActionId actionId, OnActionReceived &&callback)
    {
        receivers.insert_or_assign(actionId, std::move(callback));
    }
} /* namespace app */

M module-apps/Application.hpp => module-apps/Application.hpp +75 -6
@@ 17,6 17,7 @@
#include "gui/Common.hpp"                               // for ShowMode
#include "projdefs.h"                                   // for pdMS_TO_TICKS
#include "service-evtmgr/messages/EVMessages.hpp"       // for TorchStateMe...
#include "module-services/service-appmgr/ApplicationManifest.hpp"
#include <list>                                         // for list
#include <map>                                          // for allocator, map
#include <memory>                                       // for make_shared


@@ 57,7 58,6 @@ namespace sys

namespace app
{

    class Application;
    class GuiTimer;



@@ 71,6 71,49 @@ namespace app
        return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
    }

    using ApplicationName = std::string;

    enum class StartupStatus
    {
        Success,
        Failure
    };

    struct StartInBackground
    {
        StartInBackground(bool _value) : value{_value}
        {}

        explicit operator bool() const noexcept
        {
            return value;
        }

        bool value;
    };

    /// Type traits pattern used to enforce user-defined types to implement "GetManifest" function.
    template <class T> struct ManifestTraits;

    template <class, class = void> struct HasManifest : std::false_type
    {};

    /// Checks whether T implements "GetManifest" static method.
    /// Provides the member constant "value" that is equal to true if T implements "GetManifest" static method.
    /// Otherwise, "value" is equal to false.
    template <class T>
    struct HasManifest<T, std::void_t<decltype(&ManifestTraits<T>::GetManifest)>>
        : std::is_same<app::manager::ApplicationManifest, decltype(ManifestTraits<T>::GetManifest())>
    {};

    /// Retrieves the manifest of T, if T implements ManifestTraits.
    /// Otherwise, reports an error during compile time.
    template <class T, std::enable_if_t<HasManifest<T>::value, int> = 0>
    auto ManifestOf() -> manager::ApplicationManifest
    {
        return ManifestTraits<T>::GetManifest();
    }

    /// This is template for creating new applications. Main difference between Application and service is that:
    /// 1. Application has access to GUI and Input
    /// 2. Application lifetime is managed with app::manager::ApplicationManager


@@ 111,6 154,8 @@ namespace app
        /// c_str() function for Application::State
        static const char *stateStr(State st);

        using OnActionReceived = std::function<void(manager::actions::ActionParamsPtr &&)>;

      private:
        std::string default_window;
        State state = State::DEACTIVATED;


@@ 122,6 167,7 @@ namespace app
        sys::Message_t handleBatteryLevel(sys::DataMessage *msgl);
        sys::Message_t handleChargerPlugged(sys::DataMessage *msgl);
        sys::Message_t handleMinuteUpdated(sys::DataMessage *msgl);
        sys::Message_t handleAction(sys::DataMessage *msgl);
        sys::Message_t handleApplicationSwitch(sys::DataMessage *msgl);
        sys::Message_t handleSwitchWindow(sys::DataMessage *msgl);
        sys::Message_t handleAppClose(sys::DataMessage *msgl);


@@ 131,14 177,15 @@ namespace app
        sys::Message_t handleSIMMessage(sys::DataMessage *msgl);

        std::list<std::unique_ptr<app::GuiTimer>> gui_timers;
        std::unordered_map<manager::actions::ActionId, OnActionReceived> receivers;

      public:
        std::unique_ptr<sys::Timer> longPressTimer;
        Application(std::string name,
                    std::string parent            = "",
                    bool startBackground          = false,
                    uint32_t stackDepth           = 4096,
                    sys::ServicePriority priority = sys::ServicePriority::Idle);
                    std::string parent                  = "",
                    StartInBackground startInBackground = {false},
                    uint32_t stackDepth                 = 4096,
                    sys::ServicePriority priority       = sys::ServicePriority::Idle);

        virtual ~Application();



@@ 287,6 334,10 @@ namespace app
        /// @note consider moving these as private elements of ApplicationManager i.e. under names
        /// message::switchApplication etc.
        /// @{
        static void requestAction(sys::Service *sender,
                                  const ApplicationName &applicationName,
                                  manager::actions::ActionId actionId,
                                  manager::actions::ActionParamsPtr &&data);
        static void messageSwitchApplication(sys::Service *sender,
                                             std::string application,
                                             std::string window,


@@ 343,7 394,7 @@ namespace app
        /// 2. simple translation of keys 1 to 1 with keyboard
        std::unique_ptr<gui::KeyInputSimpleTranslation> keyTranslator;
        /// Flag defines how application will behave after registration. It can go forground or background
        bool startBackground = false;
        StartInBackground startInBackground{false};
        /// Flag which defines whether application initialized suspend mode, this will influence how render message will
        /// sent to gui service. If suspend is true, application manager will receive information from both eink and gui
        /// services if last rendering mesage will be processed.


@@ 358,6 409,24 @@ namespace app
        static void messageInputEventApplication(sys::Service *sender,
                                                 std::string application,
                                                 const gui::InputEvent &event);

        void addActionReceiver(manager::actions::ActionId actionId, OnActionReceived &&callback);
    };

    /// Parameter pack used by application launch action.
    class ApplicationLaunchData : public manager::actions::ActionParams
    {
      public:
        ApplicationLaunchData(const app::ApplicationName &appName)
            : manager::actions::ActionParams{"Application launch parameters"}, targetAppName{appName}
        {}

        [[nodiscard]] auto getTargetApplicationName() const noexcept
        {
            return targetAppName;
        }

      private:
        ApplicationName targetAppName;
    };
} /* namespace app */

M module-apps/ApplicationLauncher.hpp => module-apps/ApplicationLauncher.hpp +17 -4
@@ 7,6 7,7 @@

namespace app
{
    using ApplicationManifest = app::manager::ApplicationManifest;

    /// used in ApplicationManager to start applications
    class ApplicationLauncher


@@ 16,6 17,8 @@ namespace app
        std::string name;
        /// name of the application's owner
        std::string parent;
        /// Application's manifest
        ApplicationManifest manifest;
        /// defines whether application can be closed when it looses focus
        bool closeable = true;
        /// defines whether application should be run without gaining focus, it will remian in the BACKGROUND state


@@ 24,8 27,11 @@ namespace app
        bool preventBlocking = false;

      public:
        ApplicationLauncher(std::string name, bool isCloseable, bool preventBlocking = false)
            : name{name}, closeable{isCloseable}, preventBlocking{preventBlocking} {};
        ApplicationLauncher(std::string name,
                            ApplicationManifest &&manifest,
                            bool isCloseable,
                            bool preventBlocking = false)
            : name{name}, manifest{std::move(manifest)}, closeable{isCloseable}, preventBlocking{preventBlocking} {};
        virtual ~ApplicationLauncher() = default;

        [[nodiscard]] std::string getName() const noexcept


@@ 33,6 39,11 @@ namespace app
            return name;
        }

        [[nodiscard]] const ApplicationManifest &getManifest() const noexcept
        {
            return manifest;
        }

        [[nodiscard]] bool isCloseable() const noexcept
        {
            return closeable;


@@ 60,7 71,8 @@ namespace app
    template <class T> class ApplicationLauncherT : public ApplicationLauncher
    {
      public:
        ApplicationLauncherT(std::string name, bool isCloseable = true) : ApplicationLauncher(name, isCloseable)
        ApplicationLauncherT(std::string name, ApplicationManifest &&manifest, bool isCloseable = true)
            : ApplicationLauncher(name, std::move(manifest), isCloseable)
        {}

        bool run(sys::Service *caller) override


@@ 82,6 94,7 @@ namespace app
    template <class T>
    std::unique_ptr<ApplicationLauncherT<T>> CreateLauncher(std::string name, bool isCloseable = true)
    {
        return std::unique_ptr<ApplicationLauncherT<T>>(new ApplicationLauncherT<T>(name, isCloseable));
        return std::unique_ptr<ApplicationLauncherT<T>>(
            new ApplicationLauncherT<T>(name, ManifestOf<T>(), isCloseable));
    }
} // namespace app

M module-apps/UiCommonActions.cpp => module-apps/UiCommonActions.cpp +4 -6
@@ 12,7 12,7 @@
#include "application-special-input/ApplicationSpecialInput.hpp"

#include "service-appmgr/Controller.hpp"
#include "service-appmgr/messages/APMMessage.hpp"
#include "service-appmgr/messages/Message.hpp"

#include <i18/i18.hpp>
#include <log/log.hpp>


@@ 40,10 40,8 @@ namespace app
    auto call(Application *app, const utils::PhoneNumber::View &phoneNumber) -> bool
    {
        assert(app != nullptr);
        auto data             = std::make_unique<ExecuteCallData>(phoneNumber);
        data->disableAppClose = true;

        return app::manager::Controller::switchApplication(app, name_call, window::name_enterNumber, std::move(data));
        auto data = std::make_unique<ExecuteCallData>(phoneNumber);
        return app::manager::Controller::sendAction(app, manager::actions::Call, std::move(data));
    }

    auto prepareCall(Application *app, const std::string &number) -> bool


@@ 169,6 167,6 @@ namespace app
                app, app::special_input, app::char_select, std::move(switchData));
        }
        return app::manager::Controller::switchBack(
            app, std::make_unique<app::manager::APMSwitchPrevApp>(switchData->requester, std::move(switchData)));
            app, std::make_unique<app::manager::SwitchBackRequest>(switchData->requester, std::move(switchData)));
    }
} // namespace app

M module-apps/application-antenna/ApplicationAntenna.cpp => module-apps/application-antenna/ApplicationAntenna.cpp +2 -2
@@ 34,8 34,8 @@ namespace app
        }
    }

    ApplicationAntenna::ApplicationAntenna(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, 4096 * 2)
    ApplicationAntenna::ApplicationAntenna(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground, 4096 * 2)
    {
        busChannels.push_back(sys::BusChannels::AntennaNotifications);
        busChannels.push_back(sys::BusChannels::AntennaNotifications);

M module-apps/application-antenna/ApplicationAntenna.hpp => module-apps/application-antenna/ApplicationAntenna.hpp +11 -1
@@ 30,6 30,7 @@ namespace app
        };
        constexpr uint32_t paramsMaxSize = 9;
    } // namespace antenna

    class ApplicationAntenna : public app::Application
    {
      protected:


@@ 44,7 45,9 @@ namespace app
        uint32_t lastFreq = 0;

      public:
        ApplicationAntenna(std::string name = name_antenna, std::string parent = "", bool startBackgound = false);
        ApplicationAntenna(std::string name                    = name_antenna,
                           std::string parent                  = {},
                           StartInBackground startInBackground = {false});
        virtual ~ApplicationAntenna();

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;


@@ 73,6 76,13 @@ namespace app
        std::vector<app::antenna::StoreParams> highBandParams;
    };

    template <> struct ManifestTraits<ApplicationAntenna>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

#endif /* MODULE_APPS_APPLICATION_ANTENNA_APPLICATIONANTENNA_HPP_ */

M module-apps/application-calculator/ApplicationCalculator.cpp => module-apps/application-calculator/ApplicationCalculator.cpp +4 -3
@@ 7,9 7,10 @@

namespace app
{

    ApplicationCalculator::ApplicationCalculator(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, stack_size)
    ApplicationCalculator::ApplicationCalculator(std::string name,
                                                 std::string parent,
                                                 StartInBackground startInBackground)
        : Application(name, parent, startInBackground, stack_size)
    {}

    sys::Message_t ApplicationCalculator::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)

M module-apps/application-calculator/ApplicationCalculator.hpp => module-apps/application-calculator/ApplicationCalculator.hpp +10 -2
@@ 12,9 12,10 @@ namespace app

    class ApplicationCalculator : public Application
    {

      public:
        ApplicationCalculator(std::string name = name_calculator, std::string parent = "", bool startBackgound = false);
        ApplicationCalculator(std::string name                    = name_calculator,
                              std::string parent                  = {},
                              StartInBackground startInBackground = {false});
        ~ApplicationCalculator() override = default;

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;


@@ 30,4 31,11 @@ namespace app
        void destroyUserInterface() final;
    };

    template <> struct ManifestTraits<ApplicationCalculator>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +2 -1
@@ 44,9 44,10 @@ namespace app

    ApplicationCalendar::ApplicationCalendar(std::string name,
                                             std::string parent,
                                             StartInBackground startInBackground,
                                             uint32_t stackDepth,
                                             sys::ServicePriority priority)
        : Application(name, parent, false, stackDepth, priority)
        : Application(name, parent, startInBackground, stackDepth, priority)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);
    }

M module-apps/application-calendar/ApplicationCalendar.hpp => module-apps/application-calendar/ApplicationCalendar.hpp +11 -2
@@ 25,8 25,9 @@ namespace app
      public:
        ApplicationCalendar(std::string name,
                            std::string parent,
                            uint32_t stackDepth           = 4096,
                            sys::ServicePriority priority = sys::ServicePriority::Idle);
                            StartInBackground startInBackground = {false},
                            uint32_t stackDepth                 = 4096,
                            sys::ServicePriority priority       = sys::ServicePriority::Idle);

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;


@@ 59,4 60,12 @@ namespace app
        static const std::map<Reminder, const char *> reminderOptions;
        static const std::map<Repeat, const char *> repeatOptions;
    };

    template <> struct ManifestTraits<ApplicationCalendar>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +4 -3
@@ 30,10 30,11 @@

namespace app
{

    ApplicationCall::ApplicationCall(std::string name, std::string parent, bool startBackground)
        : Application(name, parent, startBackground, app::call_stack_size)
    ApplicationCall::ApplicationCall(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground, app::call_stack_size)
    {
        addActionReceiver(manager::actions::Call,
                          [this](auto data) { switchWindow(window::name_enterNumber, std::move(data)); });
    }

    //  number of seconds after end call to switch back to previous application

M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +11 -1
@@ 38,7 38,9 @@ namespace app
        sys::ms callDelayedStopTime = 3000;

      public:
        ApplicationCall(std::string name = name_call, std::string parent = "", bool startBackgound = false);
        ApplicationCall(std::string name                    = name_call,
                        std::string parent                  = {},
                        StartInBackground startInBackground = {false});
        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;
        sys::ReturnCodes DeinitHandler() override;


@@ 67,4 69,12 @@ namespace app
        void startRinging();
        void startRouting();
    };

    template <> struct ManifestTraits<ApplicationCall>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch, manager::actions::Call}};
        }
    };
} /* namespace app */

M module-apps/application-call/windows/EmergencyCallWindow.cpp => module-apps/application-call/windows/EmergencyCallWindow.cpp +1 -1
@@ 3,7 3,7 @@

#include "../data/CallSwitchData.hpp"
#include "../ApplicationCall.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "i18/i18.hpp"
#include "EmergencyCallWindow.hpp"

M module-apps/application-calllog/ApplicationCallLog.cpp => module-apps/application-calllog/ApplicationCallLog.cpp +2 -3
@@ 23,9 23,8 @@ using namespace calllog;

namespace app
{

    ApplicationCallLog::ApplicationCallLog(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, 4096)
    ApplicationCallLog::ApplicationCallLog(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground, 4096)
    {}

    ApplicationCallLog::~ApplicationCallLog()

M module-apps/application-calllog/ApplicationCallLog.hpp => module-apps/application-calllog/ApplicationCallLog.hpp +10 -2
@@ 14,9 14,10 @@ namespace app

    class ApplicationCallLog : public Application
    {
      protected:
      public:
        ApplicationCallLog(std::string name = CallLogAppStr, std::string parent = "", bool startBackgound = false);
        ApplicationCallLog(std::string name                    = CallLogAppStr,
                           std::string parent                  = {},
                           StartInBackground startInBackground = {false});
        ~ApplicationCallLog() override;

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;


@@ 36,4 37,11 @@ namespace app
        bool setAllEntriesRead();
    };

    template <> struct ManifestTraits<ApplicationCallLog>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp => module-apps/application-calllog/windows/CallLogDetailsWindow.cpp +1 -1
@@ 6,7 6,7 @@
#include <functional>

#include "OptionsWindow.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "bsp/rtc/rtc.hpp"


M module-apps/application-calllog/windows/CallLogMainWindow.cpp => module-apps/application-calllog/windows/CallLogMainWindow.cpp +1 -1
@@ 7,7 7,7 @@
#include "application-calllog/widgets/CalllogItem.hpp"

#include <application-call/ApplicationCall.hpp>
#include <service-appmgr/ApplicationManager.hpp>
#include <module-services/service-appmgr/model/ApplicationManager.hpp>
#include <service-db/messages/DBCalllogMessage.hpp>
#include <i18/i18.hpp>
#include <Label.hpp>

M module-apps/application-clock/ApplicationClock.cpp => module-apps/application-clock/ApplicationClock.cpp +3 -3
@@ 11,7 11,7 @@
// module-services
#include "service-evtmgr/EventManager.hpp"
#include "service-evtmgr/messages/EVMessages.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
// MessageType
#include "MessageType.hpp"
// this module


@@ 20,12 20,12 @@

namespace app
{

    ApplicationClock::ApplicationClock(std::string name,
                                       std::string parent,
                                       StartInBackground startInBackground,
                                       uint32_t stackDepth,
                                       sys::ServicePriority priority)
        : Application(name, parent, false, stackDepth, priority)
        : Application(name, parent, startInBackground, stackDepth, priority)
    {
        timerClock = std::make_unique<sys::Timer>("Clock", this, 1000);
        timerClock->connect([&](sys::Timer &) { timerClockCallback(); });

M module-apps/application-clock/ApplicationClock.hpp => module-apps/application-clock/ApplicationClock.hpp +13 -4
@@ 10,6 10,7 @@

namespace app
{
    const inline std::string name_clock = "ApplicationClock";

    class ApplicationClock : public Application
    {


@@ 17,10 18,11 @@ namespace app
        void timerClockCallback();

      public:
        ApplicationClock(std::string name,
                         std::string parent            = "",
                         uint32_t stackDepth           = 4096,
                         sys::ServicePriority priority = sys::ServicePriority::Idle);
        ApplicationClock(std::string name                    = name_clock,
                         std::string parent                  = {},
                         StartInBackground startInBackground = {false},
                         uint32_t stackDepth                 = 4096,
                         sys::ServicePriority priority       = sys::ServicePriority::Idle);

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;


@@ 35,4 37,11 @@ namespace app
        void destroyUserInterface() override;
    };

    template <> struct ManifestTraits<ApplicationClock>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +2 -3
@@ 26,9 26,8 @@
#include <cassert>
namespace app
{

    ApplicationDesktop::ApplicationDesktop(std::string name, std::string parent, bool startBackground)
        : Application(name, parent), lockHandler(this, settings)
    ApplicationDesktop::ApplicationDesktop(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground), lockHandler(this, settings)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);
    }

M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +10 -1
@@ 46,7 46,9 @@ namespace app

        gui::PinLockHandler lockHandler;

        ApplicationDesktop(std::string name = name_desktop, std::string parent = "", bool startBackground = false);
        ApplicationDesktop(std::string name                    = name_desktop,
                           std::string parent                  = {},
                           StartInBackground startInBackground = {false});
        virtual ~ApplicationDesktop();
        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;


@@ 75,7 77,14 @@ namespace app
        bool clearMessagesNotification();
        bool requestNotSeenNotifications();
        bool requestNotReadNotifications();
    };

    template <> struct ManifestTraits<ApplicationDesktop>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };

} /* namespace app */

M module-apps/application-desktop/windows/PowerOffWindow.cpp => module-apps/application-desktop/windows/PowerOffWindow.cpp +1 -1
@@ 13,7 13,7 @@
#include "../ApplicationDesktop.hpp"

// services
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "service-cellular/ServiceCellular.hpp"
#include <Style.hpp>

M module-apps/application-desktop/windows/Update.cpp => module-apps/application-desktop/windows/Update.cpp +1 -1
@@ 13,7 13,7 @@
#include "Update.hpp"
#include "../ApplicationDesktop.hpp"
// services
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "service-cellular/ServiceCellular.hpp"
#include <Style.hpp>

M module-apps/application-meditation/ApplicationMeditation.cpp => module-apps/application-meditation/ApplicationMeditation.cpp +4 -2
@@ 10,8 10,10 @@

namespace app
{
    ApplicationMeditation::ApplicationMeditation(std::string name, std::string parent, bool startBackground)
        : Application{name, parent, startBackground}, state{std::make_unique<gui::OptionsData>()}
    ApplicationMeditation::ApplicationMeditation(std::string name,
                                                 std::string parent,
                                                 StartInBackground startInBackground)
        : Application{name, parent, startInBackground}, state{std::make_unique<gui::OptionsData>()}
    {}

    auto ApplicationMeditation::InitHandler() -> sys::ReturnCodes

M module-apps/application-meditation/ApplicationMeditation.hpp => module-apps/application-meditation/ApplicationMeditation.hpp +11 -3
@@ 15,9 15,9 @@ namespace app
    class ApplicationMeditation : public Application
    {
      public:
        explicit ApplicationMeditation(std::string name     = name_meditation,
                                       std::string parent   = {},
                                       bool startBackground = false);
        explicit ApplicationMeditation(std::string name                    = name_meditation,
                                       std::string parent                  = {},
                                       StartInBackground startInBackground = {false});

        auto InitHandler() -> sys::ReturnCodes override;
        auto DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) -> sys::Message_t override;


@@ 27,4 27,12 @@ namespace app
        void destroyUserInterface() override;
        std::unique_ptr<gui::OptionsData> state;
    };

    template <> struct ManifestTraits<ApplicationMeditation>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} // namespace app

M module-apps/application-messages/ApplicationMessages.cpp => module-apps/application-messages/ApplicationMessages.cpp +2 -3
@@ 36,9 36,8 @@

namespace app
{

    ApplicationMessages::ApplicationMessages(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, 4096 * 2)
    ApplicationMessages::ApplicationMessages(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground, 4096 * 2)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);
    }

M module-apps/application-messages/ApplicationMessages.hpp => module-apps/application-messages/ApplicationMessages.hpp +11 -1
@@ 38,7 38,9 @@ namespace app
    class ApplicationMessages : public app::Application
    {
      public:
        ApplicationMessages(std::string name = name_messages, std::string parent = "", bool startBackgound = false);
        ApplicationMessages(std::string name                    = name_messages,
                            std::string parent                  = {},
                            StartInBackground startInBackground = {false});
        virtual ~ApplicationMessages();

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;


@@ 75,4 77,12 @@ namespace app
        // used by sms template items
        std::function<bool(std::shared_ptr<SMSTemplateRecord> templ)> templatesCallback;
    };

    template <> struct ManifestTraits<ApplicationMessages>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-messages/windows/MessagesMainWindow.cpp => module-apps/application-messages/windows/MessagesMainWindow.cpp +1 -1
@@ 9,7 9,7 @@
#include "application-messages/widgets/ThreadItem.hpp"
#include "application-messages/windows/SearchStart.hpp"

#include <service-appmgr/ApplicationManager.hpp>
#include <module-services/service-appmgr/model/ApplicationManager.hpp>
#include <i18/i18.hpp>
#include <service-db/api/DBServiceAPI.hpp>
#include <application-phonebook/data/PhonebookItemData.hpp>

M module-apps/application-messages/windows/SMSTemplatesWindow.cpp => module-apps/application-messages/windows/SMSTemplatesWindow.cpp +1 -1
@@ 83,7 83,7 @@ namespace gui
            LOG_DEBUG("SMS template id = %" PRIu32 "sent to %s", templ->ID, phoneNumber.getFormatted().c_str());
            app->sendSms(phoneNumber, templ->text);
            app::manager::Controller::switchBack(app,
                                                 std::make_unique<app::manager::APMSwitchPrevApp>(
                                                 std::make_unique<app::manager::SwitchBackRequest>(
                                                     application->GetName(), std::make_unique<SMSTemplateSent>()));
            return true;
        };

M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +4 -3
@@ 13,9 13,10 @@

namespace app
{

    ApplicationMusicPlayer::ApplicationMusicPlayer(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, 4096)
    ApplicationMusicPlayer::ApplicationMusicPlayer(std::string name,
                                                   std::string parent,
                                                   StartInBackground startInBackground)
        : Application(name, parent, startInBackground, 4096)
    {
        LOG_INFO("ApplicationMusicPlayer::create");
    }

M module-apps/application-music-player/ApplicationMusicPlayer.hpp => module-apps/application-music-player/ApplicationMusicPlayer.hpp +10 -3
@@ 27,9 27,9 @@ namespace app
    {

      public:
        ApplicationMusicPlayer(std::string name    = name_music_player,
                               std::string parent  = "",
                               bool startBackgound = false);
        ApplicationMusicPlayer(std::string name                    = name_music_player,
                               std::string parent                  = {},
                               StartInBackground startInBackground = {false});
        virtual ~ApplicationMusicPlayer();

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;


@@ 52,4 52,11 @@ namespace app
        std::optional<audio::Tags> getFileTags(const std::string &filePath);
    };

    template <> struct ManifestTraits<ApplicationMusicPlayer>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +2 -3
@@ 10,9 10,8 @@

namespace app
{

    ApplicationNotes::ApplicationNotes(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, 4096)
    ApplicationNotes::ApplicationNotes(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground, 4096)
    {}

    ApplicationNotes::~ApplicationNotes()

M module-apps/application-notes/ApplicationNotes.hpp => module-apps/application-notes/ApplicationNotes.hpp +10 -3
@@ 9,14 9,14 @@

namespace app
{

    inline const std::string name_notes = "ApplicationNotes";

    class ApplicationNotes : public Application
    {
      protected:
      public:
        ApplicationNotes(std::string name = name_notes, std::string parent = "", bool startBackgound = false);
        ApplicationNotes(std::string name                    = name_notes,
                         std::string parent                  = {},
                         StartInBackground startInBackground = {false});
        virtual ~ApplicationNotes();
        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;


@@ 31,6 31,13 @@ namespace app
        void destroyUserInterface() override;
    };

    template <> struct ManifestTraits<ApplicationNotes>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

#endif /* MODULE_APPS_APPLICATION_NOTES_APPLICATIONNOTES_HPP_ */

M module-apps/application-notes/windows/NotesEditWindow.cpp => module-apps/application-notes/windows/NotesEditWindow.cpp +1 -1
@@ 4,7 4,7 @@
#include <memory>
#include <functional>

#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "bsp/rtc/rtc.hpp"


M module-apps/application-notes/windows/NotesMainWindow.cpp => module-apps/application-notes/windows/NotesMainWindow.cpp +1 -1
@@ 5,7 5,7 @@
#include <functional>

#include "InputEvent.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "../ApplicationNotes.hpp"


M module-apps/application-phonebook/ApplicationPhonebook.cpp => module-apps/application-phonebook/ApplicationPhonebook.cpp +5 -4
@@ 19,9 19,10 @@

namespace app
{

    ApplicationPhonebook::ApplicationPhonebook(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound, phonebook_stack_size)
    ApplicationPhonebook::ApplicationPhonebook(std::string name,
                                               std::string parent,
                                               StartInBackground startInBackground)
        : Application(name, parent, startInBackground, phonebook_stack_size)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);
    }


@@ 162,7 163,7 @@ namespace app
                    data->result                                 = item->contact;
                    data->setDescription("PhonebookSearchRequest");
                    return app::manager::Controller::switchBack(
                        this, std::make_unique<app::manager::APMSwitchPrevApp>(GetName(), std::move(data)));
                        this, std::make_unique<app::manager::SwitchBackRequest>(GetName(), std::move(data)));
                };
            }
            LOG_DEBUG("Switching to search results window.");

M module-apps/application-phonebook/ApplicationPhonebook.hpp => module-apps/application-phonebook/ApplicationPhonebook.hpp +10 -1
@@ 31,7 31,9 @@ namespace app
    class ApplicationPhonebook : public app::Application
    {
      public:
        ApplicationPhonebook(std::string name = name_phonebook, std::string parent = "", bool startBackgound = false);
        ApplicationPhonebook(std::string name                    = name_phonebook,
                             std::string parent                  = {},
                             StartInBackground startInBackground = {false});
        ~ApplicationPhonebook() override = default;

        auto DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) -> sys::Message_t override;


@@ 49,4 51,11 @@ namespace app
        bool searchEmpty(const std::string &query);
    };

    template <> struct ManifestTraits<ApplicationPhonebook>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} // namespace app

M module-apps/application-phonebook/windows/PhonebookMainWindow.cpp => module-apps/application-phonebook/windows/PhonebookMainWindow.cpp +1 -1
@@ 108,7 108,7 @@ namespace gui
                data->setDescription("PhonebookSearchRequest");
                return app::manager::Controller::switchBack(
                    application,
                    std::make_unique<app::manager::APMSwitchPrevApp>(application->GetName(), std::move(data)));
                    std::make_unique<app::manager::SwitchBackRequest>(application->GetName(), std::move(data)));
            };

            leftArrowImage->setVisible(false);

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +4 -2
@@ 30,8 30,10 @@

namespace app
{
    ApplicationSettingsNew::ApplicationSettingsNew(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound)
    ApplicationSettingsNew::ApplicationSettingsNew(std::string name,
                                                   std::string parent,
                                                   StartInBackground startInBackground)
        : Application(name, parent, startInBackground)
    {}

    // Invoked upon receiving data message

M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +10 -3
@@ 51,9 51,9 @@ namespace app
    class ApplicationSettingsNew : public app::Application
    {
      public:
        ApplicationSettingsNew(std::string name    = name_settings_new,
                               std::string parent  = "",
                               bool startBackgound = false);
        ApplicationSettingsNew(std::string name                    = name_settings_new,
                               std::string parent                  = {},
                               StartInBackground startInBackground = {false});
        auto DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) -> sys::Message_t override;
        auto InitHandler() -> sys::ReturnCodes override;



@@ 67,4 67,11 @@ namespace app
        bsp::Board board = bsp::Board::none;
    };

    template <> struct ManifestTraits<ApplicationSettingsNew>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +2 -3
@@ 32,9 32,8 @@

namespace app
{

    ApplicationSettings::ApplicationSettings(std::string name, std::string parent, bool startBackgound)
        : Application(name, parent, startBackgound)
    ApplicationSettings::ApplicationSettings(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground)
    {
        busChannels.push_back(sys::BusChannels::AntennaNotifications);
    }

M module-apps/application-settings/ApplicationSettings.hpp => module-apps/application-settings/ApplicationSettings.hpp +10 -1
@@ 18,7 18,9 @@ namespace app
    class ApplicationSettings : public app::Application
    {
      public:
        ApplicationSettings(std::string name = name_settings, std::string parent = "", bool startBackgound = false);
        ApplicationSettings(std::string name                    = name_settings,
                            std::string parent                  = {},
                            StartInBackground startInBackground = {false});
        virtual ~ApplicationSettings();
        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;


@@ 34,6 36,13 @@ namespace app
        bsp::Board board = bsp::Board::none;
    };

    template <> struct ManifestTraits<ApplicationSettings>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
} /* namespace app */

#endif /* MODULE_APPS_APPLICATION_SETTINGS_APPLICATIONSETTINGS_HPP_ */

M module-apps/application-settings/windows/BtScanWindow.cpp => module-apps/application-settings/windows/BtScanWindow.cpp +1 -1
@@ 4,7 4,7 @@
#include <functional>
#include <memory>

#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "../ApplicationSettings.hpp"


M module-apps/application-settings/windows/BtWindow.cpp => module-apps/application-settings/windows/BtWindow.cpp +1 -1
@@ 4,7 4,7 @@
#include <functional>
#include <memory>

#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "../ApplicationSettings.hpp"
#include "../windows/BtScanWindow.hpp"

M module-apps/application-settings/windows/DateTimeWindow.cpp => module-apps/application-settings/windows/DateTimeWindow.cpp +1 -1
@@ 11,7 11,7 @@
#include <functional>
#include <memory>

#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "../ApplicationSettings.hpp"
#include "DateTimeWindow.hpp"

M module-apps/application-settings/windows/TestMessageWindow.cpp => module-apps/application-settings/windows/TestMessageWindow.cpp +1 -1
@@ 11,7 11,7 @@
#include <memory>
#include <functional>

#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"

#include "../ApplicationSettings.hpp"


M module-apps/application-settings/windows/UITestWindow.cpp => module-apps/application-settings/windows/UITestWindow.cpp +1 -1
@@ 8,7 8,7 @@
#include "i18/i18.hpp"
#include "log/log.hpp"
#include "messages/AppMessage.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
#include <GridLayout.hpp>
#include <Style.hpp>
#include <functional>

M module-apps/application-settings/windows/USSDWindow.cpp => module-apps/application-settings/windows/USSDWindow.cpp +1 -1
@@ 7,7 7,7 @@
#include "Margins.hpp"
#include "i18/i18.hpp"
#include "messages/AppMessage.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
#include <GridLayout.hpp>
#include <Style.hpp>
#include <functional>

M module-apps/application-special-input/ApplicationSpecialInput.cpp => module-apps/application-special-input/ApplicationSpecialInput.cpp +4 -2
@@ 7,8 7,10 @@

using namespace app;

ApplicationSpecialInput::ApplicationSpecialInput(std::string name, std::string parent, bool startBackgound)
    : Application(name, parent, startBackgound)
ApplicationSpecialInput::ApplicationSpecialInput(std::string name,
                                                 std::string parent,
                                                 StartInBackground startInBackground)
    : Application(name, parent, startInBackground)
{
    windowsFactory.attach(app::char_select, [](Application *app, const std::string &name) {
        return std::make_unique<gui::SpecialInputMainWindow>(app);

M module-apps/application-special-input/ApplicationSpecialInput.hpp => module-apps/application-special-input/ApplicationSpecialInput.hpp +10 -1
@@ 19,7 19,9 @@ namespace app
      public:
        std::string requester = "";

        ApplicationSpecialInput(std::string name = special_input, std::string parent = "", bool startBackgound = true);
        ApplicationSpecialInput(std::string name                    = special_input,
                                std::string parent                  = {},
                                StartInBackground startInBackground = {true});
        virtual ~ApplicationSpecialInput() = default;

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;


@@ 33,4 35,11 @@ namespace app
        void destroyUserInterface() override;
    };

    template <> struct ManifestTraits<ApplicationSpecialInput>
    {
        static auto GetManifest() -> manager::ApplicationManifest
        {
            return {{manager::actions::Launch}};
        }
    };
}; // namespace app

M module-apps/messages/AppMessage.hpp => module-apps/messages/AppMessage.hpp +22 -0
@@ 24,6 24,28 @@ namespace app
        AppMessage() : sys::DataMessage(MessageType::AppMessage){};
    };

    class AppActionRequest : public AppMessage
    {
      public:
        AppActionRequest(manager::actions::ActionId _actionId, manager::actions::ActionParamsPtr _data)
            : AppMessage(MessageType::AppAction), actionId{_actionId}, data{std::move(_data)}
        {}

        manager::actions::ActionId getAction() const noexcept
        {
            return actionId;
        }

        manager::actions::ActionParamsPtr &getData() noexcept
        {
            return data;
        }

      private:
        manager::actions::ActionId actionId;
        manager::actions::ActionParamsPtr data;
    };

    // this message is used to notify application about switching event. Application will gain or lose focus upon
    // receiving this message. Application gains focus when it was in init or active background state. Application loose
    // focus when it was in active foreground state. if no window is specified it is assumed that MainWindow is the

M module-apps/windows/Dialog.cpp => module-apps/windows/Dialog.cpp +1 -1
@@ 3,7 3,7 @@

#include "Dialog.hpp"
#include "DialogMetadataMessage.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
#include <i18/i18.hpp>

using namespace gui;

M module-apps/windows/OptionWindow.cpp => module-apps/windows/OptionWindow.cpp +1 -1
@@ 6,7 6,7 @@
#include "Margins.hpp"
#include "i18/i18.hpp"
#include "log/log.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
#include <Style.hpp>
#include <cassert>
#include <functional>

M module-services/service-antenna/ServiceAntenna.cpp => module-services/service-antenna/ServiceAntenna.cpp +1 -1
@@ 2,7 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ServiceAntenna.hpp"
#include <service-appmgr/ApplicationManager.hpp>
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
#include <common_data/EventStore.hpp>

#include <at/response.hpp> // for parseCSQ, isRegistered, parseCREG, parseNetworkFrequency, parseQNWINFO

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

#pragma once

#include <memory>
#include <string>
#include <vector>

#include <module-gui/gui/SwitchData.hpp>

namespace app::manager::actions
{
    using ActionId     = int;
    using ActionFilter = std::vector<ActionId>;

    enum Action : ActionId
    {
        Launch,
        Call,
        UserAction
    };

    using ActionParams    = gui::SwitchData;
    using ActionParamsPtr = std::unique_ptr<ActionParams>;
} // namespace app::manager::actions

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

#include "ApplicationManifest.hpp"

#include <algorithm>

namespace app::manager
{
    ApplicationManifest::ApplicationManifest(actions::ActionFilter _actions) : actions{std::move(_actions)}
    {}

    auto ApplicationManifest::contains(actions::ActionId action) const noexcept -> bool
    {
        auto it = std::find(actions.begin(), actions.end(), action);
        return it != actions.end();
    }
} // namespace app::manager

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

#pragma once

#include "Actions.hpp"

namespace app::manager
{
    struct ApplicationManifest
    {
        ApplicationManifest(actions::ActionFilter _actions = {});

        auto contains(actions::ActionId action) const noexcept -> bool;

        /// Actions the application can respond to.
        actions::ActionFilter actions;
    };
} // namespace app::manager

M module-services/service-appmgr/CMakeLists.txt => module-services/service-appmgr/CMakeLists.txt +9 -2
@@ 13,10 13,17 @@ message("${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}")

target_sources(${PROJECT_NAME}
	PRIVATE
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationManager.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationManifest.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/Controller.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/model/ApplicationManager.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/model/ApplicationHandle.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/model/ApplicationsRegistry.cpp"
	PUBLIC
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationManager.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/Actions.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationManifest.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/Controller.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/model/ApplicationManager.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/model/ApplicationHandle.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/model/ApplicationsRegistry.hpp"
)


M module-services/service-appmgr/Controller.cpp => module-services/service-appmgr/Controller.cpp +23 -19
@@ 7,80 7,84 @@

#include "module-sys/Service/Bus.hpp" // for Bus
#include "Service/Service.hpp"        // for Service
#include "service-appmgr/ApplicationManager.hpp" // for ApplicationManager, ApplicationManager::ServiceName, ApplicationHandle, ApplicationHandle::Name
#include "service-appmgr/model/ApplicationManager.hpp" // for ApplicationManager, ApplicationManager::ServiceName, ApplicationHandle, ApplicationHandle::Name

namespace app::manager
{
    auto Controller::registerApplication(sys::Service *sender, bool status, bool startBackground) -> bool
    auto Controller::sendAction(sys::Service *sender, actions::ActionId actionId, actions::ActionParamsPtr &&data)
        -> bool
    {
        auto msg = std::make_shared<app::manager::APMRegister>(sender->GetName(), status, startBackground);
        auto msg = std::make_shared<app::manager::ActionRequest>(sender->GetName(), actionId, std::move(data));
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::sendAction(sys::Service *sender, Action &&action) -> bool
    auto Controller::applicationInitialised(sys::Service *sender,
                                            StartupStatus status,
                                            StartInBackground startInBackground) -> bool
    {
        auto msg = std::make_shared<app::manager::APMAction>(sender->GetName(), std::move(action));
        auto msg =
            std::make_shared<app::manager::ApplicationInitialisation>(sender->GetName(), status, startInBackground);
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::switchApplication(sys::Service *sender,
                                       const ApplicationHandle::Name &applicationName,
                                       const ApplicationName &applicationName,
                                       const std::string &windowName,
                                       std::unique_ptr<gui::SwitchData> data) -> bool
    {
        auto msg =
            std::make_shared<app::manager::APMSwitch>(sender->GetName(), applicationName, windowName, std::move(data));
        auto msg = std::make_shared<app::manager::SwitchRequest>(
            sender->GetName(), applicationName, windowName, std::move(data));
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::confirmSwitch(sys::Service *sender) -> bool
    {

        auto msg = std::make_shared<app::manager::APMConfirmSwitch>(sender->GetName());
        auto msg = std::make_shared<app::manager::SwitchConfirmation>(sender->GetName());
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::confirmClose(sys::Service *sender) -> bool
    {
        auto msg = std::make_shared<app::manager::APMConfirmClose>(sender->GetName());
        auto msg = std::make_shared<app::manager::CloseConfirmation>(sender->GetName());
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::closeApplication(sys::Service *sender, const ApplicationHandle::Name &name) -> bool
    auto Controller::closeApplication(sys::Service *sender, const ApplicationName &name) -> bool
    {
        auto msg = std::make_shared<app::manager::APMDelayedClose>(sender->GetName(), name);
        auto msg = std::make_shared<app::manager::ApplicationCloseRequest>(sender->GetName(), name);
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::switchBack(sys::Service *sender, std::unique_ptr<APMSwitchPrevApp> msg) -> bool
    auto Controller::switchBack(sys::Service *sender, std::unique_ptr<SwitchBackRequest> msg) -> bool
    {

        std::shared_ptr<APMSwitchPrevApp> switchMsg =
            msg ? std::move(msg) : std::make_shared<app::manager::APMSwitchPrevApp>(sender->GetName());
        std::shared_ptr<SwitchBackRequest> switchMsg =
            msg ? std::move(msg) : std::make_shared<app::manager::SwitchBackRequest>(sender->GetName());
        return sys::Bus::SendUnicast(switchMsg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::changeLanguage(sys::Service *sender, utils::Lang language) -> bool
    {
        auto msg = std::make_shared<app::manager::APMChangeLanguage>(sender->GetName(), language);
        auto msg = std::make_shared<app::manager::LanguageChangeRequest>(sender->GetName(), language);
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::stopApplicationManager(sys::Service *sender) -> bool
    {
        auto msg = std::make_shared<app::manager::APMClose>(sender->GetName());
        auto msg = std::make_shared<app::manager::ShutdownRequest>(sender->GetName());
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::preventBlockingDevice(sys::Service *sender) -> bool
    {
        auto msg = std::make_shared<app::manager::APMPreventBlocking>(sender->GetName());
        auto msg = std::make_shared<app::manager::PreventBlockingRequest>(sender->GetName());
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::changePowerSaveMode(sys::Service *sender) -> bool
    {
        auto msg = std::make_shared<app::manager::APMInitPowerSaveMode>(sender->GetName());
        auto msg = std::make_shared<app::manager::PowerSaveModeInitRequest>(sender->GetName());
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }
} // namespace app::manager

M module-services/service-appmgr/Controller.hpp => module-services/service-appmgr/Controller.hpp +11 -7
@@ 6,11 6,12 @@
#include <memory> // for unique_ptr
#include <string> // for string

#include "ApplicationManager.hpp" // for ApplicationHandle, ApplicationHandle::Name
#include "Actions.hpp"
#include "module-services/service-appmgr/model/ApplicationManager.hpp"
#include "module-sys/Service/Service.hpp"
#include "SwitchData.hpp"                         // for SwitchData
#include "i18/i18.hpp"                            // for Lang
#include "service-appmgr/messages/APMMessage.hpp" // for APMSwitchPrevApp, Action (ptr only)
#include "service-appmgr/messages/Message.hpp"    // for APMSwitchPrevApp, Action (ptr only)

namespace sys
{


@@ 24,14 25,17 @@ namespace app::manager
      public:
        Controller() = delete;

        static auto sendAction(sys::Service *sender, Action &&action) -> bool;
        static auto registerApplication(sys::Service *sender, bool status, bool startBackground) -> bool;
        static auto sendAction(sys::Service *sender, actions::ActionId actionId, actions::ActionParamsPtr &&data)
            -> bool;
        static auto applicationInitialised(sys::Service *sender,
                                           StartupStatus status,
                                           StartInBackground startInBackground) -> bool;
        static auto switchApplication(sys::Service *sender,
                                      const ApplicationHandle::Name &applicationName,
                                      const ApplicationName &applicationName,
                                      const std::string &windowName,
                                      std::unique_ptr<gui::SwitchData> data = nullptr) -> bool;
        static auto switchBack(sys::Service *sender, std::unique_ptr<APMSwitchPrevApp> msg = nullptr) -> bool;
        static auto closeApplication(sys::Service *sender, const ApplicationHandle::Name &name) -> bool;
        static auto switchBack(sys::Service *sender, std::unique_ptr<SwitchBackRequest> msg = nullptr) -> bool;
        static auto closeApplication(sys::Service *sender, const ApplicationName &name) -> bool;
        static auto changeLanguage(sys::Service *sender, utils::Lang language) -> bool;
        static auto changePowerSaveMode(sys::Service *sender) -> bool;
        static auto stopApplicationManager(sys::Service *sender) -> bool;

R module-services/service-appmgr/messages/APMMessage.hpp => module-services/service-appmgr/messages/Message.hpp +83 -74
@@ 5,48 5,46 @@

#include "Service/Message.hpp"
#include "MessageType.hpp"

#include "module-gui/gui/SwitchData.hpp"

#include "i18/i18.hpp"

#include <module-apps/Application.hpp>
#include <module-gui/gui/SwitchData.hpp>
#include <module-services/service-appmgr/Actions.hpp>
#include <module-services/service-appmgr/ApplicationManifest.hpp>

namespace app::manager
{
    /// A template for all messages to application manager.
    class APMMessage : public sys::DataMessage
    class Message : public sys::DataMessage
    {
      protected:
        /// name of the application that is sending message to application manager.
        std::string senderName;

      public:
        APMMessage(MessageType messageType, std::string senderName)
        Message(MessageType messageType, ApplicationName senderName)
            : sys::DataMessage(messageType), senderName{std::move(senderName)}
        {}

        [[nodiscard]] auto getSenderName() const noexcept -> std::string
        [[nodiscard]] auto getSenderName() const noexcept -> ApplicationName
        {
            return senderName;
        }

      protected:
        /// name of the application that is sending message to application manager.
        ApplicationName senderName;
    };

    /// Requests a switch to a given application. Optionally to a specified window, too.
    class APMSwitch : public APMMessage
    class SwitchRequest : public Message
    {
        std::string application;
        std::string window;
        std::unique_ptr<gui::SwitchData> data;

      public:
        APMSwitch(const std::string &senderName,
                  std::string applicationName,
                  std::string windowName,
                  std::unique_ptr<gui::SwitchData> data)
            : APMMessage(MessageType::APMSwitch, senderName),
        SwitchRequest(const ApplicationName &senderName,
                      ApplicationName applicationName,
                      std::string windowName,
                      std::unique_ptr<gui::SwitchData> data)
            : Message(MessageType::APMSwitch, senderName),
              application{std::move(applicationName)}, window{std::move(windowName)}, data{std::move(data)}
        {}

        [[nodiscard]] auto getName() const noexcept -> const std::string &
        [[nodiscard]] auto getName() const noexcept -> const ApplicationName &
        {
            return application;
        }


@@ 60,151 58,162 @@ namespace app::manager
        {
            return data;
        }

      private:
        ApplicationName application;
        std::string window;
        std::unique_ptr<gui::SwitchData> data;
    };

    /// Requests a switch to a previous application.
    class APMSwitchPrevApp : public APMMessage
    class SwitchBackRequest : public Message
    {
        std::unique_ptr<gui::SwitchData> data;

      public:
        APMSwitchPrevApp(const std::string &name, std::unique_ptr<gui::SwitchData> data = nullptr)
            : APMMessage(MessageType::APMSwitchPrevApp, name), data{std::move(data)}
        SwitchBackRequest(const ApplicationName &name, std::unique_ptr<gui::SwitchData> data = nullptr)
            : Message(MessageType::APMSwitchPrevApp, name), data{std::move(data)}
        {}

        [[nodiscard]] auto getData() noexcept -> std::unique_ptr<gui::SwitchData> &
        {
            return data;
        }

      private:
        std::unique_ptr<gui::SwitchData> data;
    };

    /// Confirms that the applications lost/gained focus.
    class APMConfirmSwitch : public APMMessage
    class SwitchConfirmation : public Message
    {
      public:
        APMConfirmSwitch(const std::string &name) : APMMessage(MessageType::APMConfirmSwitch, name)
        SwitchConfirmation(const ApplicationName &name) : Message(MessageType::APMConfirmSwitch, name)
        {}
    };

    /// Confirms that the application closed successfully.
    class APMConfirmClose : public APMMessage
    class CloseConfirmation : public Message
    {
      public:
        APMConfirmClose(const std::string &name) : APMMessage(MessageType::APMConfirmClose, name)
        CloseConfirmation(const ApplicationName &name) : Message(MessageType::APMConfirmClose, name)
        {}
    };

    /// Confirms that the application registered successfully.
    class APMRegister : public APMMessage
    ///
    class ApplicationInitialisation : public Message
    {
        bool status;
        bool startBackground;

      public:
        APMRegister(const std::string &senderName, bool status, bool startBackground)
            : APMMessage(MessageType::APMRegister, senderName), status{status}, startBackground{startBackground}
        ApplicationInitialisation(const ApplicationName &senderName,
                                  StartupStatus _status,
                                  StartInBackground _startInBackground)
            : Message(MessageType::APMInit, senderName), status{_status}, startInBackground{_startInBackground}
        {}

        [[nodiscard]] auto getStatus() const noexcept -> bool
        [[nodiscard]] auto getStatus() const noexcept -> StartupStatus
        {
            return status;
        }

        [[nodiscard]] auto getStartBackground() const noexcept -> bool
        [[nodiscard]] auto isBackgroundApplication() const noexcept -> bool
        {
            return startBackground;
            return startInBackground.value;
        }

      private:
        StartupStatus status;
        StartInBackground startInBackground;
    };

    /// Requests the application to close.
    class APMDelayedClose : public APMMessage
    class ApplicationCloseRequest : public Message
    {
        std::string application;

      public:
        APMDelayedClose(const std::string &senderName, std::string application)
            : APMMessage(MessageType::APMDelayedClose, senderName), application{std::move(application)}
        ApplicationCloseRequest(const ApplicationName &senderName, ApplicationName application)
            : Message(MessageType::APMDelayedClose, senderName), application{std::move(application)}
        {}

        [[nodiscard]] auto getApplication() const noexcept -> const std::string &
        [[nodiscard]] auto getApplication() const noexcept -> const ApplicationName &
        {
            return application;
        }

      private:
        ApplicationName application;
    };

    /// Requests to change the language.
    class APMChangeLanguage : public APMMessage
    class LanguageChangeRequest : public Message
    {
        utils::Lang language;

      public:
        APMChangeLanguage(const std::string &senderName, utils::Lang language)
            : APMMessage(MessageType::APMChangeLanguage, senderName), language{language}
        LanguageChangeRequest(const ApplicationName &senderName, utils::Lang language)
            : Message(MessageType::APMChangeLanguage, senderName), language{language}
        {}

        [[nodiscard]] auto getLanguage() const noexcept -> utils::Lang
        {
            return language;
        }

      private:
        utils::Lang language;
    };

    /// Requests the application manager to close.
    class APMClose : public APMMessage
    class ShutdownRequest : public Message
    {
      public:
        APMClose(const std::string &senderName) : APMMessage(MessageType::APMClose, senderName)
        ShutdownRequest(const ApplicationName &senderName) : Message(MessageType::APMClose, senderName)
        {}
    };

    /// Requests application manager to prevent device blocking.
    class APMPreventBlocking : public APMMessage
    class PreventBlockingRequest : public Message
    {
      public:
        APMPreventBlocking(const std::string &senderName) : APMMessage(MessageType::APMPreventBlocking, senderName)
        PreventBlockingRequest(const ApplicationName &senderName) : Message(MessageType::APMPreventBlocking, senderName)
        {}
    };

    /// Requests the application manager to enter power save mode.
    class APMInitPowerSaveMode : public APMMessage
    class PowerSaveModeInitRequest : public Message
    {
      public:
        APMInitPowerSaveMode(const std::string &senderName) : APMMessage(MessageType::APMInitPowerSaveMode, senderName)
        PowerSaveModeInitRequest(const ApplicationName &senderName)
            : Message(MessageType::APMInitPowerSaveMode, senderName)
        {}
    };

    /// Requests the application manager to check the status of the application.
    class APMCheckApp : public APMMessage
    class ApplicationStatusRequest : public Message
    {
      public:
        APMCheckApp(const std::string &senderName, std::string applicationName)
            : APMMessage(MessageType::APMCheckAppRunning, senderName),
        ApplicationStatusRequest(const ApplicationName &senderName, ApplicationName applicationName)
            : Message(MessageType::APMCheckAppRunning, senderName),
              checkAppName(std::move(applicationName)), isRunning{false}
        {}

        std::string checkAppName;
        ApplicationName checkAppName;
        bool isRunning;
    };

    struct Action
    {
        std::string targetApplication;
        std::string targetWindow;
        std::unique_ptr<gui::SwitchData> data;
    };

    class APMAction : public APMMessage
    class ActionRequest : public Message
    {
      public:
        APMAction(const std::string &senderName, Action &&_action)
            : APMMessage{MessageType::APMAction, senderName}, action{std::move(_action)}
        ActionRequest(const ApplicationName &senderName, actions::ActionId _actionId, actions::ActionParamsPtr &&_data)
            : Message{MessageType::APMAction, senderName}, actionId{_actionId}, data{std::move(_data)}
        {}

        auto getAction() noexcept -> Action &
        [[nodiscard]] auto getAction() const noexcept -> actions::ActionId
        {
            return action;
            return actionId;
        }

        [[nodiscard]] auto getData() noexcept -> actions::ActionParamsPtr &
        {
            return data;
        }

      private:
        Action action;
        actions::ActionId actionId;
        actions::ActionParamsPtr data;
    };
} // namespace app::manager

A module-services/service-appmgr/model/ApplicationHandle.cpp => module-services/service-appmgr/model/ApplicationHandle.cpp +69 -0
@@ 0,0 1,69 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationHandle.hpp"

namespace app::manager
{
    ApplicationHandle::ApplicationHandle(std::unique_ptr<app::ApplicationLauncher> &&_launcher)
        : launcher{std::move(_launcher)}
    {}

    auto ApplicationHandle::manifest() const -> const ApplicationManifest &
    {
        return launcher ? launcher->getManifest() : InvalidManifest;
    }

    auto ApplicationHandle::name() const -> ApplicationName
    {
        return launcher ? launcher->getName() : InvalidAppName.data();
    }

    auto ApplicationHandle::state() const noexcept -> State
    {
        return launcher && launcher->handle ? launcher->handle->getState() : State::NONE;
    }

    void ApplicationHandle::setState(State state) noexcept
    {
        if (launcher && launcher->handle) {
            launcher->handle->setState(state);
        }
    }

    auto ApplicationHandle::preventsBlocking() const noexcept -> bool
    {
        return launcher ? launcher->isBlocking() : false;
    }

    auto ApplicationHandle::closeable() const noexcept -> bool
    {
        return launcher ? launcher->isCloseable() : false;
    }

    auto ApplicationHandle::started() const noexcept -> bool
    {
        const auto appState = state();
        return appState == State::ACTIVE_FORGROUND || appState == State::ACTIVE_BACKGROUND ||
               appState == State::ACTIVATING;
    }

    auto ApplicationHandle::handles(actions::ActionId action) const noexcept -> bool
    {
        return manifest().contains(action);
    }

    void ApplicationHandle::run(sys::Service *caller)
    {
        if (launcher) {
            launcher->run(caller);
        }
    }

    void ApplicationHandle::runInBackground(sys::Service *caller)
    {
        if (launcher) {
            launcher->runBackground(caller);
        }
    }
} // namespace app::manager

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

#pragma once

#include <string>
#include <memory>

#include "Application.hpp"
#include "ApplicationLauncher.hpp"

namespace app
{
    class ApplicationLauncher;
} // namespace app

namespace app::manager
{
    class ApplicationHandle
    {
      public:
        static inline constexpr std::string_view InvalidAppName{"NONE"};
        static inline const ApplicationManifest InvalidManifest;

        using State = app::Application::State;

        explicit ApplicationHandle(std::unique_ptr<app::ApplicationLauncher> &&_launcher);

        void setState(State state) noexcept;
        void run(sys::Service *caller);
        void runInBackground(sys::Service *caller);

        auto name() const -> ApplicationName;
        auto manifest() const -> const ApplicationManifest &;
        auto state() const noexcept -> State;
        auto preventsBlocking() const noexcept -> bool;
        auto closeable() const noexcept -> bool;
        auto started() const noexcept -> bool;
        auto handles(actions::ActionId action) const noexcept -> bool;

        std::unique_ptr<app::ApplicationLauncher> launcher; // Handle to the application's start function.
        std::unique_ptr<gui::SwitchData> switchData;
        std::string switchWindow;
        bool blockClosing =
            false; //< Informs the application manager that this application mustn't be closed temporarily.
        //< This flag is used to prevent application closing when application is closeable and there is
        //< incoming call. This flag is also used when closeable application is on front and there is a
        //< timeout to block the application.
    };
} // namespace app::manager

R module-services/service-appmgr/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +98 -130
@@ 1,7 1,7 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-appmgr/ApplicationManager.hpp"
#include "ApplicationManager.hpp"

#include <utility>   // for move
#include <algorithm> // for find_if


@@ 18,14 18,14 @@
#include <service-eink/ServiceEink.hpp>    // for ServiceEink
#include <service-eink/Common.hpp>
#include <service-gui/Common.hpp>
#include "service-gui/ServiceGUI.hpp"      // for ServiceGUI
#include "log/log.hpp"                     // for LOG_INFO, LOG_ERROR, LOG_WARN, LOG_DEBUG, LOG_FATAL
#include "Common.hpp"                      // for ShowMode, ShowMode::GUI_SHOW_INIT
#include "service-gui/ServiceGUI.hpp" // for ServiceGUI
#include "log/log.hpp"                // for LOG_INFO, LOG_ERROR, LOG_WARN, LOG_DEBUG, LOG_FATAL
#include "Common.hpp"                 // for ShowMode, ShowMode::GUI_SHOW_INIT
#include "Common/Common.hpp" // for SettingsLanguage, SettingsLanguage::ENGLISH, SettingsLanguage::GERMAN, SettingsLanguage::POLISH, SettingsLanguage::SPANISH
#include "Service/Bus.hpp"   // for Bus
#include "SystemManager/SystemManager.hpp"        // for SystemManager
#include "i18/i18.hpp"                            // for Lang, Lang::En, Lang::De, Lang::Pl, Lang::Sp, i18, localize
#include "service-appmgr/messages/APMMessage.hpp" // for APMCheckApp, APMSwitch, APMRegister, APMConfirmClose, APMConfirmSwitch, Action, APMAction, APMChangeLanguage, APMSwitchPrevApp, APMDelayedClose, APMClose, APMInitPowerSaveMode, APMPreventBlocking
#include "SystemManager/SystemManager.hpp"     // for SystemManager
#include "i18/i18.hpp"                         // for Lang, Lang::En, Lang::De, Lang::Pl, Lang::Sp, i18, localize
#include "service-appmgr/messages/Message.hpp" // for APMCheckApp, APMSwitch, APMRegister, APMConfirmClose, APMConfirmSwitch, Action, APMAction, APMChangeLanguage, APMSwitchPrevApp, APMDelayedClose, APMClose, APMInitPowerSaveMode, APMPreventBlocking

// Auto phone lock disabled for now till the times when it's debugged
// #define AUTO_PHONE_LOCK_ENABLED


@@ 47,9 47,8 @@ namespace app::manager
                return utils::Lang::De;
            case SettingsLanguage::SPANISH:
                return utils::Lang::Sp;
            default:
                return utils::Lang::En;
            }
            return utils::Lang::En;
        }

        SettingsLanguage toSettingsLanguage(utils::Lang language)


@@ 63,78 62,21 @@ namespace app::manager
                return SettingsLanguage::GERMAN;
            case utils::Lang::Sp:
                return SettingsLanguage::SPANISH;
            default:
                return SettingsLanguage::ENGLISH;
            }
            return SettingsLanguage::ENGLISH;
        }
    } // namespace

    ApplicationHandle::ApplicationHandle(std::unique_ptr<app::ApplicationLauncher> &&_launcher)
        : launcher{std::move(_launcher)}
    {}

    auto ApplicationHandle::name() const -> Name
    {
        return launcher ? launcher->getName() : InvalidAppName.data();
    }

    auto ApplicationHandle::state() const noexcept -> State
    {
        return launcher && launcher->handle ? launcher->handle->getState() : State::NONE;
    }

    void ApplicationHandle::setState(State state) noexcept
    {
        if (launcher && launcher->handle) {
            launcher->handle->setState(state);
        }
    }

    auto ApplicationHandle::preventsBlocking() const noexcept -> bool
    {
        return launcher ? launcher->isBlocking() : false;
    }

    auto ApplicationHandle::closeable() const noexcept -> bool
    {
        return launcher ? launcher->isCloseable() : false;
    }

    auto ApplicationHandle::started() const noexcept -> bool
    {
        const auto appState = state();
        return appState == State::ACTIVE_FORGROUND || appState == State::ACTIVE_BACKGROUND ||
               appState == State::ACTIVATING;
    }

    void ApplicationHandle::run(sys::Service *caller)
    {
        if (launcher) {
            launcher->run(caller);
        }
    }

    void ApplicationHandle::runInBackground(sys::Service *caller)
    {
        if (launcher) {
            launcher->runBackground(caller);
        }
    }

    ApplicationManagerBase::ApplicationManagerBase(std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers)
    {
        std::vector<std::unique_ptr<app::ApplicationLauncher>> container = std::move(launchers);
        for (auto &&launcher : container) {
            applications.push_back(std::make_unique<ApplicationHandle>(std::move(launcher)));
        }
    }
        : applications{std::move(launchers)}
    {}

    void ApplicationManagerBase::setState(State _state) noexcept
    {
        state = _state;
    }

    void ApplicationManagerBase::pushApplication(const ApplicationHandle::Name &name)
    void ApplicationManagerBase::pushApplication(const ApplicationName &name)
    {
        stack.push_front(name);
    }


@@ 179,20 121,14 @@ namespace app::manager
        return getApplication(stack[1]);
    }

    auto ApplicationManagerBase::getApplication(const ApplicationHandle::Name &name) const noexcept
        -> ApplicationHandle *
    auto ApplicationManagerBase::getApplication(const ApplicationName &name) const noexcept -> ApplicationHandle *
    {
        auto it = std::find_if(
            applications.begin(), applications.end(), [&name](const auto &app) { return app->name() == name; });
        if (it == applications.end()) {
            return nullptr;
        }
        return it->get();
        return applications.findByName(name);
    }

    ApplicationManager::ApplicationManager(const std::string &serviceName,
    ApplicationManager::ApplicationManager(const ApplicationName &serviceName,
                                           std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers,
                                           const ApplicationHandle::Name &_rootApplicationName)
                                           const ApplicationName &_rootApplicationName)
        : Service{serviceName}, ApplicationManagerBase(std::move(launchers)), rootApplicationName{_rootApplicationName},
          blockingTimer{std::make_unique<sys::Timer>(
              "BlockTimer", this, std::numeric_limits<sys::ms>::max(), sys::Timer::Type::SingleShot)}


@@ 238,7 174,7 @@ namespace app::manager

    void ApplicationManager::startBackgroundApplications()
    {
        for (const auto &name : std::vector<ApplicationHandle::Name>{app::name_call, app::special_input}) {
        for (const auto &name : std::vector<ApplicationName>{app::name_call, app::special_input}) {
            if (auto app = getApplication(name); app != nullptr) {
                app->runInBackground(this);
            }


@@ 260,62 196,62 @@ namespace app::manager

    void ApplicationManager::registerMessageHandlers()
    {
        connect(typeid(APMCheckApp), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg       = static_cast<APMCheckApp *>(request);
            auto ret       = std::make_shared<APMCheckApp>(GetName(), msg->checkAppName);
        connect(typeid(ApplicationStatusRequest), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg       = static_cast<ApplicationStatusRequest *>(request);
            auto ret       = std::make_shared<ApplicationStatusRequest>(GetName(), msg->checkAppName);
            ret->isRunning = getApplication(msg->checkAppName) != nullptr;
            return ret;
        });
        connect(typeid(APMInitPowerSaveMode), [this](sys::DataMessage *, sys::ResponseMessage *) {
        connect(typeid(PowerSaveModeInitRequest), [this](sys::DataMessage *, sys::ResponseMessage *) {
            handlePowerSavingModeInit();
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMPreventBlocking), [this](sys::DataMessage *, sys::ResponseMessage *) {
        connect(typeid(PreventBlockingRequest), [this](sys::DataMessage *, sys::ResponseMessage *) {
            blockingTimer->reload();
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMSwitch), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMSwitch *>(request);
        connect(typeid(SwitchRequest), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<SwitchRequest *>(request);
            handleSwitchApplication(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMSwitchPrevApp), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMSwitchPrevApp *>(request);
        connect(typeid(SwitchBackRequest), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<SwitchBackRequest *>(request);
            handleSwitchBack(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMConfirmSwitch), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMConfirmSwitch *>(request);
        connect(typeid(SwitchConfirmation), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<SwitchConfirmation *>(request);
            handleSwitchConfirmation(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMConfirmClose), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMConfirmClose *>(request);
        connect(typeid(CloseConfirmation), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<CloseConfirmation *>(request);
            handleCloseConfirmation(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMDelayedClose), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMDelayedClose *>(request);
        connect(typeid(ApplicationCloseRequest), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<ApplicationCloseRequest *>(request);
            closeService(msg->getApplication());
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMRegister), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMRegister *>(request);
            handleRegisterApplication(msg);
        connect(typeid(ApplicationInitialisation), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<ApplicationInitialisation *>(request);
            handleInitApplication(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMChangeLanguage), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<APMChangeLanguage *>(request);
        connect(typeid(LanguageChangeRequest), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto msg = static_cast<LanguageChangeRequest *>(request);
            handleLanguageChange(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMClose), [this](sys::DataMessage *, sys::ResponseMessage *) {
        connect(typeid(ShutdownRequest), [this](sys::DataMessage *, sys::ResponseMessage *) {
            closeApplications();
            closeServices();
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(APMAction), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto actionMsg = static_cast<APMAction *>(request);
        connect(typeid(ActionRequest), [this](sys::DataMessage *request, sys::ResponseMessage *) {
            auto actionMsg = static_cast<ActionRequest *>(request);
            handleAction(actionMsg);
            return std::make_shared<sys::ResponseMessage>();
        });


@@ 391,7 327,7 @@ namespace app::manager
        return true;
    }

    auto ApplicationManager::handleSwitchApplication(APMSwitch *msg) -> bool
    auto ApplicationManager::handleSwitchApplication(SwitchRequest *msg) -> bool
    {
        auto app = getApplication(msg->getName());
        if (app == nullptr) {


@@ 445,27 381,53 @@ namespace app::manager
        }
    }

    auto ApplicationManager::handleAction(APMAction *actionMsg) -> bool
    auto ApplicationManager::handleAction(ActionRequest *actionMsg) -> bool
    {
        auto &action         = actionMsg->getAction();
        const auto targetApp = getApplication(action.targetApplication);
        if (targetApp == nullptr) {
            LOG_ERROR("Failed to switch to %s application: No such application.", action.targetApplication.c_str());
        auto action = actionMsg->getAction();
        if (action == actions::Launch) {
            auto params = static_cast<ApplicationLaunchData *>(actionMsg->getData().get());
            return handleLaunchAction(params);
        }

        const auto actionHandlers = applications.findByAction(action);
        if (actionHandlers.empty()) {
            LOG_ERROR("No applications handling action #%d.", action);
            return false;
        }
        if (actionHandlers.size() > 1) {
            LOG_FATAL("Choosing amongst multiple action handler applications is not yet implemented.");
            return false;
        }

        if (targetApp->state() == app::Application::State::ACTIVE_FORGROUND) {
            // If the app is already focused, then switch window.
            auto msg = std::make_shared<app::AppSwitchWindowMessage>(
                action.targetWindow, std::string{}, std::move(action.data), gui::ShowMode::GUI_SHOW_INIT);
            return sys::Bus::SendUnicast(msg, targetApp->name(), this);
        auto &actionData     = actionMsg->getData();
        const auto targetApp = actionHandlers.front();
        if (targetApp->state() != ApplicationHandle::State::ACTIVE_FORGROUND) {
            pendingAction = std::make_tuple(targetApp->name(), action, std::move(actionData));

            SwitchRequest switchRequest(actionMsg->getSenderName(),
                                        targetApp->name(),
                                        targetApp->switchWindow,
                                        std::move(targetApp->switchData));
            return handleSwitchApplication(&switchRequest);
        }
        APMSwitch switchRequest(
            actionMsg->getSenderName(), targetApp->name(), action.targetWindow, std::move(action.data));

        app::Application::requestAction(this, targetApp->name(), action, std::move(actionData));
        return true;
    }

    auto ApplicationManager::handleLaunchAction(ApplicationLaunchData *launchParams) -> bool
    {
        auto targetApp = getApplication(launchParams->getTargetApplicationName());
        if (targetApp == nullptr || !targetApp->handles(actions::Launch)) {
            return false;
        }

        SwitchRequest switchRequest(
            ServiceName, targetApp->name(), targetApp->switchWindow, std::move(targetApp->switchData));
        return handleSwitchApplication(&switchRequest);
    }

    auto ApplicationManager::handleSwitchBack(APMSwitchPrevApp *msg) -> bool
    auto ApplicationManager::handleSwitchBack(SwitchBackRequest *msg) -> bool
    {
        auto previousApp = getPreviousApplication();
        if (previousApp == nullptr) {


@@ 506,7 468,7 @@ namespace app::manager
        previousApp.switchWindow = std::move(targetWindow);
    }

    auto ApplicationManager::handleRegisterApplication(APMRegister *msg) -> bool
    auto ApplicationManager::handleInitApplication(ApplicationInitialisation *msg) -> bool
    {
        auto app = getApplication(msg->getSenderName());
        if (app == nullptr) {


@@ 514,21 476,21 @@ namespace app::manager
            return false;
        }

        if (msg->getStatus()) {
            onApplicationRegistered(*app, msg->getStartBackground());
        if (msg->getStatus() == StartupStatus::Success) {
            onApplicationInitialised(*app, msg->isBackgroundApplication());
        }
        else {
            onApplicationRegistrationFailure(*app);
            onApplicationInitFailure(*app);
        }

        auto notification = std::make_shared<APMCheckApp>(GetName(), app->name());
        auto notification = std::make_shared<ApplicationStatusRequest>(GetName(), app->name());
        sys::Bus::SendMulticast(notification, sys::BusChannels::AppManagerNotifications, this);
        return true;
    }

    void ApplicationManager::onApplicationRegistered(ApplicationHandle &app, bool startInBackground)
    void ApplicationManager::onApplicationInitialised(ApplicationHandle &app, StartInBackground startInBackground)
    {
        LOG_DEBUG("Application %s registered successfully.", app.name().c_str());
        LOG_DEBUG("Application %s initialised successfully.", app.name().c_str());

        auto launchingApp = getLaunchingApplication();
        if (launchingApp == nullptr || launchingApp->name() != app.name()) {


@@ 548,13 510,13 @@ namespace app::manager
        }
    }

    void ApplicationManager::onApplicationRegistrationFailure(ApplicationHandle &app)
    void ApplicationManager::onApplicationInitFailure(ApplicationHandle &app)
    {
        LOG_ERROR("Failed to register %s: Application initialisation error.", app.name().c_str());
        LOG_ERROR("Failed to initialise %s: Application internal error.", app.name().c_str());
        Controller::switchBack(this);
    }

    auto ApplicationManager::handleLanguageChange(app::manager::APMChangeLanguage *msg) -> bool
    auto ApplicationManager::handleLanguageChange(app::manager::LanguageChangeRequest *msg) -> bool
    {
        const auto requestedLanguage = toSettingsLanguage(msg->getLanguage());
        if (requestedLanguage == settings.language) {


@@ 583,7 545,7 @@ namespace app::manager
        }
    }

    auto ApplicationManager::handleSwitchConfirmation(APMConfirmSwitch *msg) -> bool
    auto ApplicationManager::handleSwitchConfirmation(SwitchConfirmation *msg) -> bool
    {
        auto senderApp = getApplication(msg->getSenderName());
        if (senderApp == nullptr) {


@@ 602,6 564,12 @@ namespace app::manager
            app.setState(ApplicationHandle::State::ACTIVE_FORGROUND);
            setState(State::Running);
            EventManager::messageSetApplication(this, app.name());

            auto &[appName, action, data] = pendingAction;
            if (appName == app.name()) {
                app::Application::requestAction(this, appName, action, std::move(data));
                pendingAction = std::make_tuple(ApplicationName{}, 0, nullptr);
            }
            return true;
        }
        if (getState() == State::AwaitingLostFocusConfirmation) {


@@ 618,7 586,7 @@ namespace app::manager
        return false;
    }

    auto ApplicationManager::handleCloseConfirmation(APMConfirmClose *msg) -> bool
    auto ApplicationManager::handleCloseConfirmation(CloseConfirmation *msg) -> bool
    {
        auto senderApp = getApplication(msg->getSenderName());
        if (senderApp == nullptr) {

R module-services/service-appmgr/ApplicationManager.hpp => module-services/service-appmgr/model/ApplicationManager.hpp +29 -50
@@ 11,7 11,7 @@

#include "Application.hpp"         // for Application, Application::State
#include "ApplicationLauncher.hpp" // for ApplicationLauncher
#include "messages/APMMessage.hpp"
#include "module-services/service-appmgr/messages/Message.hpp"
#include "Service/Common.hpp"  // for ReturnCodes, ServicePowerMode
#include "Service/Message.hpp" // for Message_t, DataMessage (ptr only), ResponseMessage (ptr only)
#include "Service/Service.hpp" // for Service


@@ 19,6 19,9 @@
#include "SettingsRecord.hpp"  // for SettingsRecord
#include "SwitchData.hpp"      // for SwitchData

#include "ApplicationHandle.hpp"
#include "ApplicationsRegistry.hpp"

namespace app
{
    class ApplicationLauncher;


@@ 32,45 35,13 @@ namespace app
        class APMSwitch;
        class APMSwitchPrevApp;
    } // namespace manager
}
} // namespace app

namespace app::manager
{
    class ApplicationHandle
    {
      public:
        static inline constexpr std::string_view InvalidAppName{"NONE"};

        using State = app::Application::State;
        using Name  = std::string;

        explicit ApplicationHandle(std::unique_ptr<app::ApplicationLauncher> &&_launcher);

        void setState(State state) noexcept;
        void run(sys::Service *caller);
        void runInBackground(sys::Service *caller);

        auto name() const -> Name;
        auto state() const noexcept -> State;
        auto preventsBlocking() const noexcept -> bool;
        auto closeable() const noexcept -> bool;
        auto started() const noexcept -> bool;

        std::unique_ptr<app::ApplicationLauncher> launcher; // Handle to the application's start function.
        std::unique_ptr<gui::SwitchData> switchData;
        std::string switchWindow;
        bool blockClosing =
            false; //< Informs the application manager that this application mustn't be closed temporarily.
                   // This flag is used to prevent application closing when application is closeable and there is
                   // incoming call. This flag is also used when closeable application is on front and there is a
                   // timeout to block the application.
    };

    class ApplicationManagerBase
    {
      public:
        using ApplicationsContainer = std::vector<std::unique_ptr<ApplicationHandle>>;
        using ApplicationsStack     = std::deque<ApplicationHandle::Name>;
        enum class State
        {
            Running,


@@ 82,17 53,17 @@ namespace app::manager
        explicit ApplicationManagerBase(std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers);
        virtual ~ApplicationManagerBase() = default;

        void pushApplication(const ApplicationHandle::Name &name);
        void pushApplication(const ApplicationName &name);
        void popApplication();
        void clearStack();

        auto getFocusedApplication() const noexcept -> ApplicationHandle *;
        auto getLaunchingApplication() const noexcept -> ApplicationHandle *;
        auto getPreviousApplication() const noexcept -> ApplicationHandle *;
        auto getApplication(const ApplicationHandle::Name &name) const noexcept -> ApplicationHandle *;
        auto getApplication(const ApplicationName &name) const noexcept -> ApplicationHandle *;
        auto getApplications() const noexcept -> const ApplicationsContainer &
        {
            return applications;
            return applications.getAll();
        }

        void setState(State _state) noexcept;


@@ 101,9 72,13 @@ namespace app::manager
            return state;
        }

      protected:
        ApplicationsRegistry applications;

      private:
        using ApplicationsStack = std::deque<ApplicationName>;

        State state = State::Running;
        ApplicationsContainer applications;
        ApplicationsStack stack;
    };



@@ 112,9 87,9 @@ namespace app::manager
      public:
        static inline const std::string ServiceName = "ApplicationManager";

        ApplicationManager(const std::string &serviceName,
        ApplicationManager(const ApplicationName &serviceName,
                           std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers,
                           const ApplicationHandle::Name &_rootApplicationName);
                           const ApplicationName &_rootApplicationName);

        auto InitHandler() -> sys::ReturnCodes override;
        auto DeinitHandler() -> sys::ReturnCodes override;


@@ 133,13 108,14 @@ namespace app::manager

        // Message handlers
        void registerMessageHandlers();
        auto handleAction(APMAction *actionMsg) -> bool;
        auto handleSwitchApplication(APMSwitch *msg) -> bool;
        auto handleCloseConfirmation(APMConfirmClose *msg) -> bool;
        auto handleSwitchConfirmation(APMConfirmSwitch *msg) -> bool;
        auto handleSwitchBack(APMSwitchPrevApp *msg) -> bool;
        auto handleRegisterApplication(APMRegister *msg) -> bool;
        auto handleLanguageChange(APMChangeLanguage *msg) -> bool;
        auto handleAction(ActionRequest *actionMsg) -> bool;
        auto handleLaunchAction(ApplicationLaunchData *launchParams) -> bool;
        auto handleSwitchApplication(SwitchRequest *msg) -> bool;
        auto handleCloseConfirmation(CloseConfirmation *msg) -> bool;
        auto handleSwitchConfirmation(SwitchConfirmation *msg) -> bool;
        auto handleSwitchBack(SwitchBackRequest *msg) -> bool;
        auto handleInitApplication(ApplicationInitialisation *msg) -> bool;
        auto handleLanguageChange(LanguageChangeRequest *msg) -> bool;
        auto handlePowerSavingModeInit() -> bool;

        void requestApplicationClose(ApplicationHandle &app, bool isCloseable);


@@ 149,17 125,20 @@ namespace app::manager
        void onApplicationSwitchToPrev(ApplicationHandle &previousApp,
                                       std::unique_ptr<gui::SwitchData> &&data,
                                       std::string targetWindow = {});
        void onApplicationRegistered(ApplicationHandle &app, bool startInBackground);
        void onApplicationRegistrationFailure(ApplicationHandle &app);
        void onApplicationInitialised(ApplicationHandle &app, StartInBackground startInBackground);
        void onApplicationInitFailure(ApplicationHandle &app);
        auto onSwitchConfirmed(ApplicationHandle &app) -> bool;
        auto onCloseConfirmed(ApplicationHandle &app) -> bool;
        void onPhoneLocked();

        ApplicationHandle::Name rootApplicationName;
        ApplicationName rootApplicationName;
        SettingsRecord settings;
        std::unique_ptr<sys::Timer> blockingTimer; //< timer to count time from last user's activity. If it reaches time
                                                   // defined in settings database application
                                                   // manager is sending signal to power manager and changing window to
                                                   // the desktop window in the blocked state.

        // Temporary solution - to be replaced with ActionsMiddleware.
        std::tuple<ApplicationName, actions::ActionId, actions::ActionParamsPtr> pendingAction;
    };
} // namespace app::manager

A module-services/service-appmgr/model/ApplicationsRegistry.cpp => module-services/service-appmgr/model/ApplicationsRegistry.cpp +41 -0
@@ 0,0 1,41 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationsRegistry.hpp"

namespace app::manager
{
    ApplicationsRegistry::ApplicationsRegistry(std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers)
    {
        std::vector<std::unique_ptr<app::ApplicationLauncher>> container = std::move(launchers);
        for (auto &&launcher : container) {
            applications.push_back(std::make_unique<ApplicationHandle>(std::move(launcher)));
        }
    }

    auto ApplicationsRegistry::getAll() const noexcept -> const ApplicationsContainer &
    {
        return applications;
    }

    auto ApplicationsRegistry::findByName(const ApplicationName &name) const -> ApplicationHandle *
    {
        auto it = std::find_if(
            applications.begin(), applications.end(), [&name](const auto &app) { return app->name() == name; });
        if (it == applications.end()) {
            return nullptr;
        }
        return it->get();
    }

    auto ApplicationsRegistry::findByAction(actions::ActionId action) const -> std::vector<ApplicationHandle *>
    {
        std::vector<ApplicationHandle *> actionHandlers;
        for (const auto &app : applications) {
            if (app->handles(action)) {
                actionHandlers.push_back(app.get());
            }
        }
        return actionHandlers;
    }
} // namespace app::manager

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

#pragma once

#include <vector>
#include <memory>

#include "ApplicationHandle.hpp"

namespace app::manager
{
    using ApplicationsContainer = std::vector<std::unique_ptr<ApplicationHandle>>;

    class ApplicationsRegistry
    {
      public:
        explicit ApplicationsRegistry(std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers);

        [[nodiscard]] auto getAll() const noexcept -> const ApplicationsContainer &;
        [[nodiscard]] auto findByName(const ApplicationName &name) const -> ApplicationHandle *;
        [[nodiscard]] auto findByAction(actions::ActionId action) const -> std::vector<ApplicationHandle *>;

      private:
        ApplicationsContainer applications;
    };
} // namespace app::manager

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +4 -5
@@ 662,8 662,7 @@ sys::Message_t ServiceCellular::DataReceivedHandler(sys::DataMessage *msgl, sys:
                    }
                    else {
                        responseMsg = std::make_shared<CellularResponseMessage>(false);

                        app::manager::Controller::sendAction(this, simUnlockError(resp));
                        // TODO: Sim unlock error.
                    }
                }
                else {


@@ 671,7 670,7 @@ sys::Message_t ServiceCellular::DataReceivedHandler(sys::DataMessage *msgl, sys:
                    responseMsg = std::make_shared<CellularResponseMessage>(false);
                    at::Result fatalError;
                    fatalError.code = at::Result::Code::ERROR;
                    app::manager::Controller::sendAction(this, simUnlockError(fatalError));
                    // TODO: Sim unlock error.
                }
            }
        }


@@ 1033,10 1032,10 @@ std::optional<std::shared_ptr<CellularMessage>> ServiceCellular::identifyNotific

            Store::GSM::get()->sim = Store::GSM::get()->selected;
            if (str.find("SIM PIN", ret) != std::string::npos) {
                app::manager::Controller::sendAction(this, requestPin(3));
                // TODO: Request pin.
            }
            else if (str.find("READY", ret) != std::string::npos) {
                app::manager::Controller::sendAction(this, simUnlocked());
                // TODO: Sim unlocked.
            }
            else {
                LOG_WARN("Not supported: %s", logStr.c_str());

M module-services/service-cellular/ServiceCellular.hpp => module-services/service-cellular/ServiceCellular.hpp +0 -20
@@ 15,7 15,6 @@
#include <vector>   // for vector

#include "CellularCall.hpp" // for CellularCall
#include <service-appmgr/messages/APMMessage.hpp>
#include "USSD.hpp"                     // for State, State::none
#include "SMSRecord.hpp"                // for SMSRecord
#include "messages/CellularMessage.hpp" // for CellularUSSDMessage, CellularUSSDMessage::RequestType


@@ 53,25 52,6 @@ class ServiceCellular : public sys::Service
    sys::ReturnCodes DeinitHandler() override;
    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

    app::manager::Action simUnlockError(at::Result result)
    {
        return {"MainWindow", "PinLockWindow", nullptr};
    }
    app::manager::Action requestPuk(unsigned int attemptsLeft)
    {
        return {"MainWindow", "PinLockWindow", nullptr};
    }

    app::manager::Action requestPin(unsigned int attemptsLeft)
    {
        return {"MainWindow", "PinLockWindow", nullptr};
    }

    app::manager::Action simUnlocked()
    {
        return {"MainWindow", "PinLockWindow", nullptr};
    }

    /** Register message handlers.
     */
    void registerMessageHandlers();

M source/MessageType.hpp => source/MessageType.hpp +3 -1
@@ 127,6 127,7 @@ enum class MessageType
    APMConfirmClose,    ///< Sent by application to confirm completion of the close procedure
    APMRegister,        ///< when application finishes initHandler it is sending this messag to inform whether init was
                        ///< successful or not.
    APMInit,            ///< Send by application to confirm completion its initialisation process
    APMDelayedClose,    ///< this message is sent internally from and to application manager to close specified
                        ///< application.
    APMChangeLanguage,  ///< this message is sent from any application to inform application manager that it should send


@@ 140,7 141,8 @@ enum class MessageType
    // keyboard messages
    KBDKeyEvent,

    AppMessage, //< generic application message
    AppMessage, ///< generic application message
    AppAction,  ///< application action request.
    AppSwitch,  ///< application receives this message from application manager. It a signal to gain or loose focus.
    AppSwitchWindow, ///< This is internal message transmitted within application to change window. Additional command
                     ///< and data are transmitted with it.

M source/main.cpp => source/main.cpp +1 -1
@@ 20,7 20,7 @@
#include <application-calculator/ApplicationCalculator.hpp>

// services
#include <service-appmgr/ApplicationManager.hpp>
#include <module-services/service-appmgr/model/ApplicationManager.hpp>
#include <service-audio/ServiceAudio.hpp>
#include <service-bluetooth/ServiceBluetooth.hpp>
#include <service-db/ServiceDB.hpp>