M module-apps/ApplicationLauncher.hpp => module-apps/ApplicationLauncher.hpp +3 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 79,14 79,14 @@ namespace app
{
parent = (caller == nullptr ? "" : caller->GetName());
handle = std::make_shared<T>(name, parent);
- return sys::SystemManager::CreateService(handle, caller);
+ return sys::SystemManager::RunService(handle, caller);
}
bool runBackground(sys::Service *caller) override
{
parent = (caller == nullptr ? "" : caller->GetName());
handle = std::make_shared<T>(name, parent, true);
- return sys::SystemManager::CreateService(handle, caller);
+ return sys::SystemManager::RunService(handle, caller);
}
};
M module-apps/application-settings-new/windows/AddDeviceWindow.cpp => module-apps/application-settings-new/windows/AddDeviceWindow.cpp +5 -0
@@ 9,6 9,11 @@
#include <i18n/i18n.hpp>
#include <utility>
+extern "C"
+{
+#include <module-bluetooth/lib/btstack/src/btstack_util.h>
+}
+
namespace gui
{
M module-apps/application-settings/windows/BtScanWindow.cpp => module-apps/application-settings/windows/BtScanWindow.cpp +5 -0
@@ 16,6 16,11 @@
#include <Style.hpp>
+extern "C"
+{
+#include <module-bluetooth/lib/btstack/src/btstack_util.h>
+}
+
namespace gui
{
M module-db/Database/Database.cpp => module-db/Database/Database.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Database.hpp"
@@ 70,7 70,7 @@ Database::Database(const char *name)
{
LOG_INFO("Creating database: %s", dbName.c_str());
if (const auto rc = sqlite3_open(name, &dbConnection); rc != SQLITE_OK) {
- LOG_ERROR("SQLITE INITIALIZATION ERROR! rc=%d dbName=%s", rc, name);
+ LOG_ERROR("SQLITE INITIALIZATION ERROR! rc=%d ( %s ) dbName=%s", rc, sqlite3_errstr(rc), name);
throw DatabaseInitialisationError{"Failed to initialize the sqlite db"};
}
M module-services/service-antenna/ServiceAntenna.cpp => module-services/service-antenna/ServiceAntenna.cpp +4 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "service-antenna/ServiceAntenna.hpp"
@@ 25,8 25,6 @@
#include <string>
#include <vector>
-const char *ServiceAntenna::serviceName = "ServiceAntenna";
-
namespace antenna
{
const char *c_str(antenna::State state)
@@ 55,9 53,9 @@ namespace antenna
}
} // namespace antenna
-ServiceAntenna::ServiceAntenna() : sys::Service(serviceName)
+ServiceAntenna::ServiceAntenna() : sys::Service(service::name::antenna)
{
- LOG_INFO("[%s] Initializing", serviceName);
+ LOG_INFO("[%s] Initializing", service::name::antenna);
timer = std::make_unique<sys::Timer>("Antena", this, 5000, sys::Timer::Type::Periodic);
timer->connect([&](sys::Timer &) {
@@ 80,7 78,7 @@ ServiceAntenna::ServiceAntenna() : sys::Service(serviceName)
ServiceAntenna::~ServiceAntenna()
{
- LOG_INFO("[%s] Cleaning resources", serviceName);
+ LOG_INFO("[%s] Cleaning resources", service::name::antenna);
}
// Invoked upon receiving data message
M module-services/service-antenna/api/AntennaServiceAPI.cpp => module-services/service-antenna/api/AntennaServiceAPI.cpp +3 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <service-antenna/AntennaServiceAPI.hpp>
@@ 29,7 29,7 @@ namespace AntennaServiceAPI
bool LockRequest(sys::Service *serv, antenna::lockState request)
{
auto msg = std::make_shared<AntennaLockRequestMessage>(MessageType::AntennaLockService, request);
- auto ret = serv->bus.sendUnicast(msg, ServiceAntenna::serviceName, 5000);
+ auto ret = serv->bus.sendUnicast(msg, service::name::antenna, 5000);
if (ret.first == sys::ReturnCodes::Success) {
return true;
@@ 40,7 40,7 @@ namespace AntennaServiceAPI
bool GetLockState(sys::Service *serv, antenna::lockState &response)
{
auto msg = std::make_shared<AntennaLockRequestMessage>(MessageType::AntennaGetLockState);
- auto ret = serv->bus.sendUnicast(msg, ServiceAntenna::serviceName, 5000);
+ auto ret = serv->bus.sendUnicast(msg, service::name::antenna, 5000);
if (ret.first == sys::ReturnCodes::Success) {
auto responseMsg = dynamic_cast<AntennaLockRequestResponse *>(ret.second.get());
if (responseMsg != nullptr) {
M module-services/service-antenna/service-antenna/ServiceAntenna.hpp => module-services/service-antenna/service-antenna/ServiceAntenna.hpp +21 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 10,6 10,7 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Worker.hpp>
+#include <service-db/DBServiceName.hpp>
#include <algorithm>
#include <cassert>
@@ 28,6 29,11 @@ namespace utils
} // namespace state
} // namespace utils
+namespace service::name
+{
+ constexpr inline auto antenna = "ServiceAntenna";
+} // namespace service::name
+
namespace antenna
{
enum class State
@@ 76,8 82,6 @@ class ServiceAntenna : public sys::Service
bool suspended = false;
public:
- static const char *serviceName;
-
ServiceAntenna();
~ServiceAntenna();
@@ 102,3 106,17 @@ class ServiceAntenna : public sys::Service
bool csqChangeStateHandler(void);
bool lockedStateHandler(void);
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceAntenna>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::antenna;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +0 -15
@@ 157,7 157,6 @@ namespace app::manager
},
::settings::SettingsScope::Global);
- startSystemServices();
startBackgroundApplications();
if (auto app = getApplication(rootApplicationName); app != nullptr) {
Controller::sendAction(this, actions::Home);
@@ 166,20 165,6 @@ namespace app::manager
return sys::ReturnCodes::Success;
}
- void ApplicationManager::startSystemServices()
- {
- if (bool ret = sys::SystemManager::CreateService(
- std::make_shared<service::gui::ServiceGUI>(service::name::gui, GetName()), this);
- !ret) {
- LOG_ERROR("Failed to initialize GUI service");
- }
- if (bool ret = sys::SystemManager::CreateService(
- std::make_shared<service::eink::ServiceEink>(service::name::eink, GetName()), this);
- !ret) {
- LOG_ERROR("Failed to initialize EInk service");
- }
- }
-
void ApplicationManager::suspendSystemServices()
{
sys::SystemManager::SuspendService(service::name::gui, this);
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +17 -1
@@ 22,7 22,10 @@
#include <string_view>
#include <vector>
+#include <service-db/DBServiceName.hpp>
#include <service-db/Settings.hpp>
+#include <service-gui/Common.hpp>
+#include <service-eink/Common.hpp>
namespace app
{
@@ 100,7 103,6 @@ namespace app::manager
private:
auto startApplication(ApplicationHandle &app) -> bool;
- void startSystemServices();
void startBackgroundApplications();
void rebuildActiveApplications();
void suspendSystemServices();
@@ 158,3 160,17 @@ namespace app::manager
std::string displayLanguage;
};
} // namespace app::manager
+
+namespace sys
+{
+ template <> struct ManifestTraits<app::manager::ApplicationManager>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = app::manager::ApplicationManager::ServiceName;
+ manifest.dependencies = {service::name::db, service::name::gui, service::name::eink};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-audio/AudioServiceAPI.cpp => module-services/service-audio/AudioServiceAPI.cpp +13 -13
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "service-audio/AudioServiceAPI.hpp"
@@ 25,7 25,7 @@ namespace AudioServiceAPI
{
auto msgType = static_cast<int>(msg->type);
LOG_DEBUG("Msg type %d", msgType);
- auto ret = serv->bus.sendUnicast(msg, ServiceAudio::serviceName, sys::BusProxy::defaultTimeout);
+ auto ret = serv->bus.sendUnicast(msg, service::name::audio, sys::BusProxy::defaultTimeout);
if (ret.first == sys::ReturnCodes::Success) {
if (auto resp = std::dynamic_pointer_cast<AudioResponseMessage>(ret.second)) {
LOG_DEBUG("Msg type %d done", msgType);
@@ 42,19 42,19 @@ namespace AudioServiceAPI
bool PlaybackStart(sys::Service *serv, const audio::PlaybackType &playbackType, const std::string &fileName)
{
auto msg = std::make_shared<AudioStartPlaybackRequest>(fileName, playbackType);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool RecordingStart(sys::Service *serv, const std::string &fileName)
{
auto msg = std::make_shared<AudioStartRecorderRequest>(fileName);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool RoutingStart(sys::Service *serv)
{
auto msg = std::make_shared<AudioStartRoutingRequest>();
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool Stop(sys::Service *serv, const std::vector<audio::PlaybackType> &stopVec)
@@ 63,43 63,43 @@ namespace AudioServiceAPI
return true;
}
auto msg = std::make_shared<AudioStopRequest>(stopVec);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool Stop(sys::Service *serv, const audio::Token &token)
{
auto msg = std::make_shared<AudioStopRequest>(token);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool StopAll(sys::Service *serv)
{
auto msg = std::make_shared<AudioStopRequest>();
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool Pause(sys::Service *serv, const audio::Token &token)
{
auto msg = std::make_shared<AudioPauseRequest>(token);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool Resume(sys::Service *serv, const audio::Token &token)
{
auto msg = std::make_shared<AudioResumeRequest>(token);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool SendEvent(sys::Service *serv, std::shared_ptr<audio::Event> evt)
{
auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
bool SendEvent(sys::Service *serv, audio::EventType eType, audio::Event::DeviceState state)
{
auto msg = std::make_shared<AudioEventRequest>(eType, state);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
template <typename T>
@@ 164,7 164,7 @@ namespace AudioServiceAPI
bool KeyPressed(sys::Service *serv, const int step)
{
auto msg = std::make_shared<AudioKeyPressedRequest>(step);
- return serv->bus.sendUnicast(msg, ServiceAudio::serviceName);
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
} // namespace AudioServiceAPI
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +2 -4
@@ 13,12 13,10 @@
#include <type_traits>
-const char *ServiceAudio::serviceName = "ServiceAudio";
-
using namespace audio;
ServiceAudio::ServiceAudio()
- : sys::Service(serviceName, "", 4096 * 2, sys::ServicePriority::Idle),
+ : sys::Service(service::name::audio, "", 4096 * 2, sys::ServicePriority::Idle),
audioMux([this](auto... params) { return this->AudioServicesCallback(params...); }),
settingsProvider(std::make_unique<settings::Settings>(this))
{
@@ 426,7 424,7 @@ void ServiceAudio::HandleNotification(const AudioNotificationMessage::Type &type
}
else {
auto newMsg = std::make_shared<AudioStopRequest>(token);
- bus.sendUnicast(newMsg, ServiceAudio::serviceName);
+ bus.sendUnicast(newMsg, service::name::audio);
}
return;
}
M module-services/service-audio/service-audio/ServiceAudio.hpp => module-services/service-audio/service-audio/ServiceAudio.hpp +21 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 12,6 12,7 @@
#include <Utils.hpp>
#include <service-db/DBServiceAPI.hpp>
+#include <service-db/DBServiceName.hpp>
#include <service-db/QueryMessage.hpp>
#include <functional>
@@ 21,6 22,11 @@ namespace settings
class Settings;
}
+namespace service::name
+{
+ constexpr inline auto audio = "ServiceAudio";
+} // namespace service::name
+
class ServiceAudio : public sys::Service
{
public:
@@ 36,8 42,6 @@ class ServiceAudio : public sys::Service
sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;
- static const char *serviceName;
-
private:
enum class VibrationType
{
@@ 95,3 99,17 @@ class ServiceAudio : public sys::Service
void settingsChanged(const std::string &name, std::string value);
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceAudio>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::audio;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-bluetooth/CMakeLists.txt => module-services/service-bluetooth/CMakeLists.txt +1 -0
@@ 6,6 6,7 @@ set(SOURCES
ServiceBluetooth.cpp
service-bluetooth/SettingsHolder.cpp
service-bluetooth/SettingsSerializer.cpp
+ service-bluetooth/BluetoothMessage.cpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +0 -1
@@ 1,7 1,6 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "Constants.hpp"
#include "service-bluetooth/ServiceBluetooth.hpp"
#include "service-bluetooth/BluetoothMessage.hpp"
A module-services/service-bluetooth/service-bluetooth/BluetoothMessage.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.cpp +14 -0
@@ 0,0 1,14 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BluetoothMessage.hpp"
+
+extern "C"
+{
+#include <module-bluetooth/lib/btstack/src/btstack_util.h>
+}
+
+BluetoothAddrMessage::BluetoothAddrMessage(std::string addr) : sys::DataMessage(MessageType::BluetoothAddrResult)
+{
+ sscanf_bd_addr(addr.c_str(), this->addr);
+}
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +1 -9
@@ 14,11 14,6 @@
#include <utility>
#include <vector>
-extern "C"
-{
-#include <module-bluetooth/lib/btstack/src/btstack_util.h>
-};
-
struct BluetoothStatus
{
enum class State
@@ 80,10 75,7 @@ class BluetoothAddrMessage : public sys::DataMessage
{
public:
bd_addr_t addr;
- explicit BluetoothAddrMessage(std::string addr) : sys::DataMessage(MessageType::BluetoothAddrResult)
- {
- sscanf_bd_addr(addr.c_str(), this->addr);
- };
+ explicit BluetoothAddrMessage(std::string addr);
~BluetoothAddrMessage() override = default;
};
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +19 -2
@@ 1,13 1,16 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include <Bluetooth/BluetoothWorker.hpp>
+#include "Constants.hpp"
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include "service-bluetooth/SettingsHolder.hpp"
+#include <service-db/DBServiceName.hpp>
+#include <service-audio/ServiceAudio.hpp>
+#include <module-bluetooth/Bluetooth/CommandHandler.hpp>
#include "BluetoothMessage.hpp"
#include <memory> // for unique_ptr
@@ 36,3 39,17 @@ class ServiceBluetooth : public sys::Service
private:
std::unique_ptr<BluetoothWorker> worker;
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceBluetooth>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::bluetooth;
+ manifest.dependencies = {service::name::db, service::name::audio};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +15 -0
@@ 27,6 27,7 @@
#include <vector> // for vector
#include <service-db/Settings.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
+#include <service-db/DBServiceName.hpp>
#include <cstdint>
#include <memory>
@@ 310,3 311,17 @@ class ServiceCellular : public sys::Service
void apnListChanged(const std::string &value);
bool volteOn = false;
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceCellular>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = ServiceCellular::serviceName;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +1 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ServiceDB.hpp"
@@ 11,7 11,6 @@
#include "service-db/DBSMSMessage.hpp"
#include "service-db/DBSMSTemplateMessage.hpp"
#include "service-db/DBServiceMessage.hpp"
-#include "service-db/DBServiceName.hpp"
#include "service-db/DBThreadMessage.hpp"
#include "service-db/QueryMessage.hpp"
#include "service-db/DatabaseAgent.hpp"
M module-services/service-db/ServiceDB.hpp => module-services/service-db/ServiceDB.hpp +20 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 7,6 7,9 @@
#include "agents/settings/SettingsAgent.hpp"
#include "service-db/DatabaseAgent.hpp"
#include "service-db/DBNotificationMessage.hpp"
+#include "service-db/DBServiceName.hpp"
+
+#include "service-fileindexer/Constants.hpp"
#include <Common/Query.hpp>
#include <Interface/AlarmsRecord.hpp>
@@ 91,3 94,19 @@ class ServiceDB : public sys::Service
bool StoreIntoBackup(const std::string &backupPath);
void sendUpdateNotification(db::Interface::Name interface, db::Query::Type type);
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceDB>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::db;
+#if ENABLE_FILEINDEXER_SERVICE
+ manifest.dependencies = {service::name::file_indexer.data()};
+#endif
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-db/test/test-settings/test-service-db-settings-api.cpp => module-services/service-db/test/test-settings/test-service-db-settings-api.cpp +64 -62
@@ 26,7 26,7 @@ TEST_CASE("SettingsApi")
SECTION("variable/profile/mode register/set/get/unregister")
{
- auto manager = std::make_shared<sys::SystemManager>();
+ auto manager = std::make_shared<sys::SystemManager>(std::vector<std::unique_ptr<sys::BaseServiceCreator>>{});
std::shared_ptr<settings::MyService> varWritter;
std::shared_ptr<settings::MyService> varReader;
std::shared_ptr<settings::AppTest> testVar;
@@ 38,67 38,69 @@ TEST_CASE("SettingsApi")
std::shared_ptr<settings::AppTestProfileMode> testMode;
std::shared_ptr<std::mutex> testStart;
- manager->StartSystem([manager,
- &varWritter,
- &varReader,
- &testVar,
- &profWritter,
- &profReader,
- &testProf,
- &modeWritter,
- &modeReader,
- &testMode,
- &testStart]() {
- // preliminary
- testStart = std::make_shared<std::mutex>();
- testStart->lock();
- std::cout << "start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
- auto ret = sys::SystemManager::CreateService(std::make_shared<EventManager>(service::name::evt_manager),
- manager.get());
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceDB>(), manager.get());
-
- varWritter = std::make_shared<settings::MyService>("writterVar");
- varReader = std::make_shared<settings::MyService>("readerVar");
-
- ret &= sys::SystemManager::CreateService(varWritter, manager.get());
- ret &= sys::SystemManager::CreateService(varReader, manager.get());
-
- testVar = std::make_shared<settings::AppTest>("appTest", varWritter, varReader, testStart);
- ret &= sys::SystemManager::CreateService(testVar, manager.get());
-
- profWritter = std::make_shared<settings::ServiceProfile>("writterProf");
- profReader = std::make_shared<settings::ServiceProfile>("readerProf");
-
- ret &= sys::SystemManager::CreateService(profWritter, manager.get());
- ret &= sys::SystemManager::CreateService(profReader, manager.get());
-
- testProf =
- std::make_shared<settings::AppTestProfileMode>("appTestProfile", profWritter, profReader, testStart);
- ret &= sys::SystemManager::CreateService(testProf, manager.get());
-
- modeWritter = std::make_shared<settings::ServiceMode>("writterMode");
- modeReader = std::make_shared<settings::ServiceMode>("readerMode");
-
- ret &= sys::SystemManager::CreateService(modeWritter, manager.get());
- ret &= sys::SystemManager::CreateService(modeReader, manager.get());
-
- testMode =
- std::make_shared<settings::AppTestProfileMode>("appTestMode", modeWritter, modeReader, testStart);
- ret &= sys::SystemManager::CreateService(testMode, manager.get());
-
- std::cout << "koniec start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
- testStart->unlock();
- auto msgStart = std::make_shared<settings::UTMsg::UTMsgStart>();
- manager->bus.sendUnicast(std::move(msgStart), "appTest");
-
- msgStart = std::make_shared<settings::UTMsg::UTMsgStart>();
- manager->bus.sendUnicast(std::move(msgStart), "appTestProfile");
-
- msgStart = std::make_shared<settings::UTMsg::UTMsgStart>();
- manager->bus.sendUnicast(std::move(msgStart), "appTestMode");
-
- return ret;
- });
+ manager->StartSystem(
+ nullptr,
+ [manager,
+ &varWritter,
+ &varReader,
+ &testVar,
+ &profWritter,
+ &profReader,
+ &testProf,
+ &modeWritter,
+ &modeReader,
+ &testMode,
+ &testStart]() {
+ // preliminary
+ testStart = std::make_shared<std::mutex>();
+ testStart->lock();
+ std::cout << "start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
+ auto ret = sys::SystemManager::RunService(std::make_shared<EventManager>(service::name::evt_manager),
+ manager.get());
+ ret &= sys::SystemManager::RunService(std::make_shared<ServiceDB>(), manager.get());
+
+ varWritter = std::make_shared<settings::MyService>("writterVar");
+ varReader = std::make_shared<settings::MyService>("readerVar");
+
+ ret &= sys::SystemManager::RunService(varWritter, manager.get());
+ ret &= sys::SystemManager::RunService(varReader, manager.get());
+
+ testVar = std::make_shared<settings::AppTest>("appTest", varWritter, varReader, testStart);
+ ret &= sys::SystemManager::RunService(testVar, manager.get());
+
+ profWritter = std::make_shared<settings::ServiceProfile>("writterProf");
+ profReader = std::make_shared<settings::ServiceProfile>("readerProf");
+
+ ret &= sys::SystemManager::RunService(profWritter, manager.get());
+ ret &= sys::SystemManager::RunService(profReader, manager.get());
+
+ testProf = std::make_shared<settings::AppTestProfileMode>(
+ "appTestProfile", profWritter, profReader, testStart);
+ ret &= sys::SystemManager::RunService(testProf, manager.get());
+
+ modeWritter = std::make_shared<settings::ServiceMode>("writterMode");
+ modeReader = std::make_shared<settings::ServiceMode>("readerMode");
+
+ ret &= sys::SystemManager::RunService(modeWritter, manager.get());
+ ret &= sys::SystemManager::RunService(modeReader, manager.get());
+
+ testMode =
+ std::make_shared<settings::AppTestProfileMode>("appTestMode", modeWritter, modeReader, testStart);
+ ret &= sys::SystemManager::RunService(testMode, manager.get());
+
+ std::cout << "koniec start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
+ testStart->unlock();
+ auto msgStart = std::make_shared<settings::UTMsg::UTMsgStart>();
+ manager->bus.sendUnicast(std::move(msgStart), "appTest");
+
+ msgStart = std::make_shared<settings::UTMsg::UTMsgStart>();
+ manager->bus.sendUnicast(std::move(msgStart), "appTestProfile");
+
+ msgStart = std::make_shared<settings::UTMsg::UTMsgStart>();
+ manager->bus.sendUnicast(std::move(msgStart), "appTestMode");
+
+ return ret;
+ });
// start application
cpp_freertos::Thread::StartScheduler();
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +16 -5
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,10 13,7 @@
#include "Constants.hpp"
#include "WorkerDesktop.hpp"
#include <endpoints/update/UpdateMuditaOS.hpp>
-#include <Service/Common.hpp>
-#include <Service/Message.hpp>
-#include <Service/Service.hpp>
-#include <memory>
+#include <service-db/DBServiceName.hpp>
namespace settings
{
@@ 50,3 47,17 @@ class ServiceDesktop : public sys::Service
private:
std::unique_ptr<settings::Settings> settings;
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceDesktop>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::service_desktop;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +19 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 9,6 9,9 @@
#include "EinkDisplay.hpp"
+#include <service-db/DBServiceName.hpp>
+#include <service-gui/Common.hpp>
+
#include <chrono>
#include <cstdint>
#include <string>
@@ 18,7 21,7 @@ namespace service::eink
class ServiceEink : public sys::Service
{
public:
- explicit ServiceEink(const std::string &name, std::string parent = {});
+ explicit ServiceEink(const std::string &name = service::name::eink, std::string parent = {});
sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *response) override;
sys::ReturnCodes InitHandler() override;
@@ 60,3 63,17 @@ namespace service::eink
*/
};
} // namespace service::eink
+
+namespace sys
+{
+ template <> struct ManifestTraits<service::eink::ServiceEink>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::eink;
+ manifest.dependencies = {service::name::db, service::name::gui};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +20 -2
@@ 1,8 1,10 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+#include "Constants.hpp"
+
#include <MessageType.hpp>
#include <Service/Common.hpp>
#include <Service/Message.hpp>
@@ 13,6 15,8 @@
#include <bsp/keypad_backlight/keypad_backlight.hpp>
#include <screen-light-control/ScreenLightControl.hpp>
+#include <service-db/DBServiceName.hpp>
+
#include <cstdint>
#include <memory>
#include <string>
@@ 44,7 48,7 @@ class EventManager : public sys::Service
std::unique_ptr<screen_light_control::ScreenLightControl> screenLightControl;
public:
- EventManager(const std::string &name);
+ EventManager(const std::string &name = service::name::evt_manager);
~EventManager();
sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
@@ 62,3 66,17 @@ class EventManager : public sys::Service
*/
static bool messageSetApplication(sys::Service *sender, const std::string &applicationName);
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<EventManager>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::evt_manager;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-fileindexer/Constants.hpp => module-services/service-fileindexer/Constants.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 7,4 7,4 @@
namespace service::name
{
inline constexpr std::string_view file_indexer = "FileIndexer";
-} // namespace service::name>
\ No newline at end of file
+} // namespace service::name
M module-services/service-fileindexer/ServiceFileIndexer.hpp => module-services/service-fileindexer/ServiceFileIndexer.hpp +17 -2
@@ 1,9 1,11 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <Service/Service.hpp>
+
+#include "Constants.hpp"
#include "StartupIndexer.hpp"
namespace service
@@ 12,7 14,7 @@ namespace service
class ServiceFileIndexer final : public sys::Service
{
public:
- ServiceFileIndexer(const std::string_view name);
+ ServiceFileIndexer(const std::string_view name = service::name::file_indexer);
virtual ~ServiceFileIndexer() = default;
ServiceFileIndexer(const ServiceFileIndexer &) = delete;
ServiceFileIndexer &operator=(const ServiceFileIndexer &) = delete;
@@ 30,3 32,16 @@ namespace service
};
}; // namespace service
+
+namespace sys
+{
+ template <> struct ManifestTraits<service::ServiceFileIndexer>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::file_indexer;
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-fota/FotaServiceAPI.cpp => module-services/service-fota/FotaServiceAPI.cpp +7 -7
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "service-fota/FotaMessages.hpp"
@@ 19,21 19,21 @@ namespace FotaService
{
LOG_DEBUG("FOTA - Internet Config called");
std::shared_ptr<ConfigureAPNMessage> msg = std::make_shared<ConfigureAPNMessage>(config);
- return serv->bus.sendUnicast(std::move(msg), FotaService::Service::serviceName);
+ return serv->bus.sendUnicast(std::move(msg), service::name::fota);
}
bool API::Connect(sys::Service *serv)
{
LOG_DEBUG("FOTA - Internet connection called");
auto msg = std::make_shared<ConnectMessage>();
- return serv->bus.sendUnicast(std::move(msg), FotaService::Service::serviceName);
+ return serv->bus.sendUnicast(std::move(msg), service::name::fota);
}
bool API::Disconnect(sys::Service *serv)
{
std::shared_ptr<InternetRequestMessage> msg =
std::make_shared<InternetRequestMessage>(MessageType::FotaInternetDisconnect);
- return serv->bus.sendUnicast(std::move(msg), FotaService::Service::serviceName);
+ return serv->bus.sendUnicast(std::move(msg), service::name::fota);
}
void API::HTTPGET(sys::Service *serv, const std::string &url)
@@ 42,7 42,7 @@ namespace FotaService
std::shared_ptr<HTTPRequestMessage> msg = std::make_shared<HTTPRequestMessage>();
msg->url = url;
msg->method = FotaService::HTTPMethod::GET;
- serv->bus.sendUnicast(std::move(msg), FotaService::Service::serviceName);
+ serv->bus.sendUnicast(std::move(msg), service::name::fota);
}
void API::FotaStart(sys::Service *serv, const std::string &url)
@@ 52,7 52,7 @@ namespace FotaService
msg->url = url;
- serv->bus.sendUnicast(std::move(msg), FotaService::Service::serviceName);
+ serv->bus.sendUnicast(std::move(msg), service::name::fota);
}
void API::sendRawProgress(sys::Service *serv, const std::string &rawQind)
@@ 60,7 60,7 @@ namespace FotaService
LOG_DEBUG("Fota sending Raw progress");
std::shared_ptr<FotaService::FOTARawProgress> msg = std::make_shared<FotaService::FOTARawProgress>();
msg->qindRaw = rawQind;
- serv->bus.sendUnicast(std::move(msg), FotaService::Service::serviceName);
+ serv->bus.sendUnicast(std::move(msg), service::name::fota);
}
std::string APN::toString(APN::AuthMethod authMethod)
M module-services/service-fota/ServiceFota.cpp => module-services/service-fota/ServiceFota.cpp +4 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "service-fota/FotaMessages.hpp"
@@ 34,15 34,13 @@
namespace FotaService
{
-
- const char *Service::serviceName = "ServiceFota";
const TickType_t defaultTimer = 1000;
const uint32_t QIDEACTTimeout = 40000;
const uint32_t QIACTTimeout = 150000;
const char *httpErrorCode200 = "200";
const uint32_t httpErrorCodeValue200 = 200;
- Service::Service() : sys::Service(serviceName)
+ Service::Service() : sys::Service(service::name::fota)
{
LOG_INFO("[ServiceFota] Initializing");
@@ 53,7 51,7 @@ namespace FotaService
connectionTimer->connect([&](sys::Timer &) {
std::shared_ptr<InternetRequestMessage> msg =
std::make_shared<InternetRequestMessage>(MessageType::CellularListCurrentCalls);
- bus.sendUnicast(msg, Service::serviceName);
+ bus.sendUnicast(msg, service::name::fota);
});
registerMessageHandlers();
}
@@ 598,7 596,7 @@ namespace FotaService
std::shared_ptr<sys::ResponseMessage> responseMsg;
LOG_DEBUG("%s: DataRecieve: bus:%d | message:%d",
- serviceName,
+ service::name::fota,
static_cast<int>(msgl->channel),
static_cast<int>(msgl->messageType));
return (responseMsg ? responseMsg : std::make_shared<sys::ResponseMessage>());
M module-services/service-fota/service-fota/ServiceFota.hpp => module-services/service-fota/service-fota/ServiceFota.hpp +22 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,6 13,8 @@
#include <Service/Service.hpp>
#include <service-cellular/ServiceCellular.hpp>
+#include <service-db/DBServiceName.hpp>
+
#include <cstdint>
#include <memory>
#include <sstream>
@@ 26,6 28,11 @@ namespace sys
class Timer;
} // namespace sys
+namespace service::name
+{
+ constexpr inline auto fota = "ServiceFota";
+} // namespace service::name
+
namespace FotaService
{
@@ 60,8 67,6 @@ namespace FotaService
void registerMessageHandlers();
- static const char *serviceName;
-
private:
/** Get access to data channel
*/
@@ 121,3 126,17 @@ namespace FotaService
};
} // namespace FotaService
+
+namespace sys
+{
+ template <> struct ManifestTraits<FotaService::Service>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::fota;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-gui/ServiceGUI.hpp => module-services/service-gui/ServiceGUI.hpp +19 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 9,10 9,13 @@
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
+#include <service-db/DBServiceName.hpp>
+
#include "messages/RenderingFinished.hpp"
#include "ContextPool.hpp"
#include "DrawCommandsQueue.hpp"
+#include "Common.hpp"
#include <cstdint>
#include <memory>
@@ 33,7 36,7 @@ namespace service::gui
friend WorkerGUI;
public:
- explicit ServiceGUI(const std::string &name, std::string parent = {});
+ explicit ServiceGUI(const std::string &name = service::name::gui, std::string parent = {});
~ServiceGUI() noexcept override;
sys::ReturnCodes InitHandler() override;
@@ 88,3 91,17 @@ namespace service::gui
State currentState;
};
} // namespace service::gui
+
+namespace sys
+{
+ template <> struct ManifestTraits<service::gui::ServiceGUI>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::gui;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-lwip/ServiceLwIP.cpp => module-services/service-lwip/ServiceLwIP.cpp +2 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "service-lwip/ServiceLwIP.hpp"
@@ 51,9 51,7 @@ sys::ReturnCodes message_lwip(sys::Service *app, LwIP_message::Request req)
return ret.first;
}
-const char *ServiceLwIP::serviceName = "ServiceLwIP";
-
-ServiceLwIP::ServiceLwIP() : sys::Service(serviceName)
+ServiceLwIP::ServiceLwIP() : sys::Service(service::name::lwip)
{
LOG_INFO("[ServiceLwIP] Initializing");
tcpip_init(nullptr, nullptr);
M module-services/service-lwip/service-lwip/ServiceLwIP.hpp => module-services/service-lwip/service-lwip/ServiceLwIP.hpp +22 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 8,8 8,15 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
+#include <service-db/DBServiceName.hpp>
+
#include <memory>
+namespace service::name
+{
+ constexpr inline auto lwip = "ServiceLwIP";
+} // namespace service::name
+
class LwIP_message : public sys::DataMessage
{
public:
@@ 36,7 43,18 @@ class ServiceLwIP : public sys::Service
sys::ReturnCodes InitHandler() override;
sys::ReturnCodes DeinitHandler() override;
virtual sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;
-
- private:
- static const char *serviceName;
};
+
+namespace sys
+{
+ template <> struct ManifestTraits<ServiceLwIP>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::lwip;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-services/service-time/ServiceTime.hpp => module-services/service-time/ServiceTime.hpp +17 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 6,6 6,8 @@
#include "service-time/CalendarTimeEvents.hpp"
#include "service-time/ServiceTime.hpp"
+#include <service-db/DBServiceName.hpp>
+
#include <MessageType.hpp>
#include <Service/Common.hpp>
#include <Service/Message.hpp>
@@ 41,3 43,17 @@ namespace stm
};
} /* namespace stm */
+
+namespace sys
+{
+ template <> struct ManifestTraits<stm::ServiceTime>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::name::service_time;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M module-sys/CMakeLists.txt => module-sys/CMakeLists.txt +5 -0
@@ 14,9 14,11 @@ set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/Service/Service.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Service/Timer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/SystemManager.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/DependencyGraph.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/PowerManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/CpuStatistics.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/DeviceManager.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/graph/TopologicalSort.cpp
)
@@ 67,3 69,6 @@ target_include_directories(${PROJECT_NAME}
${CMAKE_CURRENT_SOURCE_DIR}
)
+if (${ENABLE_TESTS})
+ add_subdirectory(SystemManager/tests)
+endif()
M module-sys/Service/Service.hpp => module-sys/Service/Service.hpp +2 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 7,6 7,7 @@
#include "Common.hpp" // for ReturnCodes, ServicePriority, BusChannels
#include "Mailbox.hpp" // for Mailbox
#include "Message.hpp" // for MessagePointer
+#include "ServiceManifest.hpp"
#include "thread.hpp" // for Thread
#include <algorithm> // for find, max
#include <cstdint> // for uint32_t, uint64_t
A module-sys/Service/ServiceCreator.hpp => module-sys/Service/ServiceCreator.hpp +57 -0
@@ 0,0 1,57 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "ServiceManifest.hpp"
+
+#include <memory>
+
+namespace sys
+{
+ class Service;
+
+ class BaseServiceCreator
+ {
+ public:
+ explicit BaseServiceCreator(ServiceManifest &&manifest) noexcept : manifest{std::move(manifest)}
+ {}
+ virtual ~BaseServiceCreator() noexcept = default;
+
+ [[nodiscard]] virtual std::shared_ptr<Service> create() const = 0;
+
+ [[nodiscard]] auto getName() const noexcept -> const ServiceManifest::ServiceName &
+ {
+ return manifest.name;
+ }
+
+ [[nodiscard]] auto getDependencies() const noexcept -> const std::vector<ServiceManifest::ServiceName> &
+ {
+ return manifest.dependencies;
+ }
+
+ [[nodiscard]] auto getStartTimeout() const noexcept -> ServiceManifest::Timeout
+ {
+ return manifest.timeout;
+ }
+
+ private:
+ ServiceManifest manifest;
+ };
+
+ template <typename T> class ServiceCreator : public BaseServiceCreator
+ {
+ public:
+ using BaseServiceCreator::BaseServiceCreator;
+
+ [[nodiscard]] auto create() const -> std::shared_ptr<Service> override
+ {
+ return std::make_shared<T>();
+ }
+ };
+
+ template <typename T> std::unique_ptr<BaseServiceCreator> CreatorFor() noexcept
+ {
+ return std::make_unique<ServiceCreator<T>>(ManifestOf<T>());
+ }
+} // namespace sys
A module-sys/Service/ServiceManifest.hpp => module-sys/Service/ServiceManifest.hpp +45 -0
@@ 0,0 1,45 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <chrono>
+#include <string>
+#include <vector>
+
+namespace sys
+{
+ class Service; // Forward declaration
+
+ struct ServiceManifest
+ {
+ using ServiceName = std::string;
+ using Timeout = std::chrono::milliseconds;
+ static constexpr auto DefaultTimeout = Timeout{5000};
+
+ std::vector<ServiceName> dependencies;
+ ServiceName name;
+ Timeout timeout = DefaultTimeout;
+ };
+
+ /// 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<ServiceManifest, 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() -> ServiceManifest
+ {
+ return ManifestTraits<T>::GetManifest();
+ }
+} // namespace sys
A module-sys/SystemManager/DependencyGraph.cpp => module-sys/SystemManager/DependencyGraph.cpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "DependencyGraph.hpp"
+
+#include <algorithm>
+#include <cassert>
+
+namespace sys
+{
+ namespace graph
+ {
+ Nodes nodesFrom(const std::vector<std::unique_ptr<BaseServiceCreator>> &services)
+ {
+ Nodes nodes;
+ nodes.reserve(services.size());
+ std::transform(services.begin(), services.end(), std::back_inserter(nodes), [](const auto &service) {
+ return std::ref(*service);
+ });
+ return nodes;
+ }
+ } // namespace graph
+
+ DependencyGraph::DependencyGraph(graph::Nodes nodes, std::unique_ptr<DependencySortingStrategy> &&strategy)
+ : nodes{std::move(nodes)}, strategy{std::move(strategy)}
+ {}
+
+ auto DependencyGraph::sort() const -> graph::Nodes
+ {
+ return strategy->sort(nodes);
+ }
+} // namespace sys
A module-sys/SystemManager/DependencyGraph.hpp => module-sys/SystemManager/DependencyGraph.hpp +42 -0
@@ 0,0 1,42 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "Service/ServiceCreator.hpp"
+
+#include <memory>
+#include <vector>
+
+namespace sys
+{
+ class BaseServiceCreator; // Forward declaration
+
+ namespace graph
+ {
+ using Node = std::reference_wrapper<BaseServiceCreator>;
+ using Nodes = std::vector<Node>;
+
+ Nodes nodesFrom(const std::vector<std::unique_ptr<BaseServiceCreator>> &services);
+ } // namespace graph
+
+ class DependencySortingStrategy
+ {
+ public:
+ virtual ~DependencySortingStrategy() noexcept = default;
+
+ [[nodiscard]] virtual auto sort(const graph::Nodes &nodes) -> graph::Nodes = 0;
+ };
+
+ class DependencyGraph
+ {
+ public:
+ DependencyGraph(graph::Nodes nodes, std::unique_ptr<DependencySortingStrategy> &&strategy);
+
+ [[nodiscard]] auto sort() const -> graph::Nodes;
+
+ private:
+ graph::Nodes nodes;
+ std::unique_ptr<DependencySortingStrategy> strategy;
+ };
+} // namespace sys
M module-sys/SystemManager/SystemManager.cpp => module-sys/SystemManager/SystemManager.cpp +46 -14
@@ 3,6 3,9 @@
#include "SystemManager.hpp"
+#include "DependencyGraph.hpp"
+#include "graph/TopologicalSort.hpp"
+
#include <common_data/EventStore.hpp>
#include "thread.hpp"
#include "ticks.hpp"
@@ 18,6 21,7 @@
#include <service-appmgr/model/ApplicationManager.hpp>
#include "messages/CpuFrequencyMessage.hpp"
#include "messages/DeviceRegistrationMessage.hpp"
+#include <time/ScopedTime.hpp>
const inline size_t systemManagerStack = 4096 * 2;
@@ 34,7 38,8 @@ namespace sys
this->state = state;
}
- SystemManager::SystemManager() : Service(service::name::system_manager, "", systemManagerStack)
+ SystemManager::SystemManager(std::vector<std::unique_ptr<BaseServiceCreator>> &&creators)
+ : Service(service::name::system_manager, "", systemManagerStack), systemServiceCreators{std::move(creators)}
{
// Specify list of channels which System Manager is registered to
bus.channels = {BusChannel::SystemManagerRequests};
@@ 47,12 52,7 @@ namespace sys
void SystemManager::Run()
{
-
- InitHandler();
-
- if (userInit) {
- userInit();
- }
+ initialize();
// in shutdown we need to wait till event manager tells us that it's ok to stfu
while (state == State::Running) {
@@ 103,13 103,48 @@ namespace sys
};
}
- void SystemManager::StartSystem(InitFunction init)
+ void SystemManager::initialize()
+ {
+ utils::time::Scoped timer{"Initialize"};
+ InitHandler();
+ if (systemInit) {
+ systemInit();
+ }
+
+ StartSystemServices();
+ if (userInit) {
+ userInit();
+ }
+ }
+
+ void SystemManager::StartSystemServices()
+ {
+ DependencyGraph depGraph{graph::nodesFrom(systemServiceCreators), std::make_unique<graph::TopologicalSort>()};
+ const auto &sortedServices = [&depGraph]() {
+ utils::time::Scoped timer{"DependencyGraph"};
+ return depGraph.sort();
+ }();
+
+ LOG_INFO("Order of system services initialization:");
+ for (const auto &service : sortedServices) {
+ LOG_INFO("\t> %s", service.get().getName().c_str());
+ }
+ std::for_each(sortedServices.begin(), sortedServices.end(), [this](const auto &service) {
+ const auto startTimeout = service.get().getStartTimeout().count();
+ if (const auto success = RunService(service.get().create(), this, startTimeout); !success) {
+ LOG_FATAL("Unable to start service: %s", service.get().getName().c_str());
+ }
+ });
+ }
+
+ void SystemManager::StartSystem(InitFunction sysInit, InitFunction appSpaceInit)
{
powerManager = std::make_unique<PowerManager>();
cpuStatistics = std::make_unique<CpuStatistics>();
deviceManager = std::make_unique<DeviceManager>();
- userInit = init;
+ systemInit = std::move(sysInit);
+ userInit = std::move(appSpaceInit);
// Start System manager
StartService();
@@ 157,9 192,8 @@ namespace sys
return true;
}
- bool SystemManager::CreateService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout)
+ bool SystemManager::RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout)
{
-
CriticalSection::Enter();
servicesList.push_back(service);
CriticalSection::Exit();
@@ 173,9 207,7 @@ namespace sys
if (ret.first == ReturnCodes::Success && (resp->retCode == ReturnCodes::Success)) {
return true;
}
- else {
- return false;
- }
+ return false;
}
bool SystemManager::DestroyService(const std::string &name, Service *caller, TickType_t timeout)
M module-sys/SystemManager/SystemManager.hpp => module-sys/SystemManager/SystemManager.hpp +13 -8
@@ 17,12 17,13 @@
#include "mutex.hpp"
#include "Service/Mailbox.hpp"
#include "Service/Service.hpp"
-#include "Service/Message.hpp"
+#include "Service/ServiceCreator.hpp"
#include "PowerManager.hpp"
#include "Constants.hpp"
#include "CpuStatistics.hpp"
#include "DeviceManager.hpp"
#include <chrono>
+#include <vector>
namespace sys
{
@@ 63,12 64,14 @@ namespace sys
Reboot,
} state = State::Running;
- SystemManager();
+ explicit SystemManager(std::vector<std::unique_ptr<BaseServiceCreator>> &&creators);
~SystemManager() override;
void set(enum State state);
- void StartSystem(InitFunction init);
+ void initialize();
+
+ void StartSystem(InitFunction sysInit, InitFunction appSpaceInit);
// Invoke system close procedure
static bool CloseSystem(Service *s);
@@ 79,8 82,8 @@ namespace sys
static bool ResumeService(const std::string &name, Service *caller);
- // Create new service
- static bool CreateService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
+ /// Runs a service
+ static bool RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
/// Destroy existing service
/// @note there is no fallback
@@ 113,6 116,8 @@ namespace sys
void Run() override;
+ void StartSystemServices();
+
/// Sysmgr stores list of all active services but some of them are under control of parent services.
/// Parent services ought to manage lifetime of child services hence we are sending DestroyRequests only to
/// parents.
@@ 135,9 140,10 @@ namespace sys
bool cpuStatisticsTimerInit{false};
- InitFunction userInit;
-
+ std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
std::unique_ptr<sys::Timer> cpuStatisticsTimer;
+ InitFunction userInit;
+ InitFunction systemInit;
static std::vector<std::shared_ptr<Service>> servicesList;
static cpp_freertos::MutexStandard destroyMutex;
@@ 145,7 151,6 @@ namespace sys
static std::unique_ptr<CpuStatistics> cpuStatistics;
static std::unique_ptr<DeviceManager> deviceManager;
};
-
} // namespace sys
inline const char *c_str(sys::SystemManager::State state)
A module-sys/SystemManager/doc/ServicesSynchronization.md => module-sys/SystemManager/doc/ServicesSynchronization.md +25 -0
@@ 0,0 1,25 @@
+# Services synchronization
+
+If a service has dependencies to other services, it should be started after its dependencies are started.
+
+For example, a ServiceA may be dependent on the ServiceDB. It means that the ServiceA can not be started unless the ServiceDB successfully starts.
+
+It is a part of the Services Synchronization feature to order services based on their dependencies.
+
+## Service Manifest
+
+Each service should export its manifest. The manifest may contain the following information:
+- dependencies to other services
+- start limit
+- start timeout
+- on failure strategy
+
+The System Manager needs to read the manifests to run the services in the correct order.
+
+## Synchronization algorithm
+
+The [topological sorting](https://en.wikipedia.org/wiki/Topological_sorting) algorithm may be used to build a linear ordering of services that are to be started by the System Manager.
+
+
+
+**Important note: The Dependency Graph implementation handles Directed Acyclic Graphs only.**
A module-sys/SystemManager/doc/services_synchronization.puml => module-sys/SystemManager/doc/services_synchronization.puml +30 -0
@@ 0,0 1,30 @@
+@startuml
+
+actor Driver
+participant "System Manager" as sysmgr
+participant "Dependency Graph" as graph
+participant Service as srv
+
+Driver -> sysmgr: Pass a list\nof services
+sysmgr -> graph **: create
+
+|||
+sysmgr -> graph: addServices()
+
+|||
+sysmgr -> graph: topologicalSort()
+
+|||
+activate graph
+graph --> sysmgr: sorted services
+deactivate graph
+destroy graph
+|||
+
+loop for each service in sorted services
+sysmgr -> srv: Start
+srv --> sysmgr: Confirmation
+end
+|||
+
+@enduml
A module-sys/SystemManager/graph/TopologicalSort.cpp => module-sys/SystemManager/graph/TopologicalSort.cpp +75 -0
@@ 0,0 1,75 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "TopologicalSort.hpp"
+
+#include <algorithm>
+#include <cassert>
+
+namespace sys::graph
+{
+ auto TopologicalSort::sort(const graph::Nodes &nodes) -> graph::Nodes
+ {
+ std::vector<std::string_view> sortedNames;
+ auto edges = createEdges(nodes);
+ auto visited = createVisitedMap(nodes);
+ auto layer = 1;
+ for (const auto &node : nodes) {
+ const auto &nodeName = node.get().getName();
+ if (visited[nodeName] == false) {
+ visit(nodeName, edges, visited, layer, sortedNames);
+ }
+ }
+ return prepareOutput(nodes, sortedNames);
+ }
+
+ void TopologicalSort::visit(
+ std::string_view node, Edges &edges, VisitedMap &visited, int layer, std::vector<std::string_view> &out)
+ {
+ visited[node] = true;
+ for (const auto &dependency : edges[node]) {
+ if (visited[dependency] == false) {
+ layer += 1;
+ visit(dependency, edges, visited, layer, out);
+ }
+ }
+ out.emplace_back(node);
+ }
+
+ auto TopologicalSort::createEdges(const graph::Nodes &nodes) const -> Edges
+ {
+ Edges edges;
+ for (const auto &node : nodes) {
+ const auto &nodeName = node.get().getName();
+ const auto &dependencies = node.get().getDependencies();
+ for (const auto &dependency : dependencies) {
+ edges[nodeName].push_back(dependency);
+ }
+ }
+ return edges;
+ }
+
+ auto TopologicalSort::createVisitedMap(const graph::Nodes &nodes) const -> VisitedMap
+ {
+ VisitedMap visited;
+ std::for_each(
+ nodes.begin(), nodes.end(), [&visited](const auto &node) { visited[node.get().getName()] = false; });
+ return visited;
+ }
+
+ auto TopologicalSort::prepareOutput(const graph::Nodes &nodes, const std::vector<std::string_view> &sorted) const
+ -> graph::Nodes
+ {
+ graph::Nodes output;
+ output.reserve(sorted.size());
+ for (const auto &name : sorted) {
+ const auto it = std::find_if(
+ nodes.cbegin(), nodes.cend(), [&name](const auto &node) { return node.get().getName() == name; });
+
+ // Either nodes have been modified by mistake or there's no particular dependency in the nodes container.
+ assert(it != nodes.end());
+ output.emplace_back(*it);
+ }
+ return output;
+ }
+} // namespace sys::graph
A module-sys/SystemManager/graph/TopologicalSort.hpp => module-sys/SystemManager/graph/TopologicalSort.hpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "SystemManager/DependencyGraph.hpp"
+
+#include <list>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+namespace sys::graph
+{
+ class TopologicalSort : public DependencySortingStrategy
+ {
+ public:
+ [[nodiscard]] auto sort(const graph::Nodes &nodes) -> graph::Nodes override;
+
+ private:
+ using Edges = std::unordered_map<std::string_view, std::list<std::string_view>>;
+ using VisitedMap = std::unordered_map<std::string_view, bool>;
+
+ [[nodiscard]] auto createEdges(const graph::Nodes &nodes) const -> Edges;
+ [[nodiscard]] auto createVisitedMap(const graph::Nodes &nodes) const -> VisitedMap;
+ void visit(
+ std::string_view node, Edges &edges, VisitedMap &visited, int layer, std::vector<std::string_view> &out);
+
+ [[nodiscard]] auto prepareOutput(const graph::Nodes &nodes, const std::vector<std::string_view> &sorted) const
+ -> graph::Nodes;
+ };
+} // namespace sys::graph
A module-sys/SystemManager/tests/CMakeLists.txt => module-sys/SystemManager/tests/CMakeLists.txt +9 -0
@@ 0,0 1,9 @@
+add_catch2_executable(
+ NAME
+ dependency-graph-tests
+ SRCS
+ tests-main.cpp
+ test-DependencyGraph.cpp
+ LIBS
+ module-sys
+)
A module-sys/SystemManager/tests/test-DependencyGraph.cpp => module-sys/SystemManager/tests/test-DependencyGraph.cpp +175 -0
@@ 0,0 1,175 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <catch2/catch.hpp>
+
+#include "Service/ServiceCreator.hpp"
+#include "SystemManager/DependencyGraph.hpp"
+#include "SystemManager/graph/TopologicalSort.hpp"
+
+using namespace sys;
+using graph::TopologicalSort;
+
+class MockedServiceCreator : public BaseServiceCreator
+{
+ public:
+ using BaseServiceCreator::BaseServiceCreator;
+
+ std::shared_ptr<Service> create() const override
+ {
+ return nullptr;
+ }
+};
+
+ServiceManifest createManifest(ServiceManifest::ServiceName name, std::vector<ServiceManifest::ServiceName> deps)
+{
+ ServiceManifest manifest;
+ manifest.name = std::move(name);
+ manifest.dependencies = std::move(deps);
+ return manifest;
+}
+
+TEST_CASE("Given Dependency Graph When topological sort empty graph then verify if result is empty")
+{
+ DependencyGraph graph{{}, std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ REQUIRE(sorted.empty());
+}
+
+TEST_CASE("Given Dependency Graph When topological sort without dependencies then verify order")
+{
+ std::vector<std::unique_ptr<BaseServiceCreator>> services;
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S1", {})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S2", {})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S3", {})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S4", {})));
+
+ // Graph:
+ // S1 S2 S3 S4
+ DependencyGraph graph{graph::nodesFrom(services), std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ REQUIRE(sorted[0].get().getName() == "S1");
+ REQUIRE(sorted[1].get().getName() == "S2");
+ REQUIRE(sorted[2].get().getName() == "S3");
+ REQUIRE(sorted[3].get().getName() == "S4");
+}
+
+TEST_CASE("Given Dependency Graph When topological sort simple case then verify order")
+{
+ std::vector<std::unique_ptr<BaseServiceCreator>> services;
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S1", {"S2"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S2", {"S3"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S3", {"S4"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S4", {})));
+
+ // Graph:
+ // S1 -> S2 -> S3 -> S4
+ DependencyGraph graph{graph::nodesFrom(services), std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ REQUIRE(sorted[0].get().getName() == "S4");
+ REQUIRE(sorted[1].get().getName() == "S3");
+ REQUIRE(sorted[2].get().getName() == "S2");
+ REQUIRE(sorted[3].get().getName() == "S1");
+}
+
+TEST_CASE("Given Dependency Graph When topological sort all depending on one then verify order")
+{
+ std::vector<std::unique_ptr<BaseServiceCreator>> services;
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S1", {"S2"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S2", {})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S3", {"S2"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S4", {"S2"})));
+
+ // Graph:
+ // S1 -> S2
+ // / ^
+ // S3 |
+ // S4
+ DependencyGraph graph{graph::nodesFrom(services), std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ REQUIRE(sorted[0].get().getName() == "S2");
+ REQUIRE(sorted[1].get().getName() == "S1");
+ REQUIRE(sorted[2].get().getName() == "S3");
+ REQUIRE(sorted[3].get().getName() == "S4");
+}
+
+TEST_CASE("Given Dependency Graph When topological sort advanced case then verify order 1")
+{
+ std::vector<std::unique_ptr<BaseServiceCreator>> services;
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S1", {"S2", "S3"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S2", {"S4"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S3", {"S5"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S4", {"S6"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S5", {"S6"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S6", {})));
+
+ // Graph:
+ // -> S2 -> S4 -->
+ // S1 -> S3 -> S5 -> S6
+ DependencyGraph graph{graph::nodesFrom(services), std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ REQUIRE(sorted[0].get().getName() == "S6");
+ REQUIRE(sorted[1].get().getName() == "S4");
+ REQUIRE(sorted[2].get().getName() == "S2");
+ REQUIRE(sorted[3].get().getName() == "S5");
+ REQUIRE(sorted[4].get().getName() == "S3");
+ REQUIRE(sorted[5].get().getName() == "S1");
+}
+
+TEST_CASE("Given Dependency Graph When topological sort advanced case then verify order 2")
+{
+ std::vector<std::unique_ptr<BaseServiceCreator>> services;
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S1", {"S2", "S3", "S4"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S2", {})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S3", {"S5", "S6"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S4", {"S6"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S5", {})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S6", {})));
+
+ // Graph:
+ // --> S4 ---\>
+ // / ----> S6
+ // / /
+ // S1 -> S3 -> S5
+ // \-> S2
+ DependencyGraph graph{graph::nodesFrom(services), std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ REQUIRE(sorted[0].get().getName() == "S2");
+ REQUIRE(sorted[1].get().getName() == "S5");
+ REQUIRE(sorted[2].get().getName() == "S6");
+ REQUIRE(sorted[3].get().getName() == "S3");
+ REQUIRE(sorted[4].get().getName() == "S4");
+ REQUIRE(sorted[5].get().getName() == "S1");
+}
+
+TEST_CASE("Given Dependency Graph When topological sort on directed cyclic graph then verify order")
+{
+ std::vector<std::unique_ptr<BaseServiceCreator>> services;
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S1", {"S2"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S2", {"S3"})));
+ services.push_back(std::make_unique<MockedServiceCreator>(createManifest("S3", {"S1"})));
+
+ // Graph:
+ // S1 -> S2 -> S3
+ // \---------/
+ DependencyGraph graph{graph::nodesFrom(services), std::make_unique<TopologicalSort>()};
+
+ const auto &sorted = graph.sort();
+
+ // The order is not correct. Dependency Graph doesn't handle cyclic graphs properly
+ REQUIRE(sorted[0].get().getName() == "S3");
+ REQUIRE(sorted[1].get().getName() == "S2");
+ REQUIRE(sorted[2].get().getName() == "S1");
+}
A module-sys/SystemManager/tests/tests-main.cpp => module-sys/SystemManager/tests/tests-main.cpp +5 -0
@@ 0,0 1,5 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
+#include <catch2/catch.hpp>
A services_synchronization.png => services_synchronization.png +0 -0
M source/main.cpp => source/main.cpp +57 -60
@@ 29,6 29,10 @@
#include <service-evtmgr/EventManager.hpp>
#include <service-lwip/ServiceLwIP.hpp>
#include <service-time/ServiceTime.hpp>
+#include <Service/ServiceCreator.hpp>
+#include <module-services/service-gui/ServiceGUI.hpp>
+#include <module-services/service-gui/Common.hpp>
+#include <module-services/service-eink/ServiceEink.hpp>
#include <service-fileindexer/Constants.hpp>
#include <service-fileindexer/ServiceFileIndexer.hpp>
@@ 67,103 71,96 @@ int main()
bsp::BoardInit();
- auto sysmgr = std::make_shared<sys::SystemManager>();
-
- sysmgr->StartSystem([sysmgr]() {
- /// force initialization of PhonenumberUtil because of its stack usage
- /// otherwise we would end up with an init race and PhonenumberUtil could
- /// be initiated in a task with stack not big enough to handle it
- i18n::phonenumbers::PhoneNumberUtil::GetInstance();
-
- vfs.Init();
-
- auto ret = true;
-
- ret &=
- sys::SystemManager::CreateService(std::make_shared<EventManager>(service::name::evt_manager), sysmgr.get());
+ std::vector<std::unique_ptr<sys::BaseServiceCreator>> systemServices;
+ systemServices.emplace_back(sys::CreatorFor<EventManager>());
#if ENABLE_FILEINDEXER_SERVICE
- ret &= sys::SystemManager::CreateService(
- std::make_shared<service::ServiceFileIndexer>(service::name::file_indexer), sysmgr.get());
+ systemServices.emplace_back(sys::CreatorFor<service::ServiceFileIndexer>());
#endif
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceDB>(), sysmgr.get());
-
+ systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
#if ENABLE_GSM == 0
- // For now disable pernamenlty Service cellular when there is no GSM configured
- LOG_INFO("ServiceCellular (GSM) - Disabled");
+ // For now disable permanently Service cellular when there is no GSM configured
+ LOG_INFO("ServiceCellular (GSM) - Disabled");
#else
- LOG_INFO("ServiceCellular (GSM) - Enabling");
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceAntenna>(), sysmgr.get());
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceCellular>(), sysmgr.get());
- ret &= sys::SystemManager::CreateService(std::make_shared<FotaService::Service>(), sysmgr.get());
-#endif
-
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceAudio>(), sysmgr.get());
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceBluetooth>(), sysmgr.get());
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceLwIP>(), sysmgr.get());
- ret &= sys::SystemManager::CreateService(std::make_shared<ServiceDesktop>(), sysmgr.get());
-
- ret &= sys::SystemManager::CreateService(std::make_shared<stm::ServiceTime>(), sysmgr.get());
-
- // vector with launchers to applications
- std::vector<std::unique_ptr<app::ApplicationLauncher>> applications;
+ systemServices.emplace_back(sys::CreatorFor<ServiceAntenna>());
+ systemServices.emplace_back(sys::CreatorFor<ServiceCellular>());
+ systemServices.emplace_back(sys::CreatorFor<FotaService::Service>());
+#endif
+ systemServices.emplace_back(sys::CreatorFor<ServiceAudio>());
+ systemServices.emplace_back(sys::CreatorFor<ServiceBluetooth>());
+ systemServices.emplace_back(sys::CreatorFor<ServiceLwIP>());
+ systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());
+ systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>());
+ systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>());
+ systemServices.emplace_back(sys::CreatorFor<service::gui::ServiceGUI>());
+
+ auto sysmgr = std::make_shared<sys::SystemManager>(std::move(systemServices));
+ sysmgr->StartSystem(
+ []() {
+ vfs.Init();
+ return true;
+ },
+ [sysmgr]() {
+ /// force initialization of PhonenumberUtil because of its stack usage
+ /// otherwise we would end up with an init race and PhonenumberUtil could
+ /// be initiated in a task with stack not big enough to handle it
+ i18n::phonenumbers::PhoneNumberUtil::GetInstance();
+
+ // vector with launchers to applications
+ std::vector<std::unique_ptr<app::ApplicationLauncher>> applications;
#ifdef ENABLE_APP_DESKTOP
- applications.push_back(app::CreateLauncher<app::ApplicationDesktop>(app::name_desktop, false));
+ applications.push_back(app::CreateLauncher<app::ApplicationDesktop>(app::name_desktop, false));
#endif
#ifdef ENABLE_APP_CALL
- applications.push_back(app::CreateLauncher<app::ApplicationCall>(app::name_call, false));
+ applications.push_back(app::CreateLauncher<app::ApplicationCall>(app::name_call, false));
#endif
#ifdef ENABLE_APP_SETTINGS
- applications.push_back(app::CreateLauncher<app::ApplicationSettings>(app::name_settings));
+ applications.push_back(app::CreateLauncher<app::ApplicationSettings>(app::name_settings));
#endif
#ifdef ENABLE_APP_SETTINGS_NEW
- applications.push_back(app::CreateLauncher<app::ApplicationSettingsNew>(app::name_settings_new));
+ applications.push_back(app::CreateLauncher<app::ApplicationSettingsNew>(app::name_settings_new));
#endif
#ifdef ENABLE_APP_NOTES
- applications.push_back(app::CreateLauncher<app::ApplicationNotes>(app::name_notes));
+ applications.push_back(app::CreateLauncher<app::ApplicationNotes>(app::name_notes));
#endif
#ifdef ENABLE_APP_CALLLOG
- applications.push_back(app::CreateLauncher<app::ApplicationCallLog>(app::CallLogAppStr));
+ applications.push_back(app::CreateLauncher<app::ApplicationCallLog>(app::CallLogAppStr));
#endif
#ifdef ENABLE_APP_PHONEBOOK
- applications.push_back(app::CreateLauncher<app::ApplicationPhonebook>(app::name_phonebook));
+ applications.push_back(app::CreateLauncher<app::ApplicationPhonebook>(app::name_phonebook));
#endif
#ifdef ENABLE_APP_MESSAGES
- applications.push_back(app::CreateLauncher<app::ApplicationMessages>(app::name_messages));
+ applications.push_back(app::CreateLauncher<app::ApplicationMessages>(app::name_messages));
#endif
#ifdef ENABLE_APP_SPECIAL_INPUT
- applications.push_back(app::CreateLauncher<app::ApplicationSpecialInput>(app::special_input, false));
+ applications.push_back(app::CreateLauncher<app::ApplicationSpecialInput>(app::special_input, false));
#endif
#ifdef ENABLE_APP_ANTENNA
- applications.push_back(app::CreateLauncher<app::ApplicationAntenna>(app::name_antenna));
+ applications.push_back(app::CreateLauncher<app::ApplicationAntenna>(app::name_antenna));
#endif
#ifdef ENABLE_APP_CALENDAR
- applications.push_back(app::CreateLauncher<app::ApplicationCalendar>(app::name_calendar));
+ applications.push_back(app::CreateLauncher<app::ApplicationCalendar>(app::name_calendar));
#endif
#ifdef ENABLE_APP_MUSIC_PLAYER
- applications.push_back(app::CreateLauncher<app::ApplicationMusicPlayer>(app::name_music_player));
+ applications.push_back(app::CreateLauncher<app::ApplicationMusicPlayer>(app::name_music_player));
#endif
#ifdef ENABLE_APP_MEDITATION
- applications.push_back(app::CreateLauncher<app::ApplicationMeditation>(app::name_meditation));
+ applications.push_back(app::CreateLauncher<app::ApplicationMeditation>(app::name_meditation));
#endif
#ifdef ENABLE_APP_CALCULATOR
- applications.push_back(app::CreateLauncher<app::ApplicationCalculator>(app::name_calculator));
+ applications.push_back(app::CreateLauncher<app::ApplicationCalculator>(app::name_calculator));
#endif
#ifdef ENABLE_APP_ALARM_CLOCK
- applications.push_back(app::CreateLauncher<app::ApplicationAlarmClock>(app::name_alarm_clock));
+ applications.push_back(app::CreateLauncher<app::ApplicationAlarmClock>(app::name_alarm_clock));
#endif
+ // start application manager
+ return sysmgr->RunService(
+ std::make_shared<app::manager::ApplicationManager>(
+ app::manager::ApplicationManager::ServiceName, std::move(applications), app::name_desktop),
+ sysmgr.get());
+ });
- // start application manager
- ret &= sysmgr->CreateService(
- std::make_shared<app::manager::ApplicationManager>(
- app::manager::ApplicationManager::ServiceName, std::move(applications), app::name_desktop),
- sysmgr.get());
-
- return ret;
- });
LOG_PRINTF("Launching PurePhone \n");
LOG_PRINTF("commit: %s tag: %s branch: %s\n", GIT_REV, GIT_TAG, GIT_BRANCH);
-
cpp_freertos::Thread::StartScheduler();
-
return 0;
}